import exynos 7570 bsp
authorTO21Consortium <51391510+TO21Consortium@users.noreply.github.com>
Tue, 11 Jun 2019 09:50:50 +0000 (18:50 +0900)
committerJan Altensen <info@stricted.net>
Sun, 5 Apr 2020 01:03:58 +0000 (03:03 +0200)
 * source taken from https://github.com/TO21Consortium/SGSWPlatform

Change-Id: I739426e6562aaa40b30bfd7d8e1996ef94b4bd5f

313 files changed:
Android.mk [new file with mode: 0644]
NOTICE [new file with mode: 0644]
exynos7570.mk [new file with mode: 0644]
libcamera/Android.mk [new file with mode: 0644]
libcamera/ExynosCameraConfig.h [new file with mode: 0644]
libcamera/NOTICE [new file with mode: 0644]
libcamera/SensorInfos/ExynosCamera3SensorInfo.cpp [new file with mode: 0644]
libcamera/SensorInfos/ExynosCamera3SensorInfo.h [new file with mode: 0644]
libcamera/SensorInfos/ExynosCameraSensorInfo.cpp [new file with mode: 0644]
libcamera/SensorInfos/ExynosCameraSensorInfo.h [new file with mode: 0644]
libcamera3/Android.mk [new file with mode: 0644]
libcamera3/ExynosCamera3Config.h [new file with mode: 0644]
libcamera3/ExynosCameraAvailabilityTable.h [new file with mode: 0644]
libcamera3/ExynosCameraConfig.h [new file with mode: 0644]
libcameraInterface/Android.mk [new file with mode: 0644]
libcamera_external/Android.mk [new file with mode: 0644]
libcamera_external/model/include/SecCameraHardware-default.h [new file with mode: 0644]
libcamera_external/model/include/SecCameraHardware-model.h [new file with mode: 0644]
libcamera_external/model/include/SecCameraHardware-swatch.h [new file with mode: 0644]
libdisplaymodule/Android.mk [new file with mode: 0644]
libdisplaymodule/ExynosDisplayResourceManagerModule.cpp [new file with mode: 0644]
libdisplaymodule/ExynosDisplayResourceManagerModule.h [new file with mode: 0644]
libdisplaymodule/ExynosPrimaryDisplay.cpp [new file with mode: 0644]
libdisplaymodule/ExynosPrimaryDisplay.h [new file with mode: 0644]
libdisplaymodule/ExynosSecondaryDisplayModule.cpp [new file with mode: 0644]
libdisplaymodule/ExynosSecondaryDisplayModule.h [new file with mode: 0644]
libdisplaymodule/NOTICE [new file with mode: 0644]
libgatekeeper/Android.mk [new file with mode: 0644]
libgatekeeper/exynos_gatekeeper.cpp [new file with mode: 0644]
libgatekeeper/include/password_handle.h [new file with mode: 0644]
libgatekeeper/include/tci.h [new file with mode: 0644]
libgatekeeper/include/tlTeeGatekeeper_Api.h [new file with mode: 0644]
libgatekeeper/include/tlcTeeGatekeeper_if.h [new file with mode: 0644]
libgatekeeper/include/tlcTeeGatekeeper_log.h [new file with mode: 0644]
libgatekeeper/tlcTeeGatekeeper_if.cpp [new file with mode: 0644]
libhdmimodule/Android.mk [new file with mode: 0644]
libhdmimodule/ExynosExternalDisplayModule.cpp [new file with mode: 0644]
libhdmimodule/ExynosExternalDisplayModule.h [new file with mode: 0644]
libhdmimodule/NOTICE [new file with mode: 0644]
libhwcmodule/ExynosHWCModule.h [new file with mode: 0644]
libhwcutilsmodule/Android.mk [new file with mode: 0644]
libhwcutilsmodule/ExynosMPPModule.cpp [new file with mode: 0644]
libhwcutilsmodule/ExynosMPPModule.h [new file with mode: 0644]
libhwcutilsmodule/NOTICE [new file with mode: 0644]
libkeymaster/Android.mk [new file with mode: 0644]
libkeymaster/ver0/NOTICE [new file with mode: 0644]
libkeymaster/ver0/buildTag.h [new file with mode: 0644]
libkeymaster/ver0/keymaster_mobicore.cpp [new file with mode: 0644]
libkeymaster/ver0/tci.h [new file with mode: 0644]
libkeymaster/ver0/tlTeeKeymaster_Api.h [new file with mode: 0644]
libkeymaster/ver0/tlTeeKeymaster_log.h [new file with mode: 0644]
libkeymaster/ver0/tlcTeeKeymaster_if.c [new file with mode: 0644]
libkeymaster/ver0/tlcTeeKeymaster_if.h [new file with mode: 0644]
libkeymaster/ver1/NOTICE [new file with mode: 0644]
libkeymaster/ver1/include/km_encodings.h [new file with mode: 0644]
libkeymaster/ver1/include/km_shared_util.h [new file with mode: 0644]
libkeymaster/ver1/include/km_util.h [new file with mode: 0644]
libkeymaster/ver1/include/log.h [new file with mode: 0644]
libkeymaster/ver1/include/module.h [new file with mode: 0644]
libkeymaster/ver1/include/serialization.h [new file with mode: 0644]
libkeymaster/ver1/include/tci.h [new file with mode: 0644]
libkeymaster/ver1/include/tee_keymaster_device.h [new file with mode: 0644]
libkeymaster/ver1/include/tlTeeKeymaster_Api.h [new file with mode: 0644]
libkeymaster/ver1/include/tlcTeeKeymasterM_if.h [new file with mode: 0644]
libkeymaster/ver1/include/trustonic_tee_keymaster_impl.h [new file with mode: 0644]
libkeymaster/ver1/src/buildTag.h [new file with mode: 0644]
libkeymaster/ver1/src/km_encodings.cpp [new file with mode: 0644]
libkeymaster/ver1/src/km_shared_util.cpp [new file with mode: 0644]
libkeymaster/ver1/src/km_util.cpp [new file with mode: 0644]
libkeymaster/ver1/src/module.c [new file with mode: 0644]
libkeymaster/ver1/src/serialization.cpp [new file with mode: 0644]
libkeymaster/ver1/src/tee_keymaster_device.cpp [new file with mode: 0644]
libkeymaster/ver1/src/tlcTeeKeymaster_if.cpp [new file with mode: 0644]
libkeymaster/ver1/src/trustonic_tee_keymaster_impl.cpp [new file with mode: 0644]
libkeymaster/ver1/test/testTeeKeymaster.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_aes.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_aes.h [new file with mode: 0644]
libkeymaster/ver1/test/test_km_ec.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_ec.h [new file with mode: 0644]
libkeymaster/ver1/test/test_km_hmac.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_hmac.h [new file with mode: 0644]
libkeymaster/ver1/test/test_km_restrictions.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_restrictions.h [new file with mode: 0644]
libkeymaster/ver1/test/test_km_rsa.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_rsa.h [new file with mode: 0644]
libkeymaster/ver1/test/test_km_util.cpp [new file with mode: 0644]
libkeymaster/ver1/test/test_km_util.h [new file with mode: 0644]
libvirtualdisplaymodule/Android.mk [new file with mode: 0644]
libvirtualdisplaymodule/ExynosVirtualDisplayModule.cpp [new file with mode: 0644]
libvirtualdisplaymodule/ExynosVirtualDisplayModule.h [new file with mode: 0644]
libvirtualdisplaymodule/NOTICE [new file with mode: 0644]
mobicore/Android.mk [new file with mode: 0644]
mobicore/ClientLib/Android.mk [new file with mode: 0644]
mobicore/ClientLib/MODULE_LICENSE_BSD [new file with mode: 0644]
mobicore/ClientLib/NOTICE [new file with mode: 0644]
mobicore/ClientLib/include/GP/tee_client_api.h [new file with mode: 0644]
mobicore/ClientLib/include/GP/tee_client_api_imp.h [new file with mode: 0644]
mobicore/ClientLib/include/GP/tee_client_error.h [new file with mode: 0644]
mobicore/ClientLib/include/GP/tee_client_types.h [new file with mode: 0644]
mobicore/ClientLib/include/GpTci.h [new file with mode: 0644]
mobicore/ClientLib/include/Mci/mcimcp.h [new file with mode: 0644]
mobicore/ClientLib/include/Mci/mcinq.h [new file with mode: 0644]
mobicore/ClientLib/include/MobiCoreDriverApi.h [new file with mode: 0644]
mobicore/ClientLib/include/log.h [new file with mode: 0644]
mobicore/ClientLib/include/mcContainer.h [new file with mode: 0644]
mobicore/ClientLib/include/mcDriverId.h [new file with mode: 0644]
mobicore/ClientLib/include/mcLoadFormat.h [new file with mode: 0644]
mobicore/ClientLib/include/mcRootid.h [new file with mode: 0644]
mobicore/ClientLib/include/mcSo.h [new file with mode: 0644]
mobicore/ClientLib/include/mcSpid.h [new file with mode: 0644]
mobicore/ClientLib/include/mcSuid.h [new file with mode: 0644]
mobicore/ClientLib/include/mcUuid.h [new file with mode: 0644]
mobicore/ClientLib/include/mcVersionHelper.h [new file with mode: 0644]
mobicore/ClientLib/include/mcVersionInfo.h [new file with mode: 0644]
mobicore/ClientLib/include/proxy_server.h [new file with mode: 0644]
mobicore/ClientLib/include/uuid_attestation.h [new file with mode: 0644]
mobicore/ClientLib/src/buildTag.h [new file with mode: 0644]
mobicore/ClientLib/src/common_client.cpp [new file with mode: 0644]
mobicore/ClientLib/src/common_client.h [new file with mode: 0644]
mobicore/ClientLib/src/driver_client.cpp [new file with mode: 0644]
mobicore/ClientLib/src/driver_client.h [new file with mode: 0644]
mobicore/ClientLib/src/iclient.h [new file with mode: 0644]
mobicore/ClientLib/src/mc.pb.cpp [new file with mode: 0644]
mobicore/ClientLib/src/mc.pb.h [new file with mode: 0644]
mobicore/ClientLib/src/mc_client_api.cpp [new file with mode: 0644]
mobicore/ClientLib/src/mc_user.h [new file with mode: 0644]
mobicore/ClientLib/src/proxy_client.cpp [new file with mode: 0644]
mobicore/ClientLib/src/proxy_client.h [new file with mode: 0644]
mobicore/ClientLib/src/proxy_common.h [new file with mode: 0644]
mobicore/ClientLib/src/proxy_server.cpp [new file with mode: 0644]
mobicore/ClientLib/src/tee_client_api.cpp [new file with mode: 0644]
mobicore/Daemon/Android.mk [new file with mode: 0644]
mobicore/Daemon/MODULE_LICENSE_BSD [new file with mode: 0644]
mobicore/Daemon/NOTICE [new file with mode: 0644]
mobicore/Daemon/include/MobiCoreRegistry.h [new file with mode: 0644]
mobicore/Daemon/src/CThread.cpp [new file with mode: 0644]
mobicore/Daemon/src/CThread.h [new file with mode: 0644]
mobicore/Daemon/src/Connection.cpp [new file with mode: 0644]
mobicore/Daemon/src/Connection.h [new file with mode: 0644]
mobicore/Daemon/src/ConnectionHandler.h [new file with mode: 0644]
mobicore/Daemon/src/FSD2.cpp [new file with mode: 0644]
mobicore/Daemon/src/FSD2.h [new file with mode: 0644]
mobicore/Daemon/src/MobiCoreDriverCmd.h [new file with mode: 0644]
mobicore/Daemon/src/MobiCoreDriverDaemon.cpp [new file with mode: 0644]
mobicore/Daemon/src/MobiCoreDriverDaemon.h [new file with mode: 0644]
mobicore/Daemon/src/PrivateRegistry.cpp [new file with mode: 0644]
mobicore/Daemon/src/PrivateRegistry.h [new file with mode: 0644]
mobicore/Daemon/src/Registry.cpp [new file with mode: 0644]
mobicore/Daemon/src/SecureWorld.cpp [new file with mode: 0644]
mobicore/Daemon/src/SecureWorld.h [new file with mode: 0644]
mobicore/Daemon/src/Server.cpp [new file with mode: 0644]
mobicore/Daemon/src/Server.h [new file with mode: 0644]
mobicore/Daemon/src/buildTag.h [new file with mode: 0644]
mobicore/Daemon/src/drSecureFS_Api.h [new file with mode: 0644]
mobicore/Daemon/src/mcVersion.h [new file with mode: 0644]
mobicore/Daemon/src/mc_admin.h [new file with mode: 0644]
mobicore/Daemon/src/mc_user.h [new file with mode: 0644]
mobicore/Daemon/src/service_delegation_protocol.h [new file with mode: 0644]
mobicore/Daemon/src/sfs_error.h [new file with mode: 0644]
mobicore/Daemon/src/sfs_type.h [new file with mode: 0644]
mobicore/Daemon/src/sth2ProxyApi.h [new file with mode: 0644]
mobicore/TuiService/Android.mk [new file with mode: 0644]
mobicore/TuiService/AndroidManifest.xml [new file with mode: 0644]
mobicore/TuiService/NOTICE [new file with mode: 0644]
mobicore/TuiService/ant.properties [new file with mode: 0644]
mobicore/TuiService/build.xml [new file with mode: 0644]
mobicore/TuiService/google_certificate.keystore [new file with mode: 0644]
mobicore/TuiService/jni/tlcTui.cpp [new file with mode: 0644]
mobicore/TuiService/jni/tlcTui.h [new file with mode: 0644]
mobicore/TuiService/jni/tlcTuiJni.cpp [new file with mode: 0644]
mobicore/TuiService/jni/tlcTuiJni.h [new file with mode: 0644]
mobicore/TuiService/jni/tui_ioctl.h [new file with mode: 0644]
mobicore/TuiService/proguard-project.txt [new file with mode: 0644]
mobicore/TuiService/project.properties [new file with mode: 0644]
mobicore/TuiService/res/drawable-hdpi/sym_def_app_icon.png [new file with mode: 0644]
mobicore/TuiService/res/drawable-ldpi/sym_def_app_icon.png [new file with mode: 0644]
mobicore/TuiService/res/drawable-mdpi/sym_def_app_icon.png [new file with mode: 0644]
mobicore/TuiService/res/drawable-xhdpi/sym_def_app_icon.png [new file with mode: 0644]
mobicore/TuiService/res/drawable-xxhdpi/sym_def_app_icon.png [new file with mode: 0644]
mobicore/TuiService/res/layout/activity_tui.xml [new file with mode: 0644]
mobicore/TuiService/res/menu/tui_manager.xml [new file with mode: 0644]
mobicore/TuiService/res/values-v11/styles.xml [new file with mode: 0644]
mobicore/TuiService/res/values-v14/styles.xml [new file with mode: 0644]
mobicore/TuiService/res/values/attrs.xml [new file with mode: 0644]
mobicore/TuiService/res/values/colors.xml [new file with mode: 0644]
mobicore/TuiService/res/values/dimens.xml [new file with mode: 0644]
mobicore/TuiService/res/values/strings.xml [new file with mode: 0644]
mobicore/TuiService/res/values/styles.xml [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiapi/TUI_Event.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiapi/TUI_EventData.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiapi/TUI_EventType.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiservice/BuildTag.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiservice/TuiActivity.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiservice/TuiService.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiservice/TuiServiceAutoStart.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/tuiservice/TuiTlcWrapper.java [new file with mode: 0644]
mobicore/TuiService/src/com/trustonic/util/tLog.java [new file with mode: 0644]
mobicore/rootpa/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/AndroidManifest.xml [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/NOTICE [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/ant.properties [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/build.xml [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/generateCheaders.sh [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpBase.cpp [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpBase.h [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpCommands.cpp [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpCommands.h [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpResponses.cpp [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpResponses.h [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/JniHelpers.cpp [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/JniHelpers.h [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/NOTICE [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/McStub/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/jni/McStub/NOTICE [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/proguard-project.txt [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/project.properties [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/res/values/strings.xml [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/res/values/version.xml [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.class [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/BaseService.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/Log.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/OemService.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/ProvisioningService.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/AndroidManifest.xml [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/NOTICE [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/ant.properties [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/build.xml [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/proguard-project.txt [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/project.properties [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/AbstractEnumParcel.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/BooleanResult.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/BooleanResult.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpCommand.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpCommand.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpMsg.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpResponse.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpResponse.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CommandResult.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CommandResult.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/IfcVersion.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAOemIfc.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAProvisioningIntents.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAServiceIfc.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerState.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStateParcel.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStateParcel.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStructure.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStructure.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPID.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPID.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SUID.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SUID.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainer.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainer.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerState.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerStateParcel.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerStateParcel.java [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/Version.aidl [new file with mode: 0644]
mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/Version.java [new file with mode: 0644]
mobicore/rootpa/Code/CMakeLists.txt [new file with mode: 0644]
mobicore/rootpa/Code/Common/Android.mk [new file with mode: 0644]
mobicore/rootpa/Code/Common/NOTICE [new file with mode: 0644]
mobicore/rootpa/Code/Common/README-Android.txt [new file with mode: 0644]
mobicore/rootpa/Code/Common/base64.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/base64.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/cacerts.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/commandhandler.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/contentmanager.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/contentmanager.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/enrollmentservicexmlschema.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/include/logging.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/include/provisioningagent.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/include/rootpa.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/include/rootpaErrors.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/include/version.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/include/wrapper.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/pacmp3.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/pacmp3.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/pacmtl.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/pacmtl.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/provisioningengine.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/provisioningengine.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/registry.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/registry.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/seclient.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/seclient.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/tools.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/trustletchannel.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/trustletchannel.h [new file with mode: 0644]
mobicore/rootpa/Code/Common/xmlmessagehandler.c [new file with mode: 0644]
mobicore/rootpa/Code/Common/xmlmessagehandler.h [new file with mode: 0644]
mobicore/tlcm/Android.mk [new file with mode: 0644]
mobicore/tlcm/NOTICE [new file with mode: 0644]
mobicore/tlcm/TlCm/2.0/cmp.h [new file with mode: 0644]
mobicore/tlcm/TlCm/2.0/tlCmApi.h [new file with mode: 0644]
mobicore/tlcm/TlCm/3.0/cmp.h [new file with mode: 0644]
mobicore/tlcm/TlCm/3.0/cmpMap.h [new file with mode: 0644]
mobicore/tlcm/TlCm/3.0/tlCmApi.h [new file with mode: 0644]
mobicore/tlcm/TlCm/cmpCommon.h [new file with mode: 0644]
mobicore/tlcm/TlCm/tlCmApiCommon.h [new file with mode: 0644]
mobicore/tlcm/TlCm/tlCmError.h [new file with mode: 0644]
mobicore/tlcm/TlCm/tlCmUuid.h [new file with mode: 0644]
mobicore/tlcm/TlCm/version.h [new file with mode: 0644]
mobicore/tlcm/version.md5 [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..0707270
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+ifeq ($(TARGET_SOC), exynos7570)
+exynos7570_dirs := \
+       libgatekeeper \
+       libkeymaster \
+
+ifeq ($(BOARD_BACK_CAMERA_USES_EXTERNAL_CAMERA), true)
+exynos7570_dirs += \
+       libcamera_external
+else ifeq ($(BOARD_FRONT_CAMERA_USES_EXTERNAL_CAMERA), true)
+exynos7570_dirs += \
+       libcamera_external
+else
+exynos7570_dirs += \
+       libcamera \
+       libcamera3 \
+       libcameraInterface
+endif
+
+include $(call all-named-subdir-makefiles,$(exynos7570_dirs))
+
+endif
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..c1c71a2
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2014, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/exynos7570.mk b/exynos7570.mk
new file mode 100644 (file)
index 0000000..d505c81
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# video codecs
+PRODUCT_PACKAGES := \
+       libOMX.Exynos.MPEG4.Decoder \
+       libOMX.Exynos.AVC.Decoder \
+       libOMX.Exynos.WMV.Decoder \
+       libOMX.Exynos.VP8.Decoder \
+       libOMX.Exynos.HEVC.Decoder \
+       libOMX.Exynos.MPEG4.Encoder \
+       libOMX.Exynos.AVC.Encoder \
+       libOMX.Exynos.VP8.Encoder \
+       libOMX.Exynos.HEVC.Encoder
+
+# stagefright and device specific modules
+PRODUCT_PACKAGES += \
+       libstagefrighthw \
+       libExynosOMX_Core \
+       libExynosOMX_Resourcemanager
diff --git a/libcamera/Android.mk b/libcamera/Android.mk
new file mode 100644 (file)
index 0000000..15b6640
--- /dev/null
@@ -0,0 +1,151 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+#################
+# libexynoscamera
+
+include $(CLEAR_VARS)
+
+######## System LSI ONLY ########
+BOARD_CAMERA_GED_FEATURE := true
+#################################
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware libui
+LOCAL_SHARED_LIBRARIES += libexynosutils libhwjpeg libexynosv4l2 libexynosgscaler libion libcsc
+LOCAL_SHARED_LIBRARIES += libexpat libc++
+LOCAL_SHARED_LIBRARIES += libpower
+LOCAL_SHARED_LIBRARIES += libgui
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+else
+LOCAL_SHARED_LIBRARIES += libsecnativefeature
+LOCAL_SHARED_LIBRARIES += libliveframework
+endif
+
+LOCAL_CFLAGS += -DGAIA_FW_BETA
+LOCAL_CFLAGS += -DMAIN_CAMERA_SENSOR_NAME=$(BOARD_BACK_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DFRONT_CAMERA_SENSOR_NAME=$(BOARD_FRONT_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DUSE_CAMERA_ESD_RESET
+LOCAL_CFLAGS += -DBACK_ROTATION=$(BOARD_BACK_CAMERA_ROTATION)
+LOCAL_CFLAGS += -DFRONT_ROTATION=$(BOARD_FRONT_CAMERA_ROTATION)
+ifeq ($(TARGET_BOOTLOADER_BOARD_NAME), universal7570)
+#LOCAL_CFLAGS += -DUNIVERSAL_CAMERA
+endif
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_CFLAGS += -DCAMERA_GED_FEATURE
+endif
+
+LOCAL_CFLAGS += -D$(shell echo $(project_camera) | tr a-z A-Z)_CAMERA
+
+LOCAL_C_INCLUDES += \
+       $(LOCAL_PATH)/../include \
+       $(LOCAL_PATH)/../libcamera \
+       $(LOCAL_PATH)/../libcamera/SensorInfos \
+       $(TOP)/system/media/camera/include \
+       $(TOP)/system/core/libion/include \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx/hal1 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/SensorInfos \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Pipes2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/MCPipes \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Activities \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Buffers \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Ged \
+       $(TOP)/hardware/samsung_slsi/exynos/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/libcamera \
+       $(TOP)/hardware/samsung_slsi/exynos7570/libcamera \
+       $(TOP)/hardware/libhardware_legacy/include/hardware_legacy \
+       $(TOP)/vendor/samsung/feature/CscFeature/libsecnativefeature \
+       $(TOP)/bionic \
+       $(TOP)/external/expat/lib \
+       $(TOP)/external/libcxx/include \
+       $(TOP)/frameworks/native/include \
+       $(TOP)/hardware/camera/UniPlugin/include
+
+ifneq ($(LOCAL_PROJECT_DIR),)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libcameraSec/$(LOCAL_PROJECT_DIR)
+else
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libcamera/SensorInfos
+endif
+
+LOCAL_SRC_FILES:= \
+       ../../exynos/libcamera/common_v2/ExynosCameraFrame.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraMemory.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraFrameManager.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraUtils.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraNode.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraNodeJpegHAL.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraFrameSelector.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCamera1MetadataConverter.cpp \
+       ../../exynos/libcamera/common_v2/SensorInfos/ExynosCameraSensorInfoBase.cpp \
+       ../../exynos/libcamera/common_v2/SensorInfos/ExynosCameraSensorInfo2P8.cpp \
+       ../../exynos/libcamera/common_v2/MCPipes/ExynosCameraMCPipe.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipe.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeFlite.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeVRA.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeGSC.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeJpeg.cpp \
+       ../../exynos/libcamera/common_v2/Buffers/ExynosCameraBufferManager.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityBase.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityAutofocus.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityFlash.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivitySpecialCapture.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityUCTL.cpp \
+       ../../exynos/libcamera/common_v2/Ged/ExynosCameraActivityAutofocusVendor.cpp \
+       ../../exynos/libcamera/common_v2/Ged/ExynosCameraActivityFlashVendor.cpp \
+       ../../exynos/libcamera/common_v2/Ged/ExynosCameraFrameSelectorVendor.cpp \
+       ../../exynos/libcamera/34xx/ExynosCameraUtilsModule.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraSizeControl.cpp \
+       ../../exynos/libcamera/34xx/ExynosCameraActivityControl.cpp\
+       ../../exynos/libcamera/34xx/ExynosCameraScalableSensor.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCamera.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCamera1Parameters.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactory.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactoryPreview.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactory3aaIspM2M.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactory3aaIspM2MTpu.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactory3aaIspOtf.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactory3aaIspOtfTpu.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameReprocessingFactory.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameReprocessingFactoryNV21.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactoryVision.cpp \
+       ../../exynos/libcamera/34xx/hal1/ExynosCameraFrameFactoryFront.cpp \
+       ../../exynos/libcamera/34xx/hal1/Ged/ExynosCameraVendor.cpp \
+       ../../exynos/libcamera/34xx/hal1/Ged/ExynosCamera1ParametersVendor.cpp
+
+ifneq ($(LOCAL_PROJECT_DIR),)
+LOCAL_SRC_FILES += ../libcameraSec/$(LOCAL_PROJECT_DIR)/ExynosCameraSensorInfo.cpp
+else
+LOCAL_SRC_FILES += ../libcamera/SensorInfos/ExynosCameraSensorInfo.cpp
+endif
+
+$(foreach file,$(LOCAL_SRC_FILES),$(shell touch '$(LOCAL_PATH)/$(file)'))
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libexynoscamera
+
+include $(TOP)/hardware/samsung_slsi/exynos/BoardConfigCFlags.mk
+include $(BUILD_SHARED_LIBRARY)
+
+$(warning #####################################)
+$(warning ########    libcamera 1.0    ########)
+$(warning #####################################)
diff --git a/libcamera/ExynosCameraConfig.h b/libcamera/ExynosCameraConfig.h
new file mode 100644 (file)
index 0000000..9717a69
--- /dev/null
@@ -0,0 +1,772 @@
+/*
+ * Copyright 2015, Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed toggle an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      ExynosCameraConfig.h
+ * \brief     hearder file for ExynosCameraConfig
+ * \author    Pilsun Jang(pilsun.jang@samsung.com)
+ * \date      2013/7/15
+ *
+ */
+
+#ifndef EXYNOS_CAMERA_CONFIG_H__
+#define EXYNOS_CAMERA_CONFIG_H__
+
+#include "ExynosCameraCommonEnum.h"
+#include "ExynosCameraCommonDefine.h"
+
+/* It will be replaced by TN */
+#ifdef CAMERA_GED_FEATURE
+#else
+#include "SecCameraConfig-common.h"
+#endif /* CAMERA_GED_FEATURE */
+
+#define SMDK7870
+
+#ifndef USE_VENDOR_SPECIFIC_CONFIG_HEADER
+
+#define MONITOR_LOG_SYNC
+#define MONITOR_LOG_SYNC_INTERVAL 100
+
+#define USE_HAL3_2_METADATA_INTERFACE
+#define SUPPORT_HAL3_3_METADATA
+
+#define USE_NEW_NOISE_REDUCTION_ALGORITHM
+
+/* for universal GED */
+#if UNIVERSAL_CAMERA
+/* #define SAMSUNG_COMPANION */
+#endif
+
+#ifdef SAMSUNG_COMPANION
+#define MAIN_CAMERA_USE_SAMSUNG_COMPANION   (false)
+#define FRONT_CAMERA_USE_SAMSUNG_COMPANION  (false)
+#endif
+
+#include <math.h>
+
+/************************************************/
+#ifdef CAMERA_GED_FEATURE
+#else
+#define SUPPORT_X8_ZOOM
+#endif
+
+#define USE_SUBDIVIDED_EV
+
+/* #define DEBUG_RAWDUMP */
+/************************************************/
+
+
+#define EFFECT_VALUE_VERSION_2_0
+
+#define LCD_SIZE_DEFAULT                (0)
+#define LCD_SIZE_800_480                (1)
+#define LCD_SIZE_1280_720               (2)
+#define LCD_SIZE_1920_1080              (3)
+#define LCD_SIZE_2560_1440              (4)
+#define CAMERA_LCD_SIZE                 LCD_SIZE_1280_720
+
+/* #define LIMIT_SCP_SIZE_UNTIL_FHD_ON_CAPTURE */   /* Even if LCD is bigger than FHD, limit scp size until FHD on capture preview  */
+#define LIMIT_SCP_SIZE_UNTIL_FHD_ON_RECORDING /* Even if LCD is bigger than FHD, limit scp size until FHD on recording preview*/
+
+#define CAMERA_BCROP_ALIGN              (16)
+#define CAMERA_ISP_ALIGN                (8)
+#define CAMERA_MCSC_ALIGN               (2)
+#define CAMERA_MAGIC_ALIGN              (16)
+#define CAMERA_16PX_ALIGN               (16)
+/* This value for GSC alignment refer to "csc.h" */
+#define GSCALER_IMG_ALIGN               (16)
+
+#define SCALER_MAX_SCALE_UP_RATIO       (8)
+
+#define INITIAL_SKIP_FRAME              (8)
+#define VISION_SKIP_FRAME               (4)
+#define EFFECT_SKIP_FRAME               (1)
+#define SMART_STAY_SKIP_COMPENSATION    (1)
+#define USE_GRALLOC_REUSE_SUPPORT
+#define USE_GRALLOC_BUFFER_COLLECTOR
+
+/* Functions tobe enable */
+#define START_PICTURE_THREAD
+/* #define SET_SETFILE_BY_SHOT */
+#define USE_FRAMEMANAGER
+#ifdef USE_FRAMEMANAGER
+#define USE_FRAME_REFERENCE_COUNT
+#else
+#endif
+
+#define SET_SETFILE_BY_SET_CTRL
+#ifdef SET_SETFILE_BY_SET_CTRL
+#define SET_SETFILE_BY_SET_CTRL_3AA_ISP (false)
+#define SET_SETFILE_BY_SET_CTRL_3AA     (false)
+#define SET_SETFILE_BY_SET_CTRL_ISP     (true)
+#define SET_SETFILE_BY_SET_CTRL_SCP     (false)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+#define RESERVED_MEMORY_ENABLE
+#endif
+
+#define RESERVED_BUFFER_COUNT_MAX       (0)
+
+/* #define USE_BNS_PREVIEW */ /* use BNS on capture scenario. this change LUT size */
+
+/* #define USE_BNS_RECORDING */
+/* #define USE_BDS_RECORDING */ /* use bds on recording scenario. this change LUT size */
+
+/* #define USE_BNS_DUAL_PREVIEW */ /* use bds on recording scenario. this change LUT size */
+/* #define USE_BNS_DUAL_RECORDING */ /* use bds on recording scenario. this change LUT size */
+
+/* #define USE_UHD_RECORDING */
+/* #define USE_WQHD_RECORDING */
+/* #define FPS_CHECK */
+#define FIRST_PREVIEW_TIME_CHECK /* to get time startPreview() ~ first preview frame q to hwc */
+#define USE_FD_AE
+#define FD_ROTATION                     (true)
+#define HDR_DELAY                       (1)
+/* #define USE_FRONT_PREVIEW_DRC */
+
+#define CAMERA_PREVIEW_EXPOSURE_TIME_LIMIT (100000)
+#define CAMERA_EXPOSURE_TIME_MAX           (500000)
+
+#define BURST_CAPTURE                   (true)
+#ifdef BURST_CAPTURE
+enum {
+    BURST_SAVE_PHONE = 0,
+    BURST_SAVE_SDCARD,
+    BURST_SAVE_CALLBACK,
+};
+
+#define DEFAULT_BURST_SAVE              (BURST_SAVE_CALLBACK)
+#define BURST_SHUTTER_PREPICTURE        (0)
+#define BURST_SHUTTER_PREPICTURE_DONE   (1)
+#define BURST_SHUTTER_JPEGCB            (2)
+#endif
+
+#define SHOT_RECOVERY                   (true)
+#define SHOT_RECOVERY_ONEBYONE          (true)
+#ifdef SHOT_RECOVERY
+#define SHOT_RECOVERY_COUNT             (0)
+#else
+#define SHOT_RECOVERY_COUNT             (0)
+#endif
+
+#define FRAME_SKIP_COUNT_RECORDING      (1)
+#define FRAME_SKIP_COUNT_PREVIEW        (0)
+#define FRAME_SKIP_COUNT_PREVIEW_FRONT  (3)
+
+#ifdef CAMERA_GED_FEATURE
+#define USE_ADAPTIVE_CSC_RECORDING      (true)
+#else
+#define USE_ADAPTIVE_CSC_RECORDING      (true)
+#endif
+
+#define SUPPORT_BACK_HW_VDIS            (false)
+#define SUPPORT_FRONT_HW_VDIS           (false)
+
+#define HW_VDIS_W_RATIO                 (1.2f)
+#define HW_VDIS_H_RATIO                 (1.2f)
+
+#ifdef CAMERA_GED_FEATURE
+#define USE_HIGHSPEED_RECORDING         (false)
+#else
+#define USE_HIGHSPEED_RECORDING         (true)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#define USE_FASTEN_AE_STABLE            (false)
+#else
+#define USE_FASTEN_AE_STABLE            (true)
+#endif
+
+// fastenAE size will get by getFastenAeStableBcropSize()
+/*
+#define FASTEN_AE_WIDTH                 (1472)
+#define FASTEN_AE_HEIGHT                (828)
+*/
+#define FASTEN_AE_FPS                   (120)
+#define FASTEN_AE_FPS_FRONT             (112)
+#define DEFAULT_BINNING_RATIO           (1)
+
+#ifdef USE_BNS_PREVIEW
+#define DEFAULT_BNS_RATIO               (1)
+#else
+#define DEFAULT_BNS_RATIO               (1)
+#endif
+
+#define USE_JPEG_HWFC                   (true)
+
+#define USE_PURE_BAYER_REPROCESSING                    (false)
+#define USE_PURE_BAYER_REPROCESSING_ON_RECORDING       (false)
+#define USE_PURE_BAYER_REPROCESSING_ON_DUAL            (false)
+#define USE_PURE_BAYER_REPROCESSING_ON_DUAL_RECORDING  (false)
+
+#define USE_PURE_BAYER_REPROCESSING_FRONT              (false)
+#define USE_PURE_BAYER_REPROCESSING_FRONT_ON_RECORDING (false)
+#define USE_PURE_BAYER_REPROCESSING_FRONT_ON_DUAL      (false)
+#define USE_PURE_BAYER_REPROCESSING_FRONT_ON_DUAL_RECORDING  (false)
+
+#define USE_CAMERA_SIZE_TABLE           (true)
+
+/* #define USE_VARIABLE_FPS_OF_FRONT_RECORDING */
+
+/* This USE_DYNAMIC_BAYER define is for default scenario.
+ * See <ExynosCameraParameter.cpp> for details of dynamic bayer setting
+ */
+#define USE_DYNAMIC_BAYER                       (false)
+#define USE_DYNAMIC_BAYER_VIDEO_SNAP_SHOT       (false)
+
+#define USE_DYNAMIC_BAYER_FRONT                 (false)
+#define USE_DYNAMIC_BAYER_VIDEO_SNAP_SHOT_FRONT (false)
+
+#define USE_YUV_REPROCESSING                    (true)
+#define USE_YUV_REPROCESSING_FOR_THUMBNAIL      (true)
+
+enum REPROCESSING_BAYER_MODE {
+    REPROCESSING_BAYER_MODE_NONE            = 0, /* This means capture do not use reprocessing */
+    REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON,
+    REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON,
+    REPROCESSING_BAYER_MODE_PURE_DYNAMIC,
+    REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC,
+    REPROCESSING_BAYER_MODE_MAX,
+};
+
+#define SET_FPS_FRONTCAM                (1)
+
+#define MAX_FACEDETECT_THREADQ_SIZE     (2)
+#define MAX_FOCUSCONTINUS_THREADQ_SIZE  (2)
+
+#define USE_DYNAMIC_SCC_REAR            (false)
+#define USE_DYNAMIC_SCC_FRONT           (false)
+
+#define USE_GSC_FOR_CAPTURE_BACK        (false)
+#define USE_GSC_FOR_CAPTURE_FRONT       (false)
+
+#define MAX_SERIES_SHOT_COUNT           (1000)
+
+#define SENSOR_FW_PATH_BACK "/sys/class/camera/rear/rear_camfw"
+#define SENSOR_FW_PATH_FRONT "/sys/class/camera/front/front_camfw"
+
+#define TORCH_REAR_FILE_PATH "/sys/devices/14400000.fimc_is/torch/flash_torch_control"
+#define TORCH_FRONT_FILE_PATH "/sys/devices/14400000.fimc_is/torch/flash_torch_control"
+
+#define SUPPORT_64BITS
+
+#ifndef DEBUG_RAWDUMP
+#define CAMERA_PACKED_BAYER_ENABLE
+#endif
+/* #define USE_BUFFER_WITH_STRIDE */
+
+#define OWN_MCSC_HW                 (true)
+
+/* back */
+#define MAIN_CAMERA_FLITE_NUM                       FIMC_IS_VIDEO_SS0_NUM
+#define MAIN_CAMERA_HAS_OWN_SCC     (false)
+
+#define MAIN_CAMERA_SINGLE_FLITE_3AA_OTF (true)
+#define MAIN_CAMERA_DUAL_FLITE_3AA_OTF   (true)
+
+#define MAIN_CAMERA_SINGLE_3AA_ISP_OTF (true)
+#define MAIN_CAMERA_DUAL_3AA_ISP_OTF   (false)
+
+#define MAIN_CAMERA_SINGLE_MCSC_VRA_OTF (false)
+#define MAIN_CAMERA_DUAL_MCSC_VRA_OTF   (false)
+
+#define MAIN_CAMERA_SINGLE_REPROCESSING  (true)
+#define MAIN_CAMERA_SINGLE_SCC_CAPTURE   (false)
+
+#define MAIN_CAMERA_DUAL_REPROCESSING    (false)
+#define MAIN_CAMERA_DUAL_SCC_CAPTURE     (false)
+
+#define MAIN_CAMERA_SINGLE_3AA_ISP_OTF_REPROCESSING    (false)
+#define MAIN_CAMERA_DUAL_3AA_ISP_OTF_REPROCESSING      (false) /* need to be same with FRONT_CAMERA_DUAL_3AA_ISP_OTF on dual case */
+
+/* front */
+#define FRONT_CAMERA_FLITE_NUM                       FIMC_IS_VIDEO_SS1_NUM
+#define FRONT_CAMERA_HAS_OWN_SCC    (false)
+
+#define FRONT_CAMERA_SINGLE_FLITE_3AA_OTF (true)
+#define FRONT_CAMERA_DUAL_FLITE_3AA_OTF   (false)
+
+#define FRONT_CAMERA_SINGLE_3AA_ISP_OTF (true)
+#define FRONT_CAMERA_DUAL_3AA_ISP_OTF   (true)
+
+#define FRONT_CAMERA_SINGLE_MCSC_VRA_OTF (false)
+#define FRONT_CAMERA_DUAL_MCSC_VRA_OTF   (false)
+
+#define FRONT_CAMERA_SINGLE_REPROCESSING  (true)
+#define FRONT_CAMERA_SINGLE_SCC_CAPTURE   (false)
+
+#define FRONT_CAMERA_DUAL_REPROCESSING    (false)
+#define FRONT_CAMERA_DUAL_SCC_CAPTURE     (true)
+
+#define FRONT_CAMERA_SINGLE_3AA_ISP_OTF_REPROCESSING    (false)
+#define FRONT_CAMERA_DUAL_3AA_ISP_OTF_REPROCESSING      (false)
+
+#define USE_3AC_FOR_ISPC            (true)
+
+#define CAMERA_HAS_OWN_BDS          (false)
+
+#define SCENARIO_SHIFT              (28)
+#define REPROCESSING_SHIFT          (28)
+#define OTF_3AA_SHIFT               (24)
+#define SSX_VINDEX_SHIFT            (16)
+#define TAX_VINDEX_SHIFT            (8)
+
+#define SENSOR_NOBLOCK_SHIFT        (28)
+#define SENSOR_INSTANT_SHIFT        (16)
+#define SENSOR_SSTREAM_SHIFT        (0)
+
+#define INPUT_STREAM_MASK   0xFF000000 /* stream type : 1 (reprocessing) */
+#define INPUT_STREAM_SHIFT   24
+#define INPUT_MODULE_MASK   0x00FF0000 /* module id : unique sensor id */
+#define INPUT_MODULE_SHIFT   16
+#define INPUT_VINDEX_MASK   0x0000FF00 /* video node index : connected node */
+#define INPUT_VINDEX_SHIFT   8
+#define INPUT_MEMORY_MASK   0x000000F0 /* memory interface : 0 (on-the-fly) */
+#define INPUT_MEMORY_SHIFT   4
+#define INPUT_LEADER_MASK   0x0000000F /* leader : 1 (leader video node) */
+#define INPUT_LEADER_SHIFT   0
+
+#define PREVIEW_GSC_NODE_NUM            (4)  /* 4 = MSC from Exynos5420 */
+#define PICTURE_GSC_NODE_NUM            (4)  /* 0,1,2 = GSC */
+#define VIDEO_GSC_NODE_NUM              (4)
+
+#if (SUPPORT_BACK_HW_VDIS || SUPPORT_FRONT_HW_VDIS)
+/*
+ * HACK
+ * When enable hw vdis, one more M2M case is happen(isp -> tpu).
+ * we meet frame drop(2,3 per sec), because of memory lack.
+ * so, just increase buffer to avoid frame drop.
+ */
+#define MAX_BUFFERS                     (32)
+#define NUM_SENSOR_BUFFERS              (4 + REPROCESSING_BAYER_HOLD_COUNT)
+#define NUM_BAYER_BUFFERS               (4 + REPROCESSING_BAYER_HOLD_COUNT + SHOT_RECOVERY_COUNT)
+#define INIT_BAYER_BUFFERS              (4 + SHOT_RECOVERY_COUNT)
+#define NUM_3AA_BUFFERS                 NUM_BAYER_BUFFERS + 3
+#define NUM_HW_DIS_BUFFERS              (NUM_3AA_BUFFERS)
+#define NUM_VRA_BUFFERS                 (2)
+#define NUM_PREVIEW_BUFFERS             (9 + SHOT_RECOVERY_COUNT + 3)
+#define NUM_PREVIEW_SPARE_BUFFERS       (3)
+#define INIT_SCP_BUFFERS                (5)
+#define NUM_PICTURE_BUFFERS             (5)
+#define NUM_REPROCESSING_BUFFERS        (1)
+#define NUM_RECORDING_BUFFERS           (8)
+#define NUM_FASTAESTABLE_BUFFER         (10)
+#define NUM_PREVIEW_BUFFERS_MARGIN      (1)
+#else
+#define MAX_BUFFERS                     (32)
+#define NUM_SENSOR_BUFFERS              (4 + REPROCESSING_BAYER_HOLD_COUNT)
+#define NUM_BAYER_BUFFERS               (4 + REPROCESSING_BAYER_HOLD_COUNT + SHOT_RECOVERY_COUNT)
+#define INIT_BAYER_BUFFERS              (4 + SHOT_RECOVERY_COUNT)
+#define NUM_3AA_BUFFERS                 NUM_BAYER_BUFFERS
+#define NUM_HW_DIS_BUFFERS              (NUM_3AA_BUFFERS + 3)
+#define NUM_VRA_BUFFERS                 (2)
+#define NUM_PREVIEW_BUFFERS             (9 + SHOT_RECOVERY_COUNT + 3)
+#define NUM_PREVIEW_SPARE_BUFFERS       (3)
+#define INIT_SCP_BUFFERS                (5)
+#define NUM_PICTURE_BUFFERS             (5)
+#define NUM_REPROCESSING_BUFFERS        (1)
+#define NUM_RECORDING_BUFFERS           (8)
+#define NUM_FASTAESTABLE_BUFFER         (10)
+#define NUM_PREVIEW_BUFFERS_MARGIN      (1)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#define RESERVED_NUM_BAYER_BUFFERS      (NUM_BAYER_BUFFERS)
+#define RESERVED_NUM_ISP_BUFFERS        (0)
+#else
+#ifdef DEBUG_RAWDUMP
+#define RESERVED_NUM_BAYER_BUFFERS      (0)
+#define RESERVED_NUM_ISP_BUFFERS        (0)
+#else
+#define RESERVED_NUM_BAYER_BUFFERS      (5)
+#define RESERVED_NUM_ISP_BUFFERS        (3)
+#endif /* DEBUG_RAWDUMP */
+#endif
+
+#define PIPE_FLITE_PREPARE_COUNT            (3)
+#define PIPE_3AC_PREPARE_COUNT              (3)
+#define PIPE_3AA_ISP_PREPARE_COUNT          (3)
+#define PIPE_ISP_PREPARE_COUNT              (0)
+#define PIPE_SCC_PREPARE_COUNT              (1)
+#define PIPE_SCP_PREPARE_COUNT              (3)
+
+#define PIPE_FLITE_FRONT_PREPARE_COUNT      (3)
+#define PIPE_SCC_FRONT_PREPARE_COUNT        (1)
+#define PIPE_SCP_FRONT_PREPARE_COUNT        (3)
+#define PIPE_SCP_REPROCESSING_PREPARE_COUNT (3)
+#define PIPE_SCC_REPROCESSING_PREPARE_COUNT (1)
+
+#define NUM_FRAME_PREPARE_COUNT         (6)
+#define NUM_BURST_GSC_JPEG_INIT_BUFFER  (4) /* Number of pre-allicated buffer for burst shot
+                                               Increasing this number will increase takePicture()'s
+                                               response time. Currently it is defined as
+                                               (# of JPEG save thread) + 1 */
+
+/* TO DO : will remove */
+#define REPROCESSING_BAYER_HOLD_COUNT   (1)
+#define FRONT_NUM_SENSOR_BUFFERS        (NUM_SENSOR_BUFFERS)
+#define FRONT_NUM_BAYER_BUFFERS         (NUM_BAYER_BUFFERS)
+#define FRONT_NUM_3AA_BUFFERS           (NUM_3AA_BUFFERS)
+#define FRONT_NUM_PICTURE_BUFFERS       (NUM_PICTURE_BUFFERS)
+
+#ifdef DEBUG_RAWDUMP
+#define FRONT_RESERVED_NUM_BAYER_BUFFERS        (0)
+#define FRONT_RESERVED_NUM_ISP_BUFFERS          (0)
+#else
+#define FRONT_RESERVED_NUM_BAYER_BUFFERS        (6)
+#define FRONT_RESERVED_NUM_ISP_BUFFERS          (0)
+#endif /* DEBUG_RAWDUMP */
+
+#define MFC_7X_BUFFER_OFFSET            (256)
+
+#if (USE_HIGHSPEED_RECORDING)
+#define FPS60_NUM_NUM_SENSOR_BUFFERS         (NUM_SENSOR_BUFFERS + 5)
+#define FPS60_NUM_NUM_BAYER_BUFFERS          (NUM_BAYER_BUFFERS + 5)
+#define FPS60_INIT_BAYER_BUFFERS             (INIT_BAYER_BUFFERS * 2)
+#define FPS60_NUM_HW_DIS_BUFFERS             (NUM_HW_DIS_BUFFERS + 5)
+#define FPS60_NUM_VRA_BUFFERS                (2)
+#define FPS60_NUM_PREVIEW_BUFFERS            (NUM_PREVIEW_BUFFERS + 7)
+#define FPS60_NUM_PICTURE_BUFFERS            (NUM_PICTURE_BUFFERS)
+#define FPS60_NUM_REPROCESSING_BUFFERS       (NUM_REPROCESSING_BUFFERS)
+#define FPS60_NUM_RECORDING_BUFFERS          (NUM_RECORDING_BUFFERS + 5)
+#define FPS60_INITIAL_SKIP_FRAME             (INITIAL_SKIP_FRAME)
+#define FPS60_REPROCESSING_BAYER_HOLD_COUNT  (REPROCESSING_BAYER_HOLD_COUNT)
+#define FPS60_FRONT_NUM_SENSOR_BUFFERS       (FRONT_NUM_SENSOR_BUFFERS)
+#define FPS60_FRONT_NUM_BAYER_BUFFERS        (FRONT_NUM_BAYER_BUFFERS)
+#define FPS60_FRONT_NUM_PICTURE_BUFFERS      (FRONT_NUM_PICTURE_BUFFERS)
+#define FPS60_NUM_PREVIEW_BUFFERS_MARGIN     (NUM_PREVIEW_BUFFERS_MARGIN + 1)
+
+#define FPS60_PIPE_FLITE_PREPARE_COUNT       (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_3AC_PREPARE_COUNT         (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_3AA_ISP_PREPARE_COUNT     (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_SCP_PREPARE_COUNT         (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_SCP_REPROCESSING_PREPARE_COUNT (3)
+
+#define FPS120_NUM_NUM_SENSOR_BUFFERS        (NUM_SENSOR_BUFFERS * 3)
+#define FPS120_NUM_NUM_BAYER_BUFFERS         (NUM_BAYER_BUFFERS * 3)
+#define FPS120_INIT_BAYER_BUFFERS            (INIT_BAYER_BUFFERS * 3)
+#define FPS120_NUM_HW_DIS_BUFFERS            (NUM_HW_DIS_BUFFERS * 3)
+#define FPS120_NUM_VRA_BUFFERS               (2)
+#define FPS120_NUM_PREVIEW_BUFFERS           (NUM_PREVIEW_BUFFERS * 3)
+#define FPS120_NUM_PICTURE_BUFFERS           (NUM_PICTURE_BUFFERS)
+#define FPS120_NUM_REPROCESSING_BUFFERS      (NUM_REPROCESSING_BUFFERS)
+#define FPS120_NUM_RECORDING_BUFFERS         (NUM_RECORDING_BUFFERS * 3)
+#define FPS120_INITIAL_SKIP_FRAME            (INITIAL_SKIP_FRAME)
+#define FPS120_REPROCESSING_BAYER_HOLD_COUNT (REPROCESSING_BAYER_HOLD_COUNT)
+#define FPS120_FRONT_NUM_SENSOR_BUFFERS      (FRONT_NUM_SENSOR_BUFFERS)
+#define FPS120_FRONT_NUM_BAYER_BUFFERS       (FRONT_NUM_BAYER_BUFFERS)
+#define FPS120_FRONT_NUM_PICTURE_BUFFERS     (FRONT_NUM_PICTURE_BUFFERS)
+#define FPS120_NUM_PREVIEW_BUFFERS_MARGIN    (NUM_PREVIEW_BUFFERS_MARGIN + 1)
+
+#define FPS120_PIPE_FLITE_PREPARE_COUNT       (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_3AC_PREPARE_COUNT         (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_3AA_ISP_PREPARE_COUNT     (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_SCP_PREPARE_COUNT         (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_SCP_REPROCESSING_PREPARE_COUNT (3)
+#endif
+
+#define V4L2_CAMERA_MEMORY_TYPE         (V4L2_MEMORY_DMABUF) /* (V4L2_MEMORY_USERPTR) */
+#define SCC_OUTPUT_COLOR_FMT            (V4L2_PIX_FMT_YUYV)
+#define JPEG_INPUT_COLOR_FMT            (SCC_OUTPUT_COLOR_FMT)
+#define CAMERA_BAYER_FORMAT             (V4L2_PIX_FMT_SBGGR12)
+#define CAMERA_DUMP_BAYER_FORMAT        (V4L2_PIX_FMT_SBGGR16)
+
+#define ERROR_POLLING_DETECTED          (-1001)
+#define ERROR_DQ_BLOCKED_DETECTED       (-1002)
+#define ERROR_DQ_BLOCKED_COUNT          (20)
+#define WARNING_3AA_THREAD_INTERVAL     (100000)
+#define WARNING_SCP_THREAD_INTERVAL     (100000)
+#define MONITOR_THREAD_INTERVAL         (200000)
+
+#define FRAME_MIN_NUM (3)
+
+#define EXYNOS_CAMERA_BUFFER_MAX_PLANES (5)     /* img buffer 4 + metadata 1 */
+#define EXYNOS_CAMERA_META_PLANE_SIZE   (32 * 1024)
+#define GRALLOC_LOCK_FOR_CAMERA         (GRALLOC_SET_USAGE_FOR_CAMERA)
+
+#define EXYNOS_CAMERA_PREVIEW_FPS_REFERENCE  (60)
+
+#define  NUM_OF_DETECTED_FACES           (16)
+#define  NUM_OF_DETECTED_FACES_THRESHOLD (0)
+
+#define PERFRAME_NODE_GROUP_MAX          (5)
+#define PERFRAME_NODE_GROUP_0            (0)
+#define PERFRAME_NODE_GROUP_1            (1)
+#define PERFRAME_NODE_GROUP_2            (2)
+#define PERFRAME_NODE_GROUP_3            (3)
+#define PERFRAME_NODE_GROUP_4            (4)
+
+#define PERFRAME_INFO_INDEX_MAX          (5)
+#define PERFRAME_INFO_INDEX_0            (0)
+#define PERFRAME_INFO_INDEX_1            (1)
+#define PERFRAME_INFO_INDEX_2            (2)
+#define PERFRAME_INFO_INDEX_3            (3)
+#define PERFRAME_INFO_INDEX_4            (4)
+
+#define PERFRAME_CONTROL_PIPE                   PIPE_3AA
+#define PERFRAME_CONTROL_REPROCESSING_PIPE      PIPE_3AA_REPROCESSING
+#define PERFRAME_CONTROL_NODE_3AA
+/* #define PERFRAME_CONTROL_NODE_ISP */
+#define PERFRAME_INFO_3AA                       PERFRAME_INFO_INDEX_0
+#define PERFRAME_INFO_ISP                       PERFRAME_INFO_INDEX_1
+#define PERFRAME_INFO_DIS                       PERFRAME_INFO_INDEX_2
+#define PERFRAME_INFO_MCSC                      PERFRAME_INFO_INDEX_3
+#define PERFRAME_INFO_VRA                       PERFRAME_INFO_INDEX_4
+
+#define PERFRAME_INFO_PURE_REPROCESSING_3AA     PERFRAME_INFO_INDEX_0
+#define PERFRAME_INFO_PURE_REPROCESSING_ISP     PERFRAME_INFO_INDEX_1
+#define PERFRAME_INFO_PURE_REPROCESSING_MCSC    PERFRAME_INFO_INDEX_2
+
+#define PERFRAME_INFO_DIRTY_REPROCESSING_ISP    PERFRAME_INFO_INDEX_0
+#define PERFRAME_INFO_DIRTY_REPROCESSING_MCSC   PERFRAME_INFO_INDEX_1
+
+#define PERFRAME_INFO_YUV_REPROCESSING_MCSC     PERFRAME_INFO_INDEX_0
+
+#define PERFRAME_3AA_POS                        PER_FRAME_GROUP_0
+#define PERFRAME_ISP_POS                        PER_FRAME_GROUP_1
+
+#define PERFRAME_BACK_3AC_POS           (0)
+#define PERFRAME_BACK_3AP_POS           (1)
+#define PERFRAME_BACK_ISPC_POS          (0)
+#define PERFRAME_BACK_ISPP_POS          (2)
+#define PERFRAME_BACK_SCC_POS           (3)
+#define PERFRAME_BACK_SCP_POS           (3)
+#define PERFRAME_BACK_MCSC0_POS         (0)
+#define PERFRAME_BACK_MCSC1_POS         (0)
+#define PERFRAME_BACK_MCSC2_POS         (0)
+
+/*
+#define PERFRAME_FRONT_3AC_POS          (1)
+#define PERFRAME_FRONT_3AP_POS          (0)
+#define PERFRAME_FRONT_SCC_POS          (0)
+#define PERFRAME_FRONT_SCP_POS          (1)
+*/
+#define PERFRAME_FRONT_3AC_POS          (PERFRAME_BACK_3AC_POS)
+#define PERFRAME_FRONT_3AP_POS          (PERFRAME_BACK_3AP_POS)
+#define PERFRAME_FRONT_ISPC_POS         (PERFRAME_BACK_ISPC_POS)
+#define PERFRAME_FRONT_ISPP_POS         (PERFRAME_BACK_ISPP_POS)
+#define PERFRAME_FRONT_SCC_POS          (PERFRAME_BACK_SCC_POS)
+#define PERFRAME_FRONT_SCP_POS          (PERFRAME_BACK_SCP_POS)
+
+#define PERFRAME_REPROCESSING_3AP_POS   (0)
+#define PERFRAME_REPROCESSING_3AC_POS   (1)
+#define PERFRAME_REPROCESSING_SCC_POS   (2) /* be care of source code, when you change. */
+#define PERFRAME_REPROCESSING_ISPC_POS    (0)
+#define PERFRAME_REPROCESSING_ISPP_POS    (0)
+#define PERFRAME_REPROCESSING_MCSC0_POS   (PERFRAME_REPROCESSING_SCC_POS)
+#define PERFRAME_REPROCESSING_MCSC2_POS   (0)
+#define PERFRAME_REPROCESSING_MCSC3_POS   (0)
+#define PERFRAME_REPROCESSING_MCSC4_POS   (0)
+
+#define WAITING_TIME                     (5000)   /* 5msec */
+#define TOTAL_WAITING_TIME               (3000 * 1000)  /* 3000msec */
+#define TOTAL_WAITING_COUNT              (3)
+#define TOTAL_FLASH_WATING_COUNT         (10)
+#define CAPTURE_WAITING_COUNT            (15)
+
+#define DM_WAITING_TIME                  (30 * 1000) /* 30msec */
+#define DM_WAITING_COUNT                 (10)
+
+/*vision */
+/* #define VISION_DUMP */
+#define VISION_WIDTH                     (320)
+#define VISION_HEIGHT                    (180)
+
+/* callback state */
+#define CALLBACK_STATE_PREVIEW_META     (1)
+#define CALLBACK_STATE_PREVIEW_FRAME    (2)
+#define CALLBACK_STATE_RAW_IMAGE        (3)
+#define CALLBACK_STATE_POSTVIEW_FRAME   (4)
+#define CALLBACK_STATE_COMPRESSED_IMAGE (5)
+
+#define MAGIC_SHOT_DURATION         125000  /* 8fps */
+#define BEST_PHOTO_DURATION         195000  /* about 5fps */
+#define BEST_FACE_DURATION          400000  /* 2.5fps */
+#define ERASER_DURATION             800000  /* 1.25fps */
+#define NORMAL_BURST_DURATION       90000   /* about 11fps */
+#define SELFIE_ALARM_DURATION       330000  /* about 3fps */
+
+#define USE_MEM2MEM_GSC
+
+#ifdef USE_MEM2MEM_GSC
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP | \
+     GRALLOC_USAGE_HW_CAMERA_MASK)
+#else
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP)
+#endif
+
+enum YUV_RANGE {
+    YUV_FULL_RANGE = 0,
+    YUV_LIMITED_RANGE = 1,
+};
+
+enum pipeline {
+    PIPE_FLITE                  = 0,
+    PIPE_3AA,
+    PIPE_3AC,
+    PIPE_3AP,
+    PIPE_ISP,
+    PIPE_ISPC,
+    PIPE_ISPP,
+    PIPE_DIS,
+    PIPE_MCSC,
+    PIPE_SCP,
+    PIPE_MCSC0 = PIPE_SCP,
+    PIPE_MCSC1,
+    PIPE_MCSC2,
+    PIPE_MCSC3,
+    PIPE_MCSC4,
+    PIPE_VRA,
+    PIPE_3AA_ISP,
+    PIPE_POST_3AA_ISP,
+    PIPE_SCC,
+    PIPE_GSC,
+    PIPE_GSC_VIDEO,
+    PIPE_GSC_VRA,
+    PIPE_GSC_PICTURE,
+    PIPE_JPEG,
+    MAX_PIPE_NUM,
+
+    /*
+     * PIPE_XXX_FRONT are deprecated define.
+     * Don't use this. (just let for common code compile)
+     */
+    PIPE_FLITE_FRONT = 100,
+    PIPE_3AA_FRONT,
+    PIPE_3AC_FRONT,
+    PIPE_3AP_FRONT,
+    PIPE_ISP_FRONT,
+    PIPE_ISPC_FRONT,
+    PIPE_ISPP_FRONT,
+    PIPE_SCP_FRONT,
+    PIPE_3AA_ISP_FRONT,
+    PIPE_POST_3AA_ISP_FRONT,
+    PIPE_DIS_FRONT,
+    PIPE_SCC_FRONT,
+    PIPE_GSC_FRONT,
+    PIPE_GSC_VIDEO_FRONT,
+    PIPE_GSC_PICTURE_FRONT,
+    PIPE_JPEG_FRONT,
+    MAX_PIPE_NUM_FRONT,
+
+    PIPE_FLITE_REPROCESSING     = 200,
+    PIPE_3AA_REPROCESSING,
+    PIPE_3AC_REPROCESSING,
+    PIPE_3AP_REPROCESSING,
+    PIPE_ISP_REPROCESSING,
+    PIPE_ISPC_REPROCESSING,
+    PIPE_ISPP_REPROCESSING,
+    PIPE_MCSC_REPROCESSING,
+    PIPE_MCSC0_REPROCESSING,
+    PIPE_MCSC1_REPROCESSING,
+    PIPE_MCSC2_REPROCESSING,
+    PIPE_MCSC3_REPROCESSING,
+    PIPE_MCSC4_REPROCESSING,
+    PIPE_SCC_REPROCESSING,
+    PIPE_SCP_REPROCESSING,
+    PIPE_GSC_REPROCESSING,
+    PIPE_GSC_REPROCESSING2,
+    PIPE_GSC_REPROCESSING3,
+#ifdef UVS
+    PIPE_UVS_REPROCESSING,
+#endif
+    PIPE_JPEG_REPROCESSING,
+    PIPE_HWFC_JPEG_SRC_REPROCESSING,
+    PIPE_HWFC_THUMB_SRC_REPROCESSING,
+    PIPE_HWFC_JPEG_DST_REPROCESSING,
+    PIPE_HWFC_THUMB_DST_REPROCESSING,
+    MAX_PIPE_NUM_REPROCESSING
+};
+
+enum fimc_is_video_dev_num {
+    FIMC_IS_VIDEO_BAS_NUM = 100,
+    FIMC_IS_VIDEO_SS0_NUM = 101,
+    FIMC_IS_VIDEO_SS1_NUM,
+    FIMC_IS_VIDEO_SS2_NUM,
+    FIMC_IS_VIDEO_SS3_NUM,
+    FIMC_IS_VIDEO_30S_NUM = 110,
+    FIMC_IS_VIDEO_30C_NUM,
+    FIMC_IS_VIDEO_30P_NUM,
+    FIMC_IS_VIDEO_31S_NUM = 120,
+    FIMC_IS_VIDEO_31C_NUM,
+    FIMC_IS_VIDEO_31P_NUM,
+    FIMC_IS_VIDEO_I0S_NUM = 130,
+    FIMC_IS_VIDEO_I0C_NUM,
+    FIMC_IS_VIDEO_I0P_NUM,
+    FIMC_IS_VIDEO_I1S_NUM = 140,
+    FIMC_IS_VIDEO_I1C_NUM,
+    FIMC_IS_VIDEO_I1P_NUM,
+    FIMC_IS_VIDEO_TPU_NUM = 150,
+    FIMC_IS_VIDEO_SCC_NUM,
+    FIMC_IS_VIDEO_SCP_NUM,
+    FIMC_IS_VIDEO_M0S_NUM = 160,
+    FIMC_IS_VIDEO_M1S_NUM,
+    FIMC_IS_VIDEO_M0P_NUM = 170,
+    FIMC_IS_VIDEO_M1P_NUM,
+    FIMC_IS_VIDEO_M2P_NUM,
+    FIMC_IS_VIDEO_M3P_NUM,
+    FIMC_IS_VIDEO_M4P_NUM,
+    FIMC_IS_VIDEO_VRA_NUM = 180,
+    FIMC_IS_VIDEO_HWFC_JPEG_NUM = 200,
+    FIMC_IS_VIDEO_HWFC_THUMB_NUM = 201,
+    FIMC_IS_VIDEO_MAX_NUM
+};
+
+#define MAIN_CAMERA_COMPANION_NUM   (109)
+#define FRONT_CAMERA_COMPANION_NUM  (109)
+
+enum frame_generation_mode_enum {
+    EXYNOS_GENERATE_SKIP_FRAME = 0,
+    EXYNOS_GENERATE_FAST_AE_STABLE_FRAME = 1,
+    EXYNOS_GENERATE_DYNAMIC_BAYER_FRAME = 2,
+    EXYNOS_GENERATE_NORMAL_FRAME = 3,
+    EXYNOS_GENERATE_FRAME_MAX
+};
+
+/* This struct used in recording callback */
+/* This struct passes to OMX */
+struct addrs {
+    uint32_t        type;       /* make sure that this is 4 byte. */
+    unsigned int    fdPlaneY;
+    unsigned int    fdPlaneCbcr;
+    unsigned int    bufIndex;
+    unsigned int    reserved;
+};
+
+/* overflow handling */
+#define SENSOR_OVERFLOW_CHECK
+
+/* for test */
+/* #define SCALABLE_ON */
+/* #define TEST_GED_HIGH_SPEED_RECORDING */
+/* #define TEST_APP_HIGH_SPEED_RECORDING */ /* for ArtCamera */
+/* #define FORCE_RESET_MULTI_FRAME_FACTORY */
+#endif /*USE_VENDOR_SPECIFIC_CONFIG_HEADER*/
+
+#endif /* EXYNOS_CAMERA_CONFIG_H__ */
diff --git a/libcamera/NOTICE b/libcamera/NOTICE
new file mode 100644 (file)
index 0000000..8530865
--- /dev/null
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2015, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libcamera/SensorInfos/ExynosCamera3SensorInfo.cpp b/libcamera/SensorInfos/ExynosCamera3SensorInfo.cpp
new file mode 100644 (file)
index 0000000..9739305
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+**
+** Copyright 2015, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*#define LOG_NDEBUG 0 */
+#define LOG_TAG "ExynosCamera3SensorInfo"
+#include <cutils/log.h>
+
+#include "ExynosCamera3SensorInfo.h"
+
+namespace android {
+
+struct ExynosSensorInfoBase *createExynosCamera3SensorInfo(int camId)
+{
+    struct ExynosSensorInfoBase *sensorInfo = NULL;
+    int sensorId = getSensorId(camId);
+    if (sensorId < 0) {
+        ALOGE("ERR(%s[%d]): Inavalid camId, sensor name is nothing", __FUNCTION__, __LINE__);
+        sensorId = SENSOR_NAME_NOTHING;
+    }
+
+    switch (sensorId) {
+    case SENSOR_NAME_S5K3L2:
+        sensorInfo = new ExynosCamera3SensorS5K3L2();
+        break;
+    case SENSOR_NAME_S5K3M2:
+        sensorInfo = new ExynosCamera3SensorS5K3M2();
+        break;
+    case SENSOR_NAME_S5K5E2:
+        sensorInfo = new ExynosCamera3SensorS5K5E2();
+        break;
+    case SENSOR_NAME_S5K5E3:
+        sensorInfo = new ExynosCamera3SensorS5K5E3();
+        break;
+    default:
+        android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):Unknown sensor(%d), create default sensor, assert!!!!",
+            __FUNCTION__, __LINE__, camId);
+        break;
+    }
+
+    return sensorInfo;
+}
+
+ExynosCamera3SensorS5K3L2::ExynosCamera3SensorS5K3L2() : ExynosCamera3SensorS5K3L2Base()
+{
+    hyperFocalDistance = 1.0f / 3.6f;
+};
+
+ExynosCamera3SensorS5K3M2::ExynosCamera3SensorS5K3M2() : ExynosCamera3SensorS5K3M2Base()
+{
+    hyperFocalDistance = 1.0f / 3.6f;
+};
+
+ExynosCamera3SensorS5K5E2::ExynosCamera3SensorS5K5E2() : ExynosCamera3SensorS5K5E2Base()
+{
+};
+
+ExynosCamera3SensorS5K5E3::ExynosCamera3SensorS5K5E3() : ExynosCamera3SensorS5K5E3Base()
+{
+};
+
+}; /* namespace android */
diff --git a/libcamera/SensorInfos/ExynosCamera3SensorInfo.h b/libcamera/SensorInfos/ExynosCamera3SensorInfo.h
new file mode 100644 (file)
index 0000000..1fb79b0
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+**
+** Copyright 2015, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef EXYNOS_CAMERA3_SENSOR_INFO_H
+#define EXYNOS_CAMERA3_SENSOR_INFO_H
+
+#include "ExynosCameraSensorInfo.h"
+#include "ExynosCamera3SensorInfoBase.h"
+
+namespace android {
+
+struct ExynosCamera3SensorS5K3L2 : public ExynosCamera3SensorS5K3L2Base {
+public:
+    ExynosCamera3SensorS5K3L2();
+};
+
+struct ExynosCamera3SensorS5K3M2 : public ExynosCamera3SensorS5K3M2Base {
+public:
+    ExynosCamera3SensorS5K3M2();
+};
+
+struct ExynosCamera3SensorS5K5E2 : public ExynosCamera3SensorS5K5E2Base {
+public:
+    ExynosCamera3SensorS5K5E2();
+};
+
+struct ExynosCamera3SensorS5K5E3 : public ExynosCamera3SensorS5K5E3Base {
+public:
+    ExynosCamera3SensorS5K5E3();
+};
+
+/* Helpper functions */
+struct ExynosSensorInfoBase *createExynosCamera3SensorInfo(int sensorName);
+
+}; /* namespace android */
+#endif
diff --git a/libcamera/SensorInfos/ExynosCameraSensorInfo.cpp b/libcamera/SensorInfos/ExynosCameraSensorInfo.cpp
new file mode 100644 (file)
index 0000000..e37f641
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+**
+** Copyright 2015, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*#define LOG_NDEBUG 0 */
+#define LOG_TAG "ExynosCamera1SensorInfo"
+#include <cutils/log.h>
+
+#include "ExynosCameraSensorInfo.h"
+
+namespace android {
+struct ExynosSensorInfoBase *createExynosCamera1SensorInfo(int camId)
+{
+    struct ExynosSensorInfoBase *sensorInfo = NULL;
+    int sensorName = getSensorId(camId);
+    if (sensorName < 0) {
+        ALOGE("ERR(%s[%d]): Inavalid camId, sensor name is nothing", __FUNCTION__, __LINE__);
+        sensorName = SENSOR_NAME_NOTHING;
+    }
+    ALOGI("INFO(%s[%d]):sensor ID(%d)", __FUNCTION__, __LINE__, sensorName);
+    switch (sensorName) {
+    case SENSOR_NAME_S5K5E2:
+        sensorInfo = new ExynosSensorS5K5E2();
+        break;
+    case SENSOR_NAME_S5K3M2:
+        sensorInfo = new ExynosSensorS5K3M2();
+        break;
+    case SENSOR_NAME_S5K5E8:
+        sensorInfo = new ExynosSensorS5K5E8();
+        break;
+    default:
+        android_printAssert(NULL, LOG_TAG, "ASSERT(%s[%d]):Unknown sensor(%d), create default sensor, assert!!!!",
+            __FUNCTION__, __LINE__, camId);
+        break;
+    }
+
+#ifdef CALIBRATE_BCROP5_SIZE
+    if (sensorInfo->sizeTableSupport) {
+        LutType lut[4];
+        int maxLut[4];
+        lut[0] = sensorInfo->previewSizeLut;
+        maxLut[0] = sensorInfo->previewSizeLutMax;
+        lut[1] = sensorInfo->videoSizeLut;
+        maxLut[1] = sensorInfo->videoSizeLutMax;
+        lut[2] = sensorInfo->pictureSizeLut;
+        maxLut[2] = sensorInfo->pictureSizeLutMax;
+        lut[3] = sensorInfo->videoSizeLutHighSpeed;
+        maxLut[3] = 3;
+
+        LutType curLut;
+        int max = 0;
+        int calc = 0;
+        int offset = 0;
+        for(int k = 0  ; k < 4 ; k++ ) {
+            curLut = lut[k];
+            max = maxLut[k];
+            for (int i = 0; i < max ; i++) {
+                calc = 0;
+                ALOGD("DEBUG(%s:%d):SRC LUT BCROP(%d x %d)", __FUNCTION__, __LINE__, curLut[i][BCROP_W], curLut[i][BCROP_H]);
+                ALOGE("DEBUG(%s:%d):SRC LUT BDS  (%d x %d)", __FUNCTION__, __LINE__, curLut[i][BDS_W], curLut[i][BDS_H]);
+                calc = calibrateB3(curLut[i][BCROP_W], curLut[i][BDS_W]);
+                offset = calc-curLut[i][BDS_W];
+                curLut[i][BNS_W] += offset;
+                curLut[i][BCROP_W] += offset;
+                ALOGE("DEBUG(%s:%d): W offset(%d) ", __FUNCTION__, __LINE__, offset);
+                calc = calibrateB3(curLut[i][BCROP_H], curLut[i][BDS_H]);
+                offset = calc-curLut[i][BDS_H];
+                ALOGE("DEBUG(%s:%d): H offset(%d) ", __FUNCTION__, __LINE__, offset);
+                curLut[i][BNS_H] += offset;
+                curLut[i][BCROP_H] += offset;
+                ALOGE("DEBUG(%s:%d):DST LUT BNS(%d x %d)", __FUNCTION__, __LINE__, curLut[i][BNS_W], curLut[i][BNS_H]);
+                ALOGE("DEBUG(%s:%d):DST LUT BCROP(%d x %d)", __FUNCTION__, __LINE__, curLut[i][BCROP_W], curLut[i][BCROP_H]);
+            }
+        }
+        ALOGW("WRN(%s[%d]): Calibrate BDB size", __FUNCTION__, __LINE__);
+    }else {
+        ALOGW("WRN(%s[%d]): Not use Calibrate BDB size", __FUNCTION__, __LINE__);
+    }
+#endif
+
+    return sensorInfo;
+}
+
+ExynosSensorS5K3M2::ExynosSensorS5K3M2()
+{
+    effectList =
+          EFFECT_NONE
+        | EFFECT_MONO
+        | EFFECT_NEGATIVE
+        /* | EFFECT_SOLARIZE */
+        | EFFECT_SEPIA
+        | EFFECT_POSTERIZE
+        | EFFECT_COLD_VINTAGE
+        | EFFECT_BLUE
+        | EFFECT_RED_YELLOW
+        | EFFECT_AQUA
+        /* | EFFECT_WHITEBOARD */
+        /* | EFFECT_BLACKBOARD */
+        ;
+};
+
+ExynosSensorS5K5E2::ExynosSensorS5K5E2()
+{
+    effectList =
+          EFFECT_NONE
+        | EFFECT_MONO
+        | EFFECT_NEGATIVE
+        /* | EFFECT_SOLARIZE */
+        | EFFECT_SEPIA
+        | EFFECT_POSTERIZE
+        | EFFECT_COLD_VINTAGE
+        | EFFECT_BLUE
+        | EFFECT_RED_YELLOW
+        | EFFECT_AQUA
+        /* | EFFECT_WHITEBOARD */
+        /* | EFFECT_BLACKBOARD */
+        ;
+};
+
+ExynosSensorS5K5E8::ExynosSensorS5K5E8()
+{
+    effectList =
+          EFFECT_NONE
+        | EFFECT_MONO
+        | EFFECT_NEGATIVE
+        /* | EFFECT_SOLARIZE */
+        | EFFECT_SEPIA
+        | EFFECT_POSTERIZE
+        | EFFECT_COLD_VINTAGE
+        | EFFECT_BLUE
+        | EFFECT_RED_YELLOW
+        | EFFECT_AQUA
+        /* | EFFECT_WHITEBOARD */
+        /* | EFFECT_BLACKBOARD */
+        ;
+};
+}; /* namespace android */
diff --git a/libcamera/SensorInfos/ExynosCameraSensorInfo.h b/libcamera/SensorInfos/ExynosCameraSensorInfo.h
new file mode 100644 (file)
index 0000000..9a2bb26
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+**
+** Copyright 2015, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef EXYNOS_CAMERA_1_SENSOR_INFO_H
+#define EXYNOS_CAMERA_1_SENSOR_INFO_H
+
+#if 0
+#include <videodev2.h>
+#include <videodev2_exynos_camera.h>
+#include "ExynosCameraConfig.h"
+#include "ExynosCameraSizeTable.h"
+
+#include "fimc-is-metadata.h"
+#else
+
+#include "ExynosCameraConfig.h"
+#include "ExynosCameraSensorInfoBase.h"
+#endif /* USE_CAMERA2_API_SUPPORT */
+
+namespace android {
+
+
+/****************************************/
+/* Project Specific Sensor LUT          */
+/****************************************/
+
+
+/* Helpper functions */
+struct ExynosSensorInfoBase *createExynosCamera1SensorInfo(int sensorName);
+
+struct ExynosSensorS5K3M2 : public ExynosSensorS5K3M2Base {
+public:
+    ExynosSensorS5K3M2();
+};
+
+struct ExynosSensorS5K5E2 : public ExynosSensorS5K5E2Base {
+public:
+    ExynosSensorS5K5E2();
+};
+
+struct ExynosSensorS5K5E8 : public ExynosSensorS5K5E8Base {
+public:
+    ExynosSensorS5K5E8();
+};
+}; /* namespace android */
+#endif
diff --git a/libcamera3/Android.mk b/libcamera3/Android.mk
new file mode 100644 (file)
index 0000000..f9d80cc
--- /dev/null
@@ -0,0 +1,143 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+#################
+# libexynoscamera3
+
+include $(CLEAR_VARS)
+
+######## System LSI ONLY ########
+BOARD_CAMERA_GED_FEATURE := true
+#################################
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware libui
+LOCAL_SHARED_LIBRARIES += libexynosutils libhwjpeg libexynosv4l2 libexynosgscaler libion libcsc
+LOCAL_SHARED_LIBRARIES += libexpat libc++
+LOCAL_SHARED_LIBRARIES += libpower
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+else
+LOCAL_SHARED_LIBRARIES += libsecnativefeature
+LOCAL_SHARED_LIBRARIES += libuniplugin
+endif
+
+ifeq ($(BOARD_CAMERA_SW_VDIS), true)
+LOCAL_SHARED_LIBRARIES += libvdis
+endif
+
+LOCAL_CFLAGS += -DGAIA_FW_BETA
+LOCAL_CFLAGS += -DMAIN_CAMERA_SENSOR_NAME=$(BOARD_BACK_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DFRONT_CAMERA_SENSOR_NAME=$(BOARD_FRONT_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DUSE_CAMERA_ESD_RESET
+LOCAL_CFLAGS += -DBACK_ROTATION=$(BOARD_BACK_CAMERA_ROTATION)
+LOCAL_CFLAGS += -DFRONT_ROTATION=$(BOARD_FRONT_CAMERA_ROTATION)
+
+ifeq ($(TARGET_BOOTLOADER_BOARD_NAME), universal7570)
+#LOCAL_CFLAGS += -DUNIVERSAL_CAMERA
+endif
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_CFLAGS += -DCAMERA_GED_FEATURE
+endif
+
+LOCAL_CFLAGS += -DUSE_CAMERA2_API_SUPPORT
+
+LOCAL_C_INCLUDES += \
+       $(LOCAL_PATH)/../include \
+       $(LOCAL_PATH)/../libcamera3 \
+       $(TOP)/system/media/camera/include \
+       $(TOP)/system/core/libion/include \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/SensorInfos \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Pipes2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/MCPipes \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Activities \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Buffers \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Ged \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx/hal3 \
+       $(TOP)/hardware/samsung_slsi/exynos/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/libcamera3 \
+       $(TOP)/hardware/libhardware_legacy/include/hardware_legacy \
+       $(TOP)/vendor/samsung/feature/CscFeature/libsecnativefeature \
+       $(TOP)/bionic \
+       $(TOP)/external/expat/lib \
+       $(TOP)/external/libcxx/include \
+       $(TOP)/frameworks/native/include \
+       $(TOP)/hardware/camera/SensorListener \
+       $(TOP)/hardware/camera/UniPlugin/include
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libcamera/SensorInfos
+
+LOCAL_SRC_FILES:= \
+       ../../exynos/libcamera/common_v2/ExynosCameraFrame.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraMemory.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraFrameManager.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraUtils.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraNode.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraNodeJpegHAL.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraFrameSelector.cpp \
+       ../../exynos/libcamera/common_v2/SensorInfos/ExynosCameraSensorInfoBase.cpp \
+       ../../exynos/libcamera/common_v2/SensorInfos/ExynosCamera3SensorInfoBase.cpp \
+       ../../exynos/libcamera/common_v2/MCPipes/ExynosCameraMCPipe.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipe.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeFlite.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeVRA.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeGSC.cpp \
+       ../../exynos/libcamera/common_v2/Pipes2/ExynosCameraPipeJpeg.cpp \
+       ../../exynos/libcamera/common_v2/Buffers/ExynosCameraBufferManager.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityBase.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityAutofocus.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityFlash.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivitySpecialCapture.cpp \
+       ../../exynos/libcamera/common_v2/Activities/ExynosCameraActivityUCTL.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraRequestManager.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraStreamManager.cpp \
+       ../../exynos/libcamera/common_v2/ExynosCameraMetadataConverter.cpp \
+       ../../exynos/libcamera/common_v2/Ged/ExynosCameraActivityAutofocusVendor.cpp \
+       ../../exynos/libcamera/common_v2/Ged/ExynosCameraActivityFlashVendor.cpp \
+       ../../exynos/libcamera/common_v2/Ged/ExynosCameraFrameSelectorVendor.cpp \
+       ../../exynos/libcamera/34xx/ExynosCameraActivityControl.cpp\
+       ../../exynos/libcamera/34xx/ExynosCameraScalableSensor.cpp \
+       ../../exynos/libcamera/34xx/ExynosCameraUtilsModule.cpp \
+#HAL 3.0 source
+LOCAL_SRC_FILES += \
+       ../../exynos/libcamera/34xx/hal3/ExynosCameraSizeControl.cpp \
+       ../../exynos/libcamera/34xx/hal3/ExynosCamera3.cpp \
+       ../../exynos/libcamera/34xx/hal3/ExynosCamera3Parameters.cpp \
+       ../../exynos/libcamera/34xx/hal3/ExynosCamera3FrameFactory.cpp \
+       ../../exynos/libcamera/34xx/hal3/ExynosCamera3FrameFactoryPreview.cpp \
+       ../../exynos/libcamera/34xx/hal3/ExynosCamera3FrameReprocessingFactory.cpp \
+
+LOCAL_SRC_FILES += ../libcamera/SensorInfos/ExynosCamera3SensorInfo.cpp
+
+$(foreach file,$(LOCAL_SRC_FILES),$(shell touch '$(LOCAL_PATH)/$(file)'))
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libexynoscamera3
+
+include $(TOP)/hardware/samsung_slsi/exynos/BoardConfigCFlags.mk
+include $(BUILD_SHARED_LIBRARY)
+
+$(warning ##########################################)
+$(warning ##########################################)
+$(warning ########     libcamera 3     #############)
+$(warning ##########################################)
+$(warning ##########################################)
diff --git a/libcamera3/ExynosCamera3Config.h b/libcamera3/ExynosCamera3Config.h
new file mode 100644 (file)
index 0000000..f733a08
--- /dev/null
@@ -0,0 +1,845 @@
+/*
+ * Copyright 2015, Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed toggle an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EXYNOS_CAMERA_3_CONFIG_H__
+#define EXYNOS_CAMERA_3_CONFIG_H__
+
+#include "ExynosCameraCommonEnum.h"
+#include "ExynosCameraCommonDefine.h"
+
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <cutils/properties.h>
+#include <camera/CameraParameters.h>
+
+#ifndef USE_CAMERA2_API_SUPPORT
+#define USE_CAMERA2_API_SUPPORT
+#endif
+
+#ifndef CAMERA_GED_FEATURE
+#define CAMERA_GED_FEATURE
+#endif
+
+/* It will be replaced by TN */
+#ifdef CAMERA_GED_FEATURE
+#else
+#include "SecCameraConfig-common.h"
+#endif /* CAMERA_GED_FEATURE */
+
+#define EFFECT_VALUE_VERSION_2_0
+
+#define MONITOR_LOG_SYNC
+#define MONITOR_LOG_SYNC_INTERVAL 100
+
+#define USE_HAL3_2_METADATA_INTERFACE
+#define SUPPORT_HAL3_3_METADATA
+
+#ifndef USE_VENDOR_SPECIFIC_CONFIG_HEADER
+
+#ifdef SAMSUNG_COMPANION
+#define MAIN_CAMERA_USE_SAMSUNG_COMPANION   (false)
+#define FRONT_CAMERA_USE_SAMSUNG_COMPANION  (false)
+#endif
+
+#include <math.h>
+
+/************************************************/
+#ifdef CAMERA_GED_FEATURE
+#else
+#define SUPPORT_X8_ZOOM
+#endif
+
+#define USE_SUBDIVIDED_EV
+
+/* #define DEBUG_RAWDUMP */
+/************************************************/
+
+/* For 13MP Full Frame */
+/* #define ENABLE_13MP_FULL_FRAME            (true) */
+
+
+#define LCD_SIZE_DEFAULT                (0)
+#define LCD_SIZE_800_480                (1)
+#define LCD_SIZE_1280_720               (2)
+#define LCD_SIZE_1920_1080              (3)
+#define LCD_SIZE_2560_1440              (4)
+#define CAMERA_LCD_SIZE                 LCD_SIZE_1280_720
+
+/* #define LIMIT_SCP_SIZE_UNTIL_FHD_ON_CAPTURE */   /* Even if LCD is bigger than FHD, limit scp size until FHD on capture preview  */
+#define LIMIT_SCP_SIZE_UNTIL_FHD_ON_RECORDING /* Even if LCD is bigger than FHD, limit scp size until FHD on recording preview*/
+
+#define CAMERA_BCROP_ALIGN              (16)
+#define CAMERA_ISP_ALIGN                (8)
+#define CAMERA_MCSC_ALIGN               (2)
+#define CAMERA_MAGIC_ALIGN              (16)
+#define CAMERA_16PX_ALIGN               (16)
+/* This value for GSC alignment refer to "csc.h" */
+#define GSCALER_IMG_ALIGN               (16)
+
+#define SCALER_MAX_SCALE_UP_RATIO       (8)
+
+#define INITIAL_SKIP_FRAME              (8)
+#define VISION_SKIP_FRAME               (4)
+#define EFFECT_SKIP_FRAME               (1)
+#define SMART_STAY_SKIP_COMPENSATION    (1)
+#define USE_GRALLOC_REUSE_SUPPORT
+#define USE_GRALLOC_BUFFER_COLLECTOR
+
+#define USE_FRONT_FULL_OTF
+#define USE_REAR_FULL_OTF
+
+/* Functions tobe enable */
+/* #define START_PICTURE_THREAD */
+/* #define SET_SETFILE_BY_SHOT */
+#define USE_FRAMEMANAGER
+#ifdef USE_FRAMEMANAGER
+#define USE_FRAME_REFERENCE_COUNT
+#else
+#endif
+
+#define USE_FW_OPMODE
+#define USE_CAMERA2_USE_FENCE
+#define USE_SW_FENCE
+
+#define SET_SETFILE_BY_SET_CTRL
+#ifdef SET_SETFILE_BY_SET_CTRL
+#define SET_SETFILE_BY_SET_CTRL_3AA_ISP (false)
+#define SET_SETFILE_BY_SET_CTRL_3AA     (false)
+#define SET_SETFILE_BY_SET_CTRL_ISP     (true)
+#define SET_SETFILE_BY_SET_CTRL_SCP     (false)
+#endif
+
+/* #define USE_DVFS_LOCK */
+#ifdef CAMERA_GED_FEATURE
+#else
+#define RESERVED_MEMORY_ENABLE
+#endif
+
+#define RESERVED_BUFFER_COUNT_MAX       (0)
+
+/* #define USE_BNS_PREVIEW */ /* use BNS on capture scenario. this change LUT size */
+
+/* #define USE_BNS_RECORDING */
+/* #define USE_BDS_RECORDING */ /* use bds on recording scenario. this change LUT size */
+
+/* #define USE_BNS_DUAL_PREVIEW */ /* use bds on recording scenario. this change LUT size */
+/* #define USE_BNS_DUAL_RECORDING */ /* use bds on recording scenario. this change LUT size */
+
+/* #define USE_UHD_RECORDING */
+/* #define USE_WQHD_RECORDING */
+/* #define FPS_CHECK */
+#define FIRST_PREVIEW_TIME_CHECK /* to get time startPreview() ~ first preview frame q to hwc */
+#define USE_FD_AE
+#define FD_ROTATION                     (true)
+/* #define USE_FRONT_PREVIEW_DRC */
+
+#define CAMERA_PREVIEW_EXPOSURE_TIME_LIMIT (100000)
+#define CAMERA_EXPOSURE_TIME_MAX           (500000)
+
+#define BURST_CAPTURE                   (true)
+#ifdef BURST_CAPTURE
+
+enum {
+    BURST_SAVE_PHONE = 0,
+    BURST_SAVE_SDCARD,
+    BURST_SAVE_CALLBACK,
+};
+
+
+#define DEFAULT_BURST_SAVE              (BURST_SAVE_CALLBACK)
+#define BURST_SHUTTER_PREPICTURE        (0)
+#define BURST_SHUTTER_PREPICTURE_DONE   (1)
+#define BURST_SHUTTER_JPEGCB            (2)
+#endif
+
+#define SHOT_RECOVERY                   (true)
+#define SHOT_RECOVERY_ONEBYONE          (true)
+#ifdef SHOT_RECOVERY
+#define SHOT_RECOVERY_COUNT             (0)
+#else
+#define SHOT_RECOVERY_COUNT             (0)
+#endif
+
+#define FRAME_SKIP_COUNT_RECORDING      (1)
+#define FRAME_SKIP_COUNT_PREVIEW        (0)
+#define FRAME_SKIP_COUNT_PREVIEW_FRONT  (3)
+
+#ifdef CAMERA_GED_FEATURE
+#define USE_ADAPTIVE_CSC_RECORDING      (true)
+#else
+#define USE_ADAPTIVE_CSC_RECORDING      (true)
+#endif
+
+#define SUPPORT_BACK_HW_VDIS            (false)
+#define SUPPORT_FRONT_HW_VDIS           (false)
+
+#define HW_VDIS_W_RATIO                 (1.2f)
+#define HW_VDIS_H_RATIO                 (1.2f)
+
+#ifdef CAMERA_GED_FEATURE
+#define USE_HIGHSPEED_RECORDING         (true)
+#else
+#define USE_HIGHSPEED_RECORDING         (true)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#define USE_FASTEN_AE_STABLE            (false)
+#else
+#define USE_FASTEN_AE_STABLE            (true)
+#endif
+
+// fastenAE size will get by getFastenAeStableBcropSize()
+/*
+#define FASTEN_AE_WIDTH                 (1472)
+#define FASTEN_AE_HEIGHT                (828)
+*/
+#define FASTEN_AE_FPS                   (120)
+#define FASTEN_AE_FPS_FRONT             (112)
+#define DEFAULT_BINNING_RATIO           (1)
+
+#ifdef USE_BNS_PREVIEW
+#define DEFAULT_BNS_RATIO               (1)
+#else
+#define DEFAULT_BNS_RATIO               (1)
+#endif
+
+#define USE_JPEG_HWFC                   (true)
+
+#define MAX_YUV_STREAM_COUNT            (3)
+#define YUV_FORMAT_MIN_DURATION         ( 33331760L)       /* 30 fps */
+
+#define USE_PURE_BAYER_REPROCESSING                    (false)
+#define USE_PURE_BAYER_REPROCESSING_ON_RECORDING       (false)
+#define USE_PURE_BAYER_REPROCESSING_ON_DUAL            (false)
+#define USE_PURE_BAYER_REPROCESSING_ON_DUAL_RECORDING  (false)
+
+#define USE_PURE_BAYER_REPROCESSING_FRONT              (false)
+#define USE_PURE_BAYER_REPROCESSING_FRONT_ON_RECORDING (false)
+#define USE_PURE_BAYER_REPROCESSING_FRONT_ON_DUAL      (false)
+#define USE_PURE_BAYER_REPROCESSING_FRONT_ON_DUAL_RECORDING  (false)
+
+#define USE_CAMERA_SIZE_TABLE           (true)
+
+/* #define USE_VARIABLE_FPS_OF_FRONT_RECORDING */
+
+/* This USE_DYNAMIC_BAYER define is for default scenario.
+ * See <ExynosCameraParameter.cpp> for details of dynamic bayer setting
+ */
+#define USE_DYNAMIC_BAYER                       (false)
+#define USE_DYNAMIC_BAYER_VIDEO_SNAP_SHOT       (false)
+
+#define USE_DYNAMIC_BAYER_FRONT                 (false)
+#define USE_DYNAMIC_BAYER_VIDEO_SNAP_SHOT_FRONT (false)
+
+#define USE_YUV_REPROCESSING                    (true)
+#define USE_YUV_REPROCESSING_FOR_THUMBNAIL      (true)
+
+enum REPROCESSING_BAYER_MODE {
+    REPROCESSING_BAYER_MODE_NONE            = 0, /* This means capture do not use reprocessing */
+    REPROCESSING_BAYER_MODE_PURE_ALWAYS_ON,
+    REPROCESSING_BAYER_MODE_DIRTY_ALWAYS_ON,
+    REPROCESSING_BAYER_MODE_PURE_DYNAMIC,
+    REPROCESSING_BAYER_MODE_DIRTY_DYNAMIC,
+    REPROCESSING_BAYER_MODE_MAX,
+};
+
+#define SET_FPS_FRONTCAM                (1)
+
+#define MAX_FACEDETECT_THREADQ_SIZE     (2)
+#define MAX_FOCUSCONTINUS_THREADQ_SIZE  (2)
+
+#define USE_DYNAMIC_SCC_REAR            (false)
+#define USE_DYNAMIC_SCC_FRONT           (false)
+
+#define USE_GSC_FOR_CAPTURE_BACK        (false)
+#define USE_GSC_FOR_CAPTURE_FRONT       (false)
+
+#define MAX_SERIES_SHOT_COUNT           (1000)
+
+#define SENSOR_FW_PATH_BACK "/sys/class/camera/rear/rear_camfw"
+#define SENSOR_FW_PATH_FRONT "/sys/class/camera/front/front_camfw"
+
+#define TORCH_REAR_FILE_PATH "/sys/devices/14400000.fimc_is/torch/flash_torch_control"
+#define TORCH_FRONT_FILE_PATH "/sys/devices/14400000.fimc_is/torch/flash_torch_control"
+
+#define SUPPORT_64BITS
+
+#ifndef DEBUG_RAWDUMP
+/* #define CAMERA_PACKED_BAYER_ENABLE */
+#endif
+/* #define USE_BUFFER_WITH_STRIDE */
+
+#define OWN_MCSC_HW                 (true)
+
+/* back */
+#define MAIN_CAMERA_FLITE_NUM                       FIMC_IS_VIDEO_SS0_NUM
+#define MAIN_CAMERA_HAS_OWN_SCC     (false)
+
+#define MAIN_CAMERA_SINGLE_FLITE_3AA_OTF (true)
+#define MAIN_CAMERA_DUAL_FLITE_3AA_OTF   (true)
+
+#define MAIN_CAMERA_SINGLE_3AA_ISP_OTF (true)
+#define MAIN_CAMERA_DUAL_3AA_ISP_OTF   (false)
+
+#define MAIN_CAMERA_SINGLE_MCSC_VRA_OTF (false)
+#define MAIN_CAMERA_DUAL_MCSC_VRA_OTF   (false)
+
+#define MAIN_CAMERA_SINGLE_REPROCESSING  (true)
+#define MAIN_CAMERA_SINGLE_SCC_CAPTURE   (false)
+
+#define MAIN_CAMERA_DUAL_REPROCESSING    (false)
+#define MAIN_CAMERA_DUAL_SCC_CAPTURE     (false)
+
+#define MAIN_CAMERA_SINGLE_3AA_ISP_OTF_REPROCESSING    (false)
+#define MAIN_CAMERA_DUAL_3AA_ISP_OTF_REPROCESSING      (false) /* need to be same with FRONT_CAMERA_DUAL_3AA_ISP_OTF on dual case */
+
+/* front */
+#define FRONT_CAMERA_FLITE_NUM                       FIMC_IS_VIDEO_SS1_NUM
+#define FRONT_CAMERA_HAS_OWN_SCC    (false)
+
+#define FRONT_CAMERA_SINGLE_FLITE_3AA_OTF (true)
+#define FRONT_CAMERA_DUAL_FLITE_3AA_OTF   (false)
+
+#define FRONT_CAMERA_SINGLE_3AA_ISP_OTF (true)
+#define FRONT_CAMERA_DUAL_3AA_ISP_OTF   (true)
+
+#define FRONT_CAMERA_SINGLE_MCSC_VRA_OTF (false)
+#define FRONT_CAMERA_DUAL_MCSC_VRA_OTF   (false)
+
+#define FRONT_CAMERA_SINGLE_REPROCESSING  (true)
+#define FRONT_CAMERA_SINGLE_SCC_CAPTURE   (false)
+
+#define FRONT_CAMERA_DUAL_REPROCESSING    (false)
+#define FRONT_CAMERA_DUAL_SCC_CAPTURE     (true)
+
+#define FRONT_CAMERA_SINGLE_3AA_ISP_OTF_REPROCESSING    (false)
+#define FRONT_CAMERA_DUAL_3AA_ISP_OTF_REPROCESSING      (false)
+
+#define USE_3AC_FOR_ISPC            (true)
+
+#define CAMERA_HAS_OWN_BDS          (false)
+
+#define SCENARIO_SHIFT              (28)
+#define REPROCESSING_SHIFT          (28)
+#define OTF_3AA_SHIFT               (24)
+#define SSX_VINDEX_SHIFT            (16)
+#define TAX_VINDEX_SHIFT            (8)
+
+#define SENSOR_NOBLOCK_SHIFT        (28)
+#define SENSOR_INSTANT_SHIFT        (16)
+#define SENSOR_SSTREAM_SHIFT        (0)
+
+#define INPUT_STREAM_MASK   0xFF000000 /* stream type : 1 (reprocessing) */
+#define INPUT_STREAM_SHIFT   24
+#define INPUT_MODULE_MASK   0x00FF0000 /* module id : unique sensor id */
+#define INPUT_MODULE_SHIFT   16
+#define INPUT_VINDEX_MASK   0x0000FF00 /* video node index : connected node */
+#define INPUT_VINDEX_SHIFT   8
+#define INPUT_MEMORY_MASK   0x000000F0 /* memory interface : 0 (on-the-fly) */
+#define INPUT_MEMORY_SHIFT   4
+#define INPUT_LEADER_MASK   0x0000000F /* leader : 1 (leader video node) */
+#define INPUT_LEADER_SHIFT   0
+
+#define PREVIEW_GSC_NODE_NUM            (4)  /* 4 = MSC from Exynos5420 */
+#define PICTURE_GSC_NODE_NUM            (4)  /* 0,1,2 = GSC */
+#define VIDEO_GSC_NODE_NUM              (4)
+
+/* #define USE_INTERNAL_FRAME */
+#ifdef USE_INTERNAL_FRAME
+#define NUM_INTERNAL_FRAME_COUNT        (3)
+#define NUM_INTERNAL_FRAME_BUFFERS      (30) /* HAL3.2 internal frame */
+#else
+#define NUM_INTERNAL_FRAME_COUNT        (0)
+#define NUM_INTERNAL_FRAME_BUFFERS      (30) /* HAL3.2 internal frame */
+#endif
+
+#define NUM_REQUEST_PREVIEW_BUFFER      (9)
+#define NUM_REQUEST_CALLBACK_BUFFER     (9)
+#define NUM_REQUEST_VIDEO_BUFFER        (8)
+#define NUM_REQUEST_JPEG_BUFFER         (5)
+#define NUM_REQUEST_RAW_BUFFER          (6)
+#define NUM_SERVICE_PREVIEW_BUFFER      (2)
+#define NUM_SERVICE_CALLBACK_BUFFER     (5)
+#define NUM_SERVICE_VIDEO_BUFFER        (9)
+#define NUM_SERVICE_JPEG_BUFFER         (6)
+#define NUM_SERVICE_RAW_BUFFER          (6)
+
+#define FPS120_NUM_REQUEST_RAW_BUFFER       (NUM_REQUEST_RAW_BUFFER)
+#define FPS120_NUM_REQUEST_PREVIEW_BUFFER   (NUM_REQUEST_PREVIEW_BUFFER * 3)
+#define FPS120_NUM_REQUEST_CALLBACK_BUFFER  (NUM_REQUEST_CALLBACK_BUFFER * 3)
+#define FPS120_NUM_REQUEST_VIDEO_BUFFER     (NUM_REQUEST_VIDEO_BUFFER * 3)
+#define FPS120_NUM_REQUEST_JPEG_BUFFER      (NUM_REQUEST_JPEG_BUFFER)
+#define FPS120_NUM_SERVICE_RAW_BUFFER       (6)
+#define FPS120_NUM_SERVICE_PREVIEW_BUFFER   (1 + 19)
+#define FPS120_NUM_SERVICE_CALLBACK_BUFFER  (15)
+#define FPS120_NUM_SERVICE_VIDEO_BUFFER     (5)
+#define FPS120_NUM_SERVICE_JPEG_BUFFER      (1)
+
+/* This define was used for processCaptureRequest to keep minimum request count */
+#define NUM_REQUEST_BLOCK_MAX           (NUM_REQUEST_PREVIEW_BUFFER)
+#define NUM_REQUEST_BLOCK_MIN           (6)
+
+/***********************
+ * Time Configurations *
+ ***********************/
+#define HDR_DELAY                       (3)
+#define SENSOR_CONTROL_DELAY            (2)
+#ifdef OIS_CAPTURE
+#define OISCAPTURE_DELAY                (2)
+#endif
+
+#define MULTIPLE_VSYNC_DETECT_OFFSET_NS     (3000000)
+#define FRAME_SCHEDULE_OFFSET_NS            (1000000)
+#define FRAME_DURATION_OFFSET_US            (1000)
+
+#define HIGH_RESOLUTION_MIN_PIXEL_SIZE  (12 * 1024 * 1024) /* 12MP pixel */
+#define FHD_PIXEL_SIZE                  (1920 * 1080)
+#define STALL_FORMAT_MIN_DURATION       ( 50000000L) /* 20 fps */
+#define HIGH_RESOLUTION_MIN_DURATION    (100000000L) /* 10 fps */
+
+
+#if (SUPPORT_BACK_HW_VDIS || SUPPORT_FRONT_HW_VDIS)
+/*
+ * HACK
+ * When enable hw vdis, one more M2M case is happen(isp -> tpu).
+ * we meet frame drop(2,3 per sec), because of memory lack.
+ * so, just increase buffer to avoid frame drop.
+ */
+#define MAX_BUFFERS                     (32)
+#define NUM_SENSOR_BUFFERS              (4 + REPROCESSING_BAYER_HOLD_COUNT)
+#define NUM_BAYER_BUFFERS               (4 + REPROCESSING_BAYER_HOLD_COUNT + SHOT_RECOVERY_COUNT)
+#define INIT_BAYER_BUFFERS              (4 + SHOT_RECOVERY_COUNT)
+#define NUM_3AA_BUFFERS                 NUM_BAYER_BUFFERS + 3
+#define NUM_HW_DIS_BUFFERS              (NUM_3AA_BUFFERS)
+#define NUM_VRA_BUFFERS                 (2)
+#define NUM_PREVIEW_BUFFERS             (9 + SHOT_RECOVERY_COUNT + 3)
+#define NUM_PREVIEW_SPARE_BUFFERS       (3)
+#define INIT_SCP_BUFFERS                (5)
+#define NUM_PICTURE_BUFFERS             (4)
+#define NUM_REPROCESSING_BUFFERS        (1)
+#define NUM_RECORDING_BUFFERS           (8)
+#define NUM_FASTAESTABLE_BUFFERS        (10)
+#define NUM_PREVIEW_BUFFERS_MARGIN      (1)
+#else
+
+#define MAX_BUFFERS                     (32)
+#define NUM_SENSOR_BUFFERS              (4 + REPROCESSING_BAYER_HOLD_COUNT)
+#define NUM_BAYER_BUFFERS               (1 + REPROCESSING_BAYER_HOLD_COUNT + SHOT_RECOVERY_COUNT)
+#define INIT_BAYER_BUFFERS              (4 + SHOT_RECOVERY_COUNT)
+#define NUM_3AA_BUFFERS                 (MAX_BUFFERS)
+#define NUM_HW_DIS_BUFFERS              (NUM_3AA_BUFFERS + 3)
+#define NUM_VRA_BUFFERS                 (2)
+#define NUM_PREVIEW_BUFFERS             (9 + SHOT_RECOVERY_COUNT + 3)
+#define NUM_PREVIEW_SPARE_BUFFERS       (3)
+#define INIT_SCP_BUFFERS                (5)
+#define NUM_PICTURE_BUFFERS             (8)
+#define NUM_REPROCESSING_BUFFERS        (1)
+#define NUM_RECORDING_BUFFERS           (8)
+#define NUM_FASTAESTABLE_BUFFERS        (10)
+#define NUM_PREVIEW_BUFFERS_MARGIN      (1)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#define RESERVED_NUM_BAYER_BUFFERS      (NUM_BAYER_BUFFERS)
+#define RESERVED_NUM_ISP_BUFFERS        (0)
+#else
+#ifdef DEBUG_RAWDUMP
+#define RESERVED_NUM_BAYER_BUFFERS      (0)
+#define RESERVED_NUM_ISP_BUFFERS        (0)
+#else
+#define RESERVED_NUM_BAYER_BUFFERS      (5)
+#define RESERVED_NUM_ISP_BUFFERS        (3)
+#endif /* DEBUG_RAWDUMP */
+#endif
+
+#define PIPE_FLITE_PREPARE_COUNT            (0)
+#define PIPE_3AC_PREPARE_COUNT              (3)
+#define PIPE_3AA_ISP_PREPARE_COUNT          (3)
+#define PIPE_3AA_PREPARE_COUNT              (2)
+#define PIPE_ISP_PREPARE_COUNT              (0)
+#define PIPE_SCC_PREPARE_COUNT              (1)
+#define PIPE_SCP_PREPARE_COUNT              (3)
+
+#define PIPE_FLITE_FRONT_PREPARE_COUNT      (0)
+#define PIPE_SCC_FRONT_PREPARE_COUNT        (1)
+#define PIPE_SCP_FRONT_PREPARE_COUNT        (3)
+#define PIPE_SCP_REPROCESSING_PREPARE_COUNT (3)
+#define PIPE_SCC_REPROCESSING_PREPARE_COUNT (1)
+
+#define NUM_FRAME_PREPARE_COUNT         (6)
+#define NUM_BURST_GSC_JPEG_INIT_BUFFER  (4) /* Number of pre-allicated buffer for burst shot
+                                               Increasing this number will increase takePicture()'s
+                                               response time. Currently it is defined as
+                                               (# of JPEG save thread) + 1 */
+
+/* TO DO : will remove */
+#define REPROCESSING_BAYER_HOLD_COUNT   (1)
+#define FRONT_NUM_BAYER_BUFFERS         (NUM_BAYER_BUFFERS)
+#define FRONT_NUM_3AA_BUFFERS           (NUM_3AA_BUFFERS)
+#define FRONT_NUM_PICTURE_BUFFERS       (NUM_PICTURE_BUFFERS)
+
+#ifdef DEBUG_RAWDUMP
+#define FRONT_RESERVED_NUM_BAYER_BUFFERS        (0)
+#define FRONT_RESERVED_NUM_ISP_BUFFERS          (0)
+#else
+#define FRONT_RESERVED_NUM_BAYER_BUFFERS        (6)
+#define FRONT_RESERVED_NUM_ISP_BUFFERS          (0)
+#endif /* DEBUG_RAWDUMP */
+
+#define MFC_7X_BUFFER_OFFSET            (256)
+
+#if (USE_HIGHSPEED_RECORDING)
+#define FPS60_NUM_SENSOR_BUFFERS         (NUM_SENSOR_BUFFERS + 5)
+#define FPS60_NUM_NUM_BAYER_BUFFERS          (NUM_BAYER_BUFFERS + 5)
+#define FPS60_INIT_BAYER_BUFFERS             (INIT_BAYER_BUFFERS * 2)
+#define FPS60_NUM_HW_DIS_BUFFERS             (NUM_HW_DIS_BUFFERS + 5)
+#define FPS60_NUM_VRA_BUFFERS                (2)
+#define FPS60_NUM_PREVIEW_BUFFERS            (NUM_PREVIEW_BUFFERS + 7)
+#define FPS60_NUM_PICTURE_BUFFERS            (NUM_PICTURE_BUFFERS)
+#define FPS60_NUM_REPROCESSING_BUFFERS       (NUM_REPROCESSING_BUFFERS)
+#define FPS60_NUM_RECORDING_BUFFERS          (NUM_RECORDING_BUFFERS + 5)
+#define FPS60_INITIAL_SKIP_FRAME             (INITIAL_SKIP_FRAME)
+#define FPS60_REPROCESSING_BAYER_HOLD_COUNT  (REPROCESSING_BAYER_HOLD_COUNT)
+#define FPS60_FRONT_NUM_BAYER_BUFFERS        (FRONT_NUM_BAYER_BUFFERS)
+#define FPS60_FRONT_NUM_PICTURE_BUFFERS      (FRONT_NUM_PICTURE_BUFFERS)
+#define FPS60_NUM_PREVIEW_BUFFERS_MARGIN     (NUM_PREVIEW_BUFFERS_MARGIN + 1)
+#define FPS60_NUM_REQUEST_BLOCK_MAX          (FPS60_NUM_PREVIEW_BUFFERS)
+#define FPS60_NUM_REQUEST_BLOCK_MIN          (FPS60_INIT_BAYER_BUFFERS + 2)
+
+#define FPS60_PIPE_FLITE_PREPARE_COUNT       (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_3AC_PREPARE_COUNT         (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_3AA_ISP_PREPARE_COUNT     (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_3AA_PREPARE_COUNT         (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_SCP_PREPARE_COUNT         (FPS60_INIT_BAYER_BUFFERS)
+#define FPS60_PIPE_SCP_REPROCESSING_PREPARE_COUNT (3)
+
+#define FPS120_NUM_SENSOR_BUFFERS            (NUM_SENSOR_BUFFERS * 3)
+#define FPS120_NUM_NUM_BAYER_BUFFERS         (NUM_BAYER_BUFFERS * 3)
+#define FPS120_INIT_BAYER_BUFFERS            (INIT_BAYER_BUFFERS * 3)
+#define FPS120_NUM_3AA_BUFFERS               (NUM_3AA_BUFFERS)
+#define FPS120_NUM_HW_DIS_BUFFERS            (NUM_HW_DIS_BUFFERS * 3)
+#define FPS120_NUM_VRA_BUFFERS               (2)
+#define FPS120_NUM_PREVIEW_BUFFERS           (NUM_PREVIEW_BUFFERS * 3)
+#define FPS120_NUM_PICTURE_BUFFERS           (NUM_PICTURE_BUFFERS)
+#define FPS120_NUM_REPROCESSING_BUFFERS      (NUM_REPROCESSING_BUFFERS)
+#define FPS120_NUM_RECORDING_BUFFERS         (NUM_RECORDING_BUFFERS * 3)
+#define FPS120_NUM_FASTAESTABLE_BUFFERS      (NUM_FASTAESTABLE_BUFFERS)
+#define FPS120_INITIAL_SKIP_FRAME            (INITIAL_SKIP_FRAME)
+#define FPS120_REPROCESSING_BAYER_HOLD_COUNT (REPROCESSING_BAYER_HOLD_COUNT)
+#define FPS120_FRONT_NUM_BAYER_BUFFERS       (FRONT_NUM_BAYER_BUFFERS)
+#define FPS120_FRONT_NUM_PICTURE_BUFFERS     (FRONT_NUM_PICTURE_BUFFERS)
+#define FPS120_NUM_PREVIEW_BUFFERS_MARGIN    (NUM_PREVIEW_BUFFERS_MARGIN + 1)
+#define FPS120_NUM_REQUEST_BLOCK_MAX         (FPS120_NUM_PREVIEW_BUFFERS)
+#define FPS120_NUM_REQUEST_BLOCK_MIN         (FPS120_INIT_BAYER_BUFFERS + 8)
+
+#define FPS120_PIPE_FLITE_PREPARE_COUNT       (3)
+#define FPS120_PIPE_3AC_PREPARE_COUNT         (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_3AA_ISP_PREPARE_COUNT     (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_3AA_PREPARE_COUNT         (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_SCP_PREPARE_COUNT         (FPS120_INIT_BAYER_BUFFERS)
+#define FPS120_PIPE_SCP_REPROCESSING_PREPARE_COUNT (3)
+#endif
+
+#define V4L2_CAMERA_MEMORY_TYPE         (V4L2_MEMORY_DMABUF) /* (V4L2_MEMORY_USERPTR) */
+#define SCC_OUTPUT_COLOR_FMT            (V4L2_PIX_FMT_YUYV)
+#define JPEG_INPUT_COLOR_FMT            (SCC_OUTPUT_COLOR_FMT)
+#define CAMERA_BAYER_FORMAT             (V4L2_PIX_FMT_SBGGR12)
+#define CAMERA_DUMP_BAYER_FORMAT        (V4L2_PIX_FMT_SBGGR16)
+
+#define ERROR_POLLING_DETECTED          (-1001)
+#define ERROR_DQ_BLOCKED_DETECTED       (-1002)
+#define ERROR_DQ_BLOCKED_COUNT          (20)
+#define WARNING_3AA_THREAD_INTERVAL     (100000)
+#define WARNING_SCP_THREAD_INTERVAL     (100000)
+#define MONITOR_THREAD_INTERVAL         (200000)
+
+#define FRAME_MIN_NUM (3)
+
+#define EXYNOS_CAMERA_BUFFER_MAX_PLANES (5)     /* img buffer 4 + metadata 1 */
+#define EXYNOS_CAMERA_META_PLANE_SIZE   (32 * 1024)
+#define GRALLOC_LOCK_FOR_CAMERA         (GRALLOC_SET_USAGE_FOR_CAMERA)
+
+#define EXYNOS_CAMERA_PREVIEW_FPS_REFERENCE  (60)
+
+#define  NUM_OF_DETECTED_FACES           (16)
+#define  NUM_OF_DETECTED_FACES_THRESHOLD (0)
+
+#define PERFRAME_NODE_GROUP_MAX          (5)
+#define PERFRAME_NODE_GROUP_0            (0)
+#define PERFRAME_NODE_GROUP_1            (1)
+#define PERFRAME_NODE_GROUP_2            (2)
+#define PERFRAME_NODE_GROUP_3            (3)
+#define PERFRAME_NODE_GROUP_4            (4)
+
+#define PERFRAME_INFO_INDEX_MAX          (5)
+#define PERFRAME_INFO_INDEX_0            (0)
+#define PERFRAME_INFO_INDEX_1            (1)
+#define PERFRAME_INFO_INDEX_2            (2)
+#define PERFRAME_INFO_INDEX_3            (3)
+#define PERFRAME_INFO_INDEX_4            (4)
+
+#define PERFRAME_CONTROL_PIPE                   PIPE_3AA
+#define PERFRAME_CONTROL_REPROCESSING_PIPE      PIPE_3AA_REPROCESSING
+#define PERFRAME_CONTROL_NODE_3AA
+/* #define PERFRAME_CONTROL_NODE_ISP */
+#define PERFRAME_INFO_3AA                       PERFRAME_INFO_INDEX_0
+#define PERFRAME_INFO_ISP                       PERFRAME_INFO_INDEX_1
+#define PERFRAME_INFO_DIS                       PERFRAME_INFO_INDEX_2
+#define PERFRAME_INFO_MCSC                      PERFRAME_INFO_INDEX_3
+#define PERFRAME_INFO_VRA                       PERFRAME_INFO_INDEX_4
+
+#define PERFRAME_INFO_PURE_REPROCESSING_3AA     PERFRAME_INFO_INDEX_0
+#define PERFRAME_INFO_PURE_REPROCESSING_ISP     PERFRAME_INFO_INDEX_1
+#define PERFRAME_INFO_PURE_REPROCESSING_MCSC    PERFRAME_INFO_INDEX_2
+
+#define PERFRAME_INFO_DIRTY_REPROCESSING_ISP    PERFRAME_INFO_INDEX_0
+#define PERFRAME_INFO_DIRTY_REPROCESSING_MCSC   PERFRAME_INFO_INDEX_1
+
+#define PERFRAME_INFO_YUV_REPROCESSING_MCSC     PERFRAME_INFO_INDEX_0
+
+#define PERFRAME_3AA_POS                        PER_FRAME_GROUP_0
+#define PERFRAME_ISP_POS                        PER_FRAME_GROUP_1
+
+#define PERFRAME_BACK_3AC_POS           (0)
+#define PERFRAME_BACK_3AP_POS           (1)
+#define PERFRAME_BACK_ISPC_POS          (0)
+#define PERFRAME_BACK_ISPP_POS          (2)
+#define PERFRAME_BACK_SCC_POS           (3)
+#define PERFRAME_BACK_SCP_POS           (3)
+#define PERFRAME_BACK_MCSC0_POS         (0)
+#define PERFRAME_BACK_MCSC1_POS         (0)
+#define PERFRAME_BACK_MCSC2_POS         (0)
+
+/*
+#define PERFRAME_FRONT_3AC_POS          (1)
+#define PERFRAME_FRONT_3AP_POS          (0)
+#define PERFRAME_FRONT_SCC_POS          (0)
+#define PERFRAME_FRONT_SCP_POS          (1)
+*/
+#define PERFRAME_FRONT_3AC_POS          (PERFRAME_BACK_3AC_POS)
+#define PERFRAME_FRONT_3AP_POS          (PERFRAME_BACK_3AP_POS)
+#define PERFRAME_FRONT_ISPC_POS         (PERFRAME_BACK_ISPC_POS)
+#define PERFRAME_FRONT_ISPP_POS         (PERFRAME_BACK_ISPP_POS)
+#define PERFRAME_FRONT_SCC_POS          (PERFRAME_BACK_SCC_POS)
+#define PERFRAME_FRONT_SCP_POS          (PERFRAME_BACK_SCP_POS)
+
+#define PERFRAME_REPROCESSING_3AP_POS   (0)
+#define PERFRAME_REPROCESSING_3AC_POS   (1)
+#define PERFRAME_REPROCESSING_SCC_POS   (2) /* be care of source code, when you change. */
+#define PERFRAME_REPROCESSING_ISPC_POS    (0)
+#define PERFRAME_REPROCESSING_ISPP_POS    (0)
+#define PERFRAME_REPROCESSING_MCSC0_POS   (PERFRAME_REPROCESSING_SCC_POS)
+#define PERFRAME_REPROCESSING_MCSC2_POS   (0)
+#define PERFRAME_REPROCESSING_MCSC3_POS   (0)
+#define PERFRAME_REPROCESSING_MCSC4_POS   (0)
+
+#define WAITING_TIME                     (5000)   /* 5msec */
+#define TOTAL_WAITING_TIME               (3000 * 1000)  /* 3000msec */
+#define TOTAL_WAITING_COUNT              (3)
+#define TOTAL_FLASH_WATING_COUNT         (10)
+#define CAPTURE_WAITING_COUNT            (15)
+
+#define DM_WAITING_TIME                  (30 * 1000) /* 30msec */
+#define DM_WAITING_COUNT                 (10)
+
+/*vision */
+/* #define VISION_DUMP */
+#define VISION_WIDTH                     (320)
+#define VISION_HEIGHT                    (180)
+
+/* callback state */
+#define CALLBACK_STATE_PREVIEW_META     (1)
+#define CALLBACK_STATE_PREVIEW_FRAME    (2)
+#define CALLBACK_STATE_RAW_IMAGE        (3)
+#define CALLBACK_STATE_POSTVIEW_FRAME   (4)
+#define CALLBACK_STATE_COMPRESSED_IMAGE (5)
+
+#define MAGIC_SHOT_DURATION         125000  /* 8fps */
+#define BEST_PHOTO_DURATION         195000  /* about 5fps */
+#define BEST_FACE_DURATION          400000  /* 2.5fps */
+#define ERASER_DURATION             800000  /* 1.25fps */
+#define NORMAL_BURST_DURATION       90000   /* about 11fps */
+#define SELFIE_ALARM_DURATION       330000  /* about 3fps */
+
+#define USE_MEM2MEM_GSC
+
+#ifdef USE_MEM2MEM_GSC
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP | \
+     GRALLOC_USAGE_HW_CAMERA_MASK)
+#else
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP)
+#endif
+
+enum YUV_RANGE {
+    YUV_FULL_RANGE = 0,
+    YUV_LIMITED_RANGE = 1,
+};
+
+enum pipeline {
+    PIPE_FLITE                  = 0,
+    PIPE_3AA,
+    PIPE_3AC,
+    PIPE_3AP,
+    PIPE_ISP,
+    PIPE_ISPC,
+    PIPE_ISPP,
+    PIPE_DIS,
+    PIPE_MCSC,
+    PIPE_SCP,
+    PIPE_MCSC0 = PIPE_SCP,
+    PIPE_MCSC1,
+    PIPE_MCSC2,
+    PIPE_MCSC3,
+    PIPE_MCSC4,
+    PIPE_VRA,
+    PIPE_3AA_ISP,
+    PIPE_POST_3AA_ISP,
+    PIPE_SCC,
+    PIPE_GSC,
+    PIPE_GSC_VIDEO,
+    PIPE_GSC_VRA,
+    PIPE_GSC_PICTURE,
+    PIPE_JPEG,
+    MAX_PIPE_NUM,
+
+    /*
+     * PIPE_XXX_FRONT are deprecated define.
+     * Don't use this. (just let for common code compile)
+     */
+    PIPE_FLITE_FRONT = 100,
+    PIPE_3AA_FRONT,
+    PIPE_3AC_FRONT,
+    PIPE_3AP_FRONT,
+    PIPE_ISP_FRONT,
+    PIPE_ISPC_FRONT,
+    PIPE_ISPP_FRONT,
+    PIPE_SCP_FRONT,
+    PIPE_3AA_ISP_FRONT,
+    PIPE_POST_3AA_ISP_FRONT,
+    PIPE_DIS_FRONT,
+    PIPE_SCC_FRONT,
+    PIPE_GSC_FRONT,
+    PIPE_GSC_VIDEO_FRONT,
+    PIPE_GSC_PICTURE_FRONT,
+    PIPE_JPEG_FRONT,
+    MAX_PIPE_NUM_FRONT,
+
+    PIPE_FLITE_REPROCESSING     = 200,
+    PIPE_3AA_REPROCESSING,
+    PIPE_3AC_REPROCESSING,
+    PIPE_3AP_REPROCESSING,
+    PIPE_ISP_REPROCESSING,
+    PIPE_ISPC_REPROCESSING,
+    PIPE_ISPP_REPROCESSING,
+    PIPE_MCSC_REPROCESSING,
+    PIPE_MCSC0_REPROCESSING,
+    PIPE_MCSC1_REPROCESSING,
+    PIPE_MCSC2_REPROCESSING,
+    PIPE_MCSC3_REPROCESSING,
+    PIPE_MCSC4_REPROCESSING,
+    PIPE_SCC_REPROCESSING,
+    PIPE_SCP_REPROCESSING,
+    PIPE_GSC_REPROCESSING,
+    PIPE_GSC_REPROCESSING2,
+    PIPE_GSC_REPROCESSING3,
+#ifdef UVS
+    PIPE_UVS_REPROCESSING,
+#endif
+    PIPE_JPEG_REPROCESSING,
+    PIPE_HWFC_JPEG_SRC_REPROCESSING,
+    PIPE_HWFC_THUMB_SRC_REPROCESSING,
+    PIPE_HWFC_JPEG_DST_REPROCESSING,
+    PIPE_HWFC_THUMB_DST_REPROCESSING,
+    MAX_PIPE_NUM_REPROCESSING
+};
+
+enum fimc_is_video_dev_num {
+    FIMC_IS_VIDEO_BAS_NUM = 100,
+    FIMC_IS_VIDEO_SS0_NUM = 101,
+    FIMC_IS_VIDEO_SS1_NUM,
+    FIMC_IS_VIDEO_SS2_NUM,
+    FIMC_IS_VIDEO_SS3_NUM,
+    FIMC_IS_VIDEO_30S_NUM = 110,
+    FIMC_IS_VIDEO_30C_NUM,
+    FIMC_IS_VIDEO_30P_NUM,
+    FIMC_IS_VIDEO_31S_NUM = 120,
+    FIMC_IS_VIDEO_31C_NUM,
+    FIMC_IS_VIDEO_31P_NUM,
+    FIMC_IS_VIDEO_I0S_NUM = 130,
+    FIMC_IS_VIDEO_I0C_NUM,
+    FIMC_IS_VIDEO_I0P_NUM,
+    FIMC_IS_VIDEO_I1S_NUM = 140,
+    FIMC_IS_VIDEO_I1C_NUM,
+    FIMC_IS_VIDEO_I1P_NUM,
+    FIMC_IS_VIDEO_TPU_NUM = 150,
+    FIMC_IS_VIDEO_SCC_NUM,
+    FIMC_IS_VIDEO_SCP_NUM,
+    FIMC_IS_VIDEO_M0S_NUM = 160,
+    FIMC_IS_VIDEO_M1S_NUM,
+    FIMC_IS_VIDEO_M0P_NUM = 170,
+    FIMC_IS_VIDEO_M1P_NUM,
+    FIMC_IS_VIDEO_M2P_NUM,
+    FIMC_IS_VIDEO_M3P_NUM,
+    FIMC_IS_VIDEO_M4P_NUM,
+    FIMC_IS_VIDEO_VRA_NUM = 180,
+    FIMC_IS_VIDEO_HWFC_JPEG_NUM = 200,
+    FIMC_IS_VIDEO_HWFC_THUMB_NUM = 201,
+    FIMC_IS_VIDEO_MAX_NUM
+};
+
+#define MAIN_CAMERA_COMPANION_NUM   (109)
+#define FRONT_CAMERA_COMPANION_NUM  (109)
+
+enum frame_generation_mode_enum {
+    EXYNOS_GENERATE_SKIP_FRAME = 0,
+    EXYNOS_GENERATE_FAST_AE_STABLE_FRAME = 1,
+    EXYNOS_GENERATE_DYNAMIC_BAYER_FRAME = 2,
+    EXYNOS_GENERATE_NORMAL_FRAME = 3,
+    EXYNOS_GENERATE_FRAME_MAX
+};
+
+/* This struct used in recording callback */
+/* This struct passes to OMX */
+struct addrs {
+    uint32_t        type;       /* make sure that this is 4 byte. */
+    unsigned int    fdPlaneY;
+    unsigned int    fdPlaneCbcr;
+    unsigned int    bufIndex;
+    unsigned int    reserved;
+};
+
+/* overflow handling */
+#define SENSOR_OVERFLOW_CHECK
+
+/* for test */
+/* #define SCALABLE_ON */
+/* #define TEST_GED_HIGH_SPEED_RECORDING */
+/* #define TEST_APP_HIGH_SPEED_RECORDING */ /* for ArtCamera */
+/* #define FORCE_RESET_MULTI_FRAME_FACTORY */
+#endif /*USE_VENDOR_SPECIFIC_CONFIG_HEADER*/
+
+#endif /* EXYNOS_CAMERA_CONFIG_H__ */
diff --git a/libcamera3/ExynosCameraAvailabilityTable.h b/libcamera3/ExynosCameraAvailabilityTable.h
new file mode 100644 (file)
index 0000000..faec4b8
--- /dev/null
@@ -0,0 +1,1187 @@
+/*
+** Copyright 2015, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef EXYNOS_CAMERA_AVAILABILITY_TABLE_H
+#define EXYNOS_CAMERA_AVAILABILITY_TABLE_H
+
+#include <hardware/camera3.h>
+#include <camera/CameraMetadata.h>
+
+/* Android ColorCorrection Static Metadata */
+static uint8_t AVAILABLE_COLOR_CORRECTION_ABERRATION_MODES[] =
+{
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,
+    //ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
+    //ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY,
+};
+
+/* Android Control Static Metadata */
+static uint8_t AVAILABLE_ANTIBANDING_MODES[] =
+{
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
+};
+
+/* ANDROID_LENS_FACING_FRONT */
+static uint8_t AVAILABLE_AE_MODES_FRONT[] =
+{
+    ANDROID_CONTROL_AE_MODE_OFF,
+    ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH,
+    //ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
+    //ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
+};
+/* ANDROID_LENS_FACING_BACK */
+static uint8_t AVAILABLE_AE_MODES_BACK[] =
+{
+    ANDROID_CONTROL_AE_MODE_OFF,
+    ANDROID_CONTROL_AE_MODE_ON,
+    ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH,
+    ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
+    //ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
+};
+
+/* ANDROID_LENS_FACING_FRONT */
+static uint8_t AVAILABLE_AF_MODES_FRONT[] =
+{
+    ANDROID_CONTROL_AF_MODE_OFF,
+    //ANDROID_CONTROL_AF_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_MACRO,
+    //ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+    //ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
+    //ANDROID_CONTROL_AF_MODE_EDOF,
+};
+/* ANDROID_LENS_FACING_BACK */
+static uint8_t AVAILABLE_AF_MODES_BACK[] =
+{
+    ANDROID_CONTROL_AF_MODE_OFF,
+    ANDROID_CONTROL_AF_MODE_AUTO,
+    ANDROID_CONTROL_AF_MODE_MACRO,
+    ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+    ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
+    //ANDROID_CONTROL_AF_MODE_EDOF,
+};
+
+static uint8_t AVAILABLE_EFFECT_MODES[] =
+{
+    ANDROID_CONTROL_EFFECT_MODE_OFF,
+    ANDROID_CONTROL_EFFECT_MODE_MONO,
+    ANDROID_CONTROL_EFFECT_MODE_NEGATIVE,
+    //ANDROID_CONTROL_EFFECT_MODE_SOLARIZE,
+    ANDROID_CONTROL_EFFECT_MODE_SEPIA,
+    ANDROID_CONTROL_EFFECT_MODE_POSTERIZE,
+    //ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD,
+    //ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD,
+    ANDROID_CONTROL_EFFECT_MODE_AQUA,
+};
+
+static uint8_t AVAILABLE_SCENE_MODES[] =
+{
+    ANDROID_CONTROL_SCENE_MODE_DISABLED,
+    ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY,
+    //ANDROID_CONTROL_SCENE_MODE_ACTION,               /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_PORTRAIT,             /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_LANDSCAPE,            /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_NIGHT,                        /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT,       /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_THEATRE,              /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_BEACH,                        /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_SNOW,                 /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_SUNSET,               /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO,          /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_FIREWORKS,            /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_SPORTS,               /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_PARTY,                        /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT,          /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_BARCODE,              /* optional */
+    //ANDROID_CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO,     /* deprecated */
+    ANDROID_CONTROL_SCENE_MODE_HDR,
+};
+
+static uint8_t AVAILABLE_VIDEO_STABILIZATION_MODES[] =
+{
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
+    //ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON,
+};
+
+static uint8_t AVAILABLE_AWB_MODES[] =
+{
+    ANDROID_CONTROL_AWB_MODE_OFF,
+    ANDROID_CONTROL_AWB_MODE_AUTO,
+    ANDROID_CONTROL_AWB_MODE_INCANDESCENT,
+    ANDROID_CONTROL_AWB_MODE_FLUORESCENT,
+    //ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT,
+    ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+    ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT,
+    //ANDROID_CONTROL_AWB_MODE_TWILIGHT,
+    //ANDROID_CONTROL_AWB_MODE_SHADE,
+};
+
+static uint8_t AVAILABLE_CONTROL_MODES[] =
+{
+    ANDROID_CONTROL_MODE_OFF,
+    ANDROID_CONTROL_MODE_AUTO,
+    ANDROID_CONTROL_MODE_USE_SCENE_MODE,
+    //ANDROID_CONTROL_MODE_OFF_KEEP_STATE,
+};
+
+static uint8_t SCENE_MODE_OVERRIDES[] =
+{
+    /* ANDROID_CONTROL_SCENE_MODE_DISABLED */
+    ANDROID_CONTROL_AE_MODE_ON,
+    ANDROID_CONTROL_AWB_MODE_AUTO,
+    ANDROID_CONTROL_AF_MODE_AUTO,
+    /* ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY */
+    ANDROID_CONTROL_AE_MODE_ON,
+    ANDROID_CONTROL_AWB_MODE_AUTO,
+    ANDROID_CONTROL_AF_MODE_AUTO,
+    /* ANDROID_CONTROL_SCENE_MODE_ACTION */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_PORTRAIT */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_LANDSCAPE */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_NIGHT */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_THEATRE */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_BEACH */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_SNOW */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_AUTO,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_SUNSET */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_SUNSET */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_FIREWORKS */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_SPORTS */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_SCENE_MODE_PARTY,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_SUNSET */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_BARCODE */
+    //ANDROID_CONTROL_AE_MODE_ON,
+    //ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+    //ANDROID_CONTROL_AF_MODE_OFF,
+    /* ANDROID_CONTROL_SCENE_MODE_HDR */
+    ANDROID_CONTROL_AE_MODE_ON,
+    ANDROID_CONTROL_AWB_MODE_AUTO,
+    ANDROID_CONTROL_AF_MODE_AUTO,
+};
+
+/* Android Edge Static Metadata */
+static uint8_t AVAILABLE_EDGE_MODES[] =
+{
+    ANDROID_EDGE_MODE_OFF,
+    ANDROID_EDGE_MODE_FAST,
+    ANDROID_EDGE_MODE_HIGH_QUALITY, /* NOT supported */
+};
+
+/* Android Hot Pixel Static Metadata */
+static uint8_t AVAILABLE_HOT_PIXEL_MODES[] =
+{
+    ANDROID_HOT_PIXEL_MODE_OFF,
+    ANDROID_HOT_PIXEL_MODE_FAST,
+    ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY,
+};
+
+/* Android Lens Static Metadata */
+static uint8_t AVAILABLE_OPTICAL_STABILIZATION[] =
+{
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
+    //ANDROID_LENS_OPTICAL_STABILIZATION_MODE_ON,
+};
+
+/* Android Lens Static Metadata */
+static uint8_t AVAILABLE_OPTICAL_STABILIZATION_BACK[] =
+{
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
+    //ANDROID_LENS_OPTICAL_STABILIZATION_MODE_ON,
+};
+
+/* Android Noise Reduction Static Metadata */
+static uint8_t AVAILABLE_NOISE_REDUCTION_MODES[] =
+{
+    ANDROID_NOISE_REDUCTION_MODE_OFF,
+    ANDROID_NOISE_REDUCTION_MODE_FAST,
+    ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY,
+};
+
+/* Android Request Static Metadata */
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED */
+static uint8_t AVAILABLE_CAPABILITIES_LIMITED[] =
+{
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+};
+
+static uint8_t AVAILABLE_CAPABILITIES_LIMITED_BURST[] =
+{
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED add optional */
+static uint8_t AVAILABLE_CAPABILITIES_LIMITED_OPTIONAL[] =
+{
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL */
+static uint8_t AVAILABLE_CAPABILITIES_FULL[] =
+{
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+    //ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY */
+static uint8_t AVAILABLE_CAPABILITIES_LEGACY[] =
+{
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED */
+static int32_t AVAILABLE_REQUEST_KEYS_LIMITED[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_NOISE_REDUCTION_MODE,
+#if 1
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    ANDROID_TONEMAP_MODE,
+    ANDROID_COLOR_CORRECTION_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    /* ETC */
+    ANDROID_EDGE_MODE,
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+#endif
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+};
+
+static int32_t AVAILABLE_REQUEST_KEYS_LIMITED_OPTIONAL[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_JPEG_GPS_COORDINATES,
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+    ANDROID_JPEG_GPS_TIMESTAMP,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCAL_LENGTH,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    ANDROID_NOISE_REDUCTION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    //ANDROID_TONEMAP_CURVE_BLUE,
+    //ANDROID_TONEMAP_CURVE_GREEN,
+    //ANDROID_TONEMAP_CURVE_RED,
+    ANDROID_TONEMAP_MODE,
+#if 0
+    ANDROID_COLOR_CORRECTION_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    //ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+#endif
+    /* ETC */
+    //ANDROID_DEMOSAIC_MODE,  //future
+    ANDROID_EDGE_MODE,
+    //ANDROID_EDGE_STRENGTH,  //future
+    //ANDROID_SENSOR_TEST_PATTERN_MODE,
+    //ANDROID_STATISTICS_HISTOGRAM_MODE,      //future
+    //ANDROID_STATISTICS_SHARPNESS_MAP_MODE,  //future
+    ANDROID_REQUEST_ID,
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+};
+
+static int32_t AVAILABLE_REQUEST_KEYS_LIMITED_FRONT[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_JPEG_GPS_COORDINATES,
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+    ANDROID_JPEG_GPS_TIMESTAMP,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_NOISE_REDUCTION_MODE,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_EDGE_MODE,
+    ANDROID_TONEMAP_MODE,
+#if 0
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCAL_LENGTH,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    ANDROID_TONEMAP_CURVE_BLUE,
+    ANDROID_TONEMAP_CURVE_GREEN,
+    ANDROID_TONEMAP_CURVE_RED,
+    ANDROID_TONEMAP_MODE,
+    ANDROID_COLOR_CORRECTION_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    /* ETC */
+    //ANDROID_DEMOSAIC_MODE,  //future
+    ANDROID_EDGE_MODE,
+    //ANDROID_EDGE_STRENGTH,  //future
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+    //ANDROID_STATISTICS_HISTOGRAM_MODE,      //future
+    //ANDROID_STATISTICS_SHARPNESS_MAP_MODE,  //future
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+#endif
+    ANDROID_REQUEST_ID,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL */
+static int32_t AVAILABLE_REQUEST_KEYS_FULL[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_JPEG_GPS_COORDINATES,
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+    ANDROID_JPEG_GPS_TIMESTAMP,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCAL_LENGTH,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    ANDROID_TONEMAP_CURVE_BLUE,
+    ANDROID_TONEMAP_CURVE_GREEN,
+    ANDROID_TONEMAP_CURVE_RED,
+    ANDROID_TONEMAP_MODE,
+    ANDROID_COLOR_CORRECTION_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    /* ETC */
+    //ANDROID_DEMOSAIC_MODE,  //future
+    ANDROID_EDGE_MODE,
+    //ANDROID_EDGE_STRENGTH,  //future
+    ANDROID_NOISE_REDUCTION_MODE,
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+    //ANDROID_STATISTICS_HISTOGRAM_MODE,      //future
+    //ANDROID_STATISTICS_SHARPNESS_MAP_MODE,  //future
+    ANDROID_REQUEST_ID,
+};
+
+static int32_t AVAILABLE_REQUEST_KEYS_LEGACY[] =
+{
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED */
+static int32_t AVAILABLE_RESULT_KEYS_LIMITED[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_FLASH_STATE,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_NOISE_REDUCTION_MODE,
+#if 1
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    ANDROID_TONEMAP_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
+    ANDROID_SENSOR_GREEN_SPLIT,
+    ANDROID_SENSOR_NOISE_PROFILE,
+    /* ETC */
+    ANDROID_EDGE_MODE,
+    ANDROID_STATISTICS_SCENE_FLICKER,
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+#endif
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+};
+
+static int32_t AVAILABLE_RESULT_KEYS_LIMITED_OPTIONAL[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_FLASH_STATE,
+    ANDROID_JPEG_GPS_COORDINATES,
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+    ANDROID_JPEG_GPS_TIMESTAMP,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_STATISTICS_FACE_IDS,
+    ANDROID_STATISTICS_FACE_RECTANGLES,
+    ANDROID_STATISTICS_FACE_SCORES,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCAL_LENGTH,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_LENS_STATE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    ANDROID_NOISE_REDUCTION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    //ANDROID_TONEMAP_CURVE_BLUE,
+    //ANDROID_TONEMAP_CURVE_GREEN,
+    //ANDROID_TONEMAP_CURVE_RED,
+    ANDROID_TONEMAP_MODE,
+#if 0
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    //ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
+    ANDROID_SENSOR_GREEN_SPLIT,
+    ANDROID_SENSOR_NOISE_PROFILE,
+#endif
+    /* ETC */
+    ANDROID_EDGE_MODE,
+    ANDROID_STATISTICS_SCENE_FLICKER,
+    //ANDROID_SENSOR_TEST_PATTERN_MODE,
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+};
+
+static int32_t AVAILABLE_RESULT_KEYS_LIMITED_FRONT[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_FLASH_STATE,
+    ANDROID_JPEG_GPS_COORDINATES,
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+    ANDROID_JPEG_GPS_TIMESTAMP,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_NOISE_REDUCTION_MODE,
+#if 0
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCAL_LENGTH,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_LENS_STATE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    ANDROID_TONEMAP_CURVE_BLUE,
+    ANDROID_TONEMAP_CURVE_GREEN,
+    ANDROID_TONEMAP_CURVE_RED,
+    ANDROID_TONEMAP_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
+    ANDROID_SENSOR_GREEN_SPLIT,
+    ANDROID_SENSOR_NOISE_PROFILE,
+    /* ETC */
+    ANDROID_EDGE_MODE,
+    ANDROID_STATISTICS_SCENE_FLICKER,
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+#endif
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL */
+static int32_t AVAILABLE_RESULT_KEYS_FULL[] =
+{
+    /* REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE */
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+    ANDROID_CONTROL_AE_LOCK,
+    ANDROID_CONTROL_AE_MODE,
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+    ANDROID_CONTROL_AF_MODE,
+    ANDROID_CONTROL_AF_TRIGGER,
+    ANDROID_CONTROL_AWB_LOCK,
+    ANDROID_CONTROL_AWB_MODE,
+    ANDROID_CONTROL_CAPTURE_INTENT,
+    ANDROID_CONTROL_EFFECT_MODE,
+    ANDROID_CONTROL_MODE,
+    ANDROID_CONTROL_SCENE_MODE,
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+    ANDROID_FLASH_MODE,
+    ANDROID_FLASH_STATE,
+    ANDROID_JPEG_GPS_COORDINATES,
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+    ANDROID_JPEG_GPS_TIMESTAMP,
+    ANDROID_JPEG_ORIENTATION,
+    ANDROID_JPEG_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+    ANDROID_SCALER_CROP_REGION,
+    ANDROID_STATISTICS_FACE_DETECT_MODE,
+    ANDROID_STATISTICS_FACE_IDS,
+    ANDROID_STATISTICS_FACE_LANDMARKS,
+    ANDROID_STATISTICS_FACE_RECTANGLES,
+    ANDROID_STATISTICS_FACE_SCORES,
+    ANDROID_CONTROL_AE_REGIONS,
+    ANDROID_CONTROL_AWB_REGIONS,
+    ANDROID_CONTROL_AF_REGIONS,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR */
+    ANDROID_SENSOR_FRAME_DURATION,
+    ANDROID_SENSOR_EXPOSURE_TIME,
+    ANDROID_SENSOR_SENSITIVITY,
+    ANDROID_LENS_APERTURE,
+    ANDROID_LENS_FILTER_DENSITY,
+    ANDROID_LENS_FOCAL_LENGTH,
+    ANDROID_LENS_FOCUS_DISTANCE,
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+    ANDROID_LENS_STATE,
+    ANDROID_BLACK_LEVEL_LOCK,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING */
+    ANDROID_TONEMAP_CURVE_BLUE,
+    ANDROID_TONEMAP_CURVE_GREEN,
+    ANDROID_TONEMAP_CURVE_RED,
+    ANDROID_TONEMAP_MODE,
+    ANDROID_COLOR_CORRECTION_GAINS,
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+    ANDROID_SHADING_MODE,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING with FULL H/W level */
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+    /* REQUEST_AVAILABLE_CAPABILITIES_RAW */
+    ANDROID_HOT_PIXEL_MODE,
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+    ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
+    ANDROID_SENSOR_GREEN_SPLIT,
+    ANDROID_SENSOR_NOISE_PROFILE,
+    /* ETC */
+    ANDROID_EDGE_MODE,
+    ANDROID_NOISE_REDUCTION_MODE,
+    ANDROID_STATISTICS_SCENE_FLICKER,
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY */
+static int32_t AVAILABLE_RESULT_KEYS_LEGACY[] =
+{
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED */
+static int32_t AVAILABLE_CHARACTERISTICS_KEYS_LIMITED[] =
+{
+    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+    ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+    ANDROID_CONTROL_AE_COMPENSATION_STEP,
+    ANDROID_CONTROL_AF_AVAILABLE_MODES,
+    ANDROID_CONTROL_AVAILABLE_EFFECTS,
+    ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+    ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+    ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+    ANDROID_CONTROL_MAX_REGIONS,
+    ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+    ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+    ANDROID_CONTROL_AVAILABLE_MODES,
+    ANDROID_FLASH_INFO_AVAILABLE,
+    ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+    ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+    ANDROID_LENS_FACING,
+    ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+    ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+    ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+    ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+    ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+    ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+    ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+    ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+    ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+    ANDROID_SCALER_CROPPING_TYPE,
+    ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+    ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM1,
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM2,
+    ANDROID_SENSOR_COLOR_TRANSFORM1,
+    ANDROID_SENSOR_COLOR_TRANSFORM2,
+    ANDROID_SENSOR_FORWARD_MATRIX1,
+    ANDROID_SENSOR_FORWARD_MATRIX2,
+    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+    ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+    ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+    ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+    ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+    ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+    ANDROID_SENSOR_INFO_WHITE_LEVEL,
+    ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+    ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
+    ANDROID_SENSOR_ORIENTATION,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
+    ANDROID_SHADING_AVAILABLE_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+    ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+    ANDROID_SYNC_MAX_LATENCY,
+    ANDROID_TONEMAP_MAX_CURVE_POINTS,
+#if 1
+    ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+    ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+    ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+    ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
+#endif
+};
+
+static int32_t AVAILABLE_CHARACTERISTICS_KEYS_LIMITED_OPTIONAL[] =
+{
+    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+    ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+    ANDROID_CONTROL_AE_COMPENSATION_STEP,
+    ANDROID_CONTROL_AF_AVAILABLE_MODES,
+    ANDROID_CONTROL_AVAILABLE_EFFECTS,
+    ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+    ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+    ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+    ANDROID_CONTROL_MAX_REGIONS,
+    ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+    ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+    ANDROID_CONTROL_AVAILABLE_MODES,
+    ANDROID_FLASH_INFO_AVAILABLE,
+    ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+    ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+    ANDROID_LENS_FACING,
+    ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+    ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+    ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+    ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+    ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+    ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+    ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+    ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+    ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+    ANDROID_SCALER_CROPPING_TYPE,
+    ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+    ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM1,
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM2,
+    ANDROID_SENSOR_COLOR_TRANSFORM1,
+    ANDROID_SENSOR_COLOR_TRANSFORM2,
+    ANDROID_SENSOR_FORWARD_MATRIX1,
+    ANDROID_SENSOR_FORWARD_MATRIX2,
+    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+    ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+    ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+    ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+    ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+    ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+    ANDROID_SENSOR_INFO_WHITE_LEVEL,
+    ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+    ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
+    ANDROID_SENSOR_ORIENTATION,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
+    ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+    ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+    ANDROID_SYNC_MAX_LATENCY,
+    ANDROID_TONEMAP_MAX_CURVE_POINTS,
+    ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+    ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+    ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+    ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL */
+static int32_t AVAILABLE_CHARACTERISTICS_KEYS_FULL[] =
+{
+    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_MODES,
+    ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+    ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+    ANDROID_CONTROL_AE_COMPENSATION_STEP,
+    ANDROID_CONTROL_AF_AVAILABLE_MODES,
+    ANDROID_CONTROL_AVAILABLE_EFFECTS,
+    ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+    ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+    ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+    ANDROID_CONTROL_MAX_REGIONS,
+    ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+    ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+    ANDROID_CONTROL_AVAILABLE_MODES,
+    ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+    ANDROID_FLASH_INFO_AVAILABLE,
+    ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
+    ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+    ANDROID_LENS_FACING,
+    ANDROID_LENS_INFO_AVAILABLE_APERTURES,
+    ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+    ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+    ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+    ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+    ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+    ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+    ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+    ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+    ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+    ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+    ANDROID_SCALER_CROPPING_TYPE,
+    ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+    ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM1,
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM2,
+    ANDROID_SENSOR_COLOR_TRANSFORM1,
+    ANDROID_SENSOR_COLOR_TRANSFORM2,
+    ANDROID_SENSOR_FORWARD_MATRIX1,
+    ANDROID_SENSOR_FORWARD_MATRIX2,
+    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+    ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+    ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+    ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+    ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+    ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+    ANDROID_SENSOR_INFO_WHITE_LEVEL,
+    ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+    ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
+    ANDROID_SENSOR_ORIENTATION,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
+    ANDROID_SHADING_AVAILABLE_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+    ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+    ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+    ANDROID_SYNC_MAX_LATENCY,
+    ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
+    ANDROID_TONEMAP_MAX_CURVE_POINTS,
+};
+
+/* ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY */
+static int32_t AVAILABLE_CHARACTERISTICS_KEYS_LEGACY[] =
+{
+};
+
+/* Android Scaler Static Metadata */
+static int64_t AVAILABLE_STALL_DURATIONS[] =
+{
+};
+
+static int32_t YUV_FORMATS[] =
+{
+    HAL_PIXEL_FORMAT_RGBA_8888,
+    HAL_PIXEL_FORMAT_YCbCr_420_888,
+};
+
+static int32_t STALL_FORMATS[] =
+{
+    HAL_PIXEL_FORMAT_BLOB,
+};
+
+static int32_t RAW_FORMATS[] =
+{
+    HAL_PIXEL_FORMAT_RAW16,
+};
+
+/* Android Sensor Static Metadata */
+static int32_t AVAILABLE_TEST_PATTERN_MODES[] =
+{
+    ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
+    //ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR,
+    //ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS,
+    //ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY,
+    //ANDROID_SENSOR_TEST_PATTERN_MODE_PN9,
+    //ANDROID_SENSOR_TEST_PATTERN_MODE_CUSTOM1,
+};
+
+/* Android Statistics Static Metadata */
+static uint8_t AVAILABLE_FACE_DETECT_MODES[] =
+{
+    ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
+    ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE,
+    //ANDROID_STATISTICS_FACE_DETECT_MODE_FULL,
+};
+
+static uint8_t AVAILABLE_HOT_PIXEL_MAP_MODES[] =
+{
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF,
+    //ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_ON,
+};
+
+static uint8_t SHADING_AVAILABLE_MODES[] =
+{
+    ANDROID_SHADING_MODE_OFF,
+    ANDROID_SHADING_MODE_FAST,
+    //ANDROID_SHADING_MODE_HIGH_QUALITY,
+};
+
+static uint8_t AVAILABLE_LENS_SHADING_MAP_MODES[] =
+{
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF,
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON,
+};
+
+/* Android Tone Map Static Metadata */
+static uint8_t AVAILABLE_TONE_MAP_MODES[] =
+{
+    //ANDROID_TONEMAP_MODE_CONTRAST_CURVE,
+    ANDROID_TONEMAP_MODE_FAST,
+    ANDROID_TONEMAP_MODE_HIGH_QUALITY,
+    ANDROID_TONEMAP_MODE_GAMMA_VALUE,
+    ANDROID_TONEMAP_MODE_PRESET_CURVE,
+};
+
+/* Android LED Static Metadata */
+static uint8_t AVAILABLE_LEDS[] =
+{
+};
+
+#ifdef SAMSUNG_CONTROL_METERING
+typedef enum camera_metadata_enum_samsung_android_control_metering_mode {
+    SAMSUNG_ANDROID_CONTROL_METERING_MODE_CENTER = 0,
+    SAMSUNG_ANDROID_CONTROL_METERING_MODE_SPOT,
+    SAMSUNG_ANDROID_CONTROL_METERING_MODE_MATRIX,
+    SAMSUNG_ANDROID_CONTROL_METERING_MODE_MANUAL,
+} camera_metadata_enum_samsung_android_control_metering_mode_t;
+
+static int32_t AVAILABLE_VENDOR_METERING_MODES[] =
+{
+    (int32_t)SAMSUNG_ANDROID_CONTROL_METERING_MODE_CENTER,
+    (int32_t)SAMSUNG_ANDROID_CONTROL_METERING_MODE_SPOT,
+    (int32_t)SAMSUNG_ANDROID_CONTROL_METERING_MODE_MATRIX,
+    (int32_t)SAMSUNG_ANDROID_CONTROL_METERING_MODE_MANUAL,
+};
+#endif
+
+#ifdef SAMSUNG_OIS
+typedef enum camera_metadata_enum_samsung_android_lens_ois_mode {
+    SAMSUNG_ANDROID_LENS_OPTICAL_STABILIZATION_OPERATION_MODE_PICTURE = 0,
+    SAMSUNG_ANDROID_LENS_OPTICAL_STABILIZATION_OPERATION_MODE_VIDEO,
+} camera_metadata_enum_samsung_android_lens_ois_mode_t;
+
+static int32_t AVAILABLE_VENDOR_OIS_MODES[] =
+{
+    (int32_t)SAMSUNG_ANDROID_LENS_OPTICAL_STABILIZATION_OPERATION_MODE_PICTURE,
+    (int32_t)SAMSUNG_ANDROID_LENS_OPTICAL_STABILIZATION_OPERATION_MODE_VIDEO,
+};
+#endif
+#endif
diff --git a/libcamera3/ExynosCameraConfig.h b/libcamera3/ExynosCameraConfig.h
new file mode 100644 (file)
index 0000000..d4b0710
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015, Samsung Electronics Co. LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed toggle an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file      ExynosCameraConfig.h
+ * \brief     hearder file for ExynosCameraConfig
+ * \author    Sangwoo Park(sw5771.park@samsung.com)
+ * \date      2015/7/2
+ *
+ */
+
+#ifndef EXYNOS_CAMERA_CONFIG_WRAPPER_H__
+#define EXYNOS_CAMERA_CONFIG_WRAPPER_H__
+
+#ifdef USE_CAMERA2_API_SUPPORT
+#include "ExynosCamera3Config.h"
+#else
+#error This ExynosCameraConfig.h is 3.2 wrapper
+#endif
+
+#endif /* EXYNOS_CAMERA_CONFIG_WRAPPER_H__ */
diff --git a/libcameraInterface/Android.mk b/libcameraInterface/Android.mk
new file mode 100644 (file)
index 0000000..963e489
--- /dev/null
@@ -0,0 +1,129 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+#################
+# camera.exynos7570.so
+
+include $(CLEAR_VARS)
+
+######## System LSI ONLY ########
+BOARD_CAMERA_GED_FEATURE := true
+#################################
+
+# HAL module implemenation stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.product.board>.so
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_C_INCLUDES += \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libcamera \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libcamera/Vendor \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libcamera3 \
+       $(TOP)/system/media/camera/include \
+       $(TOP)/system/core/libion/include \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx/hal1 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx/hal3 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/SensorInfos \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Pipes2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/MCPipes \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Activities \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Buffers \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Sec \
+       $(TOP)/hardware/samsung_slsi/exynos/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \
+       frameworks/native/include \
+       $(TOP)/external/libcxx/include \
+       $(TOP)/bionic
+else
+LOCAL_C_INCLUDES += \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libcameraSec \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libcameraSec/Vendor \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libcamera3Sec \
+       $(TOP)/system/media/camera/include \
+       $(TOP)/system/core/libion/include \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx/hal1 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/34xx/hal3 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/SensorInfos \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Pipes2 \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/MCPipes \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Activities \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Buffers \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2/Sec \
+       $(TOP)/hardware/samsung_slsi/exynos/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \
+       frameworks/native/include \
+       $(TOP)/external/libcxx/include \
+       $(TOP)/bionic \
+       $(TOP)/hardware/camera/SensorListener \
+       $(TOP)/hardware/camera/UniPlugin/include
+endif
+
+ifneq ($(LOCAL_PROJECT_DIR),)
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libcameraSec/$(LOCAL_PROJECT_DIR)
+else
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libcamera/SensorInfos
+endif
+
+ifeq ($(BOARD_CAMERA_HAL3_FEATURE), true)
+LOCAL_SRC_FILES:= \
+       ../../exynos/libcamera/common_v2/ExynosCamera3Interface.cpp
+else
+LOCAL_SRC_FILES:= \
+       ../../exynos/libcamera/common_v2/ExynosCameraInterface.cpp
+endif
+
+LOCAL_CFLAGS += -DBACK_ROTATION=$(BOARD_BACK_CAMERA_ROTATION)
+LOCAL_CFLAGS += -DFRONT_ROTATION=$(BOARD_FRONT_CAMERA_ROTATION)
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_CFLAGS += -DCAMERA_GED_FEATURE
+endif
+ifeq ($(BOARD_CAMERA_HAL3_FEATURE), true)
+LOCAL_CFLAGS += -DUSE_CAMERA2_API_SUPPORT
+endif
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+LOCAL_SHARED_LIBRARIES += libexynosutils libhwjpeg libexynosv4l2 libcsc libion libcamera_metadata libexynoscamera
+
+ifeq ($(BOARD_CAMERA_HAL3_FEATURE), true)
+LOCAL_SHARED_LIBRARIES += libexynoscamera3
+endif
+
+$(foreach file,$(LOCAL_SRC_FILES),$(shell touch '$(LOCAL_PATH)/$(file)'))
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_MODULE := camera.$(TARGET_BOOTLOADER_BOARD_NAME)
+else
+LOCAL_MODULE := camera.$(TARGET_BOOTLOADER_BOARD_NAME)
+# Temporary modified
+#LOCAL_MODULE := camera.$(TARGET_BOARD_PLATFORM)
+endif
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS += -D$(shell echo $(project_camera) | tr a-z A-Z)_CAMERA
+
+include $(TOP)/hardware/samsung_slsi/exynos/BoardConfigCFlags.mk
+include $(BUILD_SHARED_LIBRARY)
+
+$(warning #####################################)
+$(warning ########    libcamera I/F    ########)
+$(warning #####################################)
diff --git a/libcamera_external/Android.mk b/libcamera_external/Android.mk
new file mode 100644 (file)
index 0000000..5e45b87
--- /dev/null
@@ -0,0 +1,168 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+###################
+# libexynoscameraexternal
+
+soc_prj_list := swatch
+project_camera := $(strip $(foreach p,$(soc_prj_list),$(if $(findstring $(p),$(TARGET_PRODUCT)),$(p))))
+
+include $(CLEAR_VARS)
+
+######## System LSI ONLY ########
+BOARD_CAMERA_GED_FEATURE := true
+############################
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+       $(LOCAL_PATH)/../include \
+       $(TOP)/system/media/camera/include \
+       $(TOP)/system/core/libion/include \
+       $(TOP)/hardware/samsung_slsi/exynos/include \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera_external \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2 \
+       $(TOP)/hardware/libhardware/include/hardware \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/include \
+       $(TOP)/vendor/samsung/feature/CscFeature/libsecnativefeature \
+       $(TOP)/bionic \
+       $(TOP)/external/expat/lib \
+       frameworks/native/include
+
+LOCAL_SRC_FILES:= \
+       ../../exynos/libcamera_external/Exif.cpp \
+       ../../exynos/libcamera_external/SecCameraParameters.cpp \
+       ../../exynos/libcamera_external/ISecCameraHardware.cpp \
+       ../../exynos/libcamera_external/SecCameraHardware.cpp \
+       ../../exynos/libcamera_external/SecCameraHardware1MetadataConverter.cpp \
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware libgui
+LOCAL_SHARED_LIBRARIES += libexynosutils libhwjpeg libexynosv4l2 libcsc libion libcamera_metadata
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+else
+LOCAL_SHARED_LIBRARIES += libsecnativefeature libexpat
+endif
+
+ifeq ($(TARGET_USES_UNIVERSAL_LIBHWJPEG), true)
+       LOCAL_CFLAGS += -DUSES_UNIVERSAL_LIBHWJPEG
+endif
+
+LOCAL_CFLAGS += -DGAIA_FW_BETA
+LOCAL_CFLAGS += -DBACK_CAMERA_SENSOR_NAME=$(BOARD_BACK_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DFRONT_CAMERA_SENSOR_NAME=$(BOARD_FRONT_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DBACK_ROTATION=$(BOARD_BACK_CAMERA_ROTATION)
+LOCAL_CFLAGS += -DFRONT_ROTATION=$(BOARD_FRONT_CAMERA_ROTATION)
+
+ifeq ($(BOARD_BACK_CAMERA_USES_EXTERNAL_CAMERA), true)
+       LOCAL_CFLAGS += -DBOARD_BACK_CAMERA_USES_EXTERNAL_CAMERA
+endif
+
+ifeq ($(BOARD_FRONT_CAMERA_USES_EXTERNAL_CAMERA), true)
+       LOCAL_CFLAGS += -DBOARD_FRONT_CAMERA_USES_EXTERNAL_CAMERA
+endif
+
+ifeq ($(BOARD_FRONT_CAMERA_ONLY_USE), true)
+       LOCAL_CFLAGS += -DBOARD_FRONT_CAMERA_ONLY_USE
+endif
+
+ifeq ($(BOARD_USE_MHB_ION), true)
+LOCAL_CFLAGS += -DBOARD_USE_MHB_ION
+endif
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_CFLAGS += -DCAMERA_GED_FEATURE
+endif
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+else
+LOCAL_CFLAGS += -DUSE_CSC_FEATURE
+endif
+
+LOCAL_CFLAGS += -D$(shell echo $(project_camera) | tr a-z A-Z)_CAMERA
+
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libexynoscameraexternal
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+#################
+# camera.exynos7570.so
+
+include $(CLEAR_VARS)
+
+######## System LSI ONLY ########
+BOARD_CAMERA_GED_FEATURE := true
+############################
+
+# HAL module implemenation stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.product.board>.so
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_C_INCLUDES += \
+       $(LOCAL_PATH)/../include \
+       $(TOP)/system/media/camera/include \
+       $(TOP)/system/core/libion/include \
+       $(TOP)/hardware/samsung_slsi/exynos/include \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera_external \
+       $(TOP)/hardware/samsung_slsi/exynos/libcamera/common_v2 \
+       $(TOP)/hardware/libhardware/include/hardware \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/include \
+       frameworks/native/include \
+
+LOCAL_SRC_FILES:= \
+       ../../exynos/libcamera_external/SecCameraInterface.cpp
+
+LOCAL_CFLAGS += -DGAIA_FW_BETA
+LOCAL_CFLAGS += -DBACK_CAMERA_SENSOR_NAME=$(BOARD_BACK_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DFRONT_CAMERA_SENSOR_NAME=$(BOARD_FRONT_CAMERA_SENSOR)
+LOCAL_CFLAGS += -DBACK_ROTATION=$(BOARD_BACK_CAMERA_ROTATION)
+LOCAL_CFLAGS += -DFRONT_ROTATION=$(BOARD_FRONT_CAMERA_ROTATION)
+
+
+ifeq ($(BOARD_BACK_CAMERA_USES_EXTERNAL_CAMERA), true)
+       LOCAL_CFLAGS += -DBOARD_BACK_CAMERA_USES_EXTERNAL_CAMERA
+endif
+
+ifeq ($(BOARD_FRONT_CAMERA_USES_EXTERNAL_CAMERA), true)
+       LOCAL_CFLAGS += -DBOARD_FRONT_CAMERA_USES_EXTERNAL_CAMERA
+endif
+
+ifeq ($(BOARD_FRONT_CAMERA_ONLY_USE), true)
+       LOCAL_CFLAGS += -DBOARD_FRONT_CAMERA_ONLY_USE
+endif
+
+ifeq ($(BOARD_CAMERA_GED_FEATURE), true)
+LOCAL_CFLAGS += -DCAMERA_GED_FEATURE
+endif
+
+ifeq ($(TARGET_USES_UNIVERSAL_LIBHWJPEG), true)
+       LOCAL_CFLAGS += -DUSES_UNIVERSAL_LIBHWJPEG
+endif
+
+LOCAL_CFLAGS += -D$(shell echo $(project_camera) | tr a-z A-Z)_CAMERA
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+LOCAL_SHARED_LIBRARIES += libexynosutils libhwjpeg libexynosv4l2 libcsc libion libexynoscameraexternal
+
+LOCAL_MODULE := camera.$(TARGET_BOOTLOADER_BOARD_NAME)
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libcamera_external/model/include/SecCameraHardware-default.h b/libcamera_external/model/include/SecCameraHardware-default.h
new file mode 100644 (file)
index 0000000..78b7158
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright (c) 2011, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
+*/
+#ifndef ANDROID_HARDWARE_SECCAMERAHARDWARE_DEFAULT_H
+#define ANDROID_HARDWARE_SECCAMERAHARDWARE_DEFAULT_H
+
+#include "Exif.h"
+#include "SecCameraParameters.h"
+
+/**
+ * Define function feature
+**/
+#define MFC_7X_BUFFER_OFFSET            (256)
+#define GRALLOC_LOCK_FOR_CAMERA         (GRALLOC_SET_USAGE_FOR_CAMERA)
+
+#define USE_MEM2MEM_GSC
+#ifdef USE_MEM2MEM_GSC
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP | \
+     GRALLOC_USAGE_HW_CAMERA_MASK)
+#else
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP)
+#endif
+
+#define PREVIEW_GSC_NODE_NUM            (4)  /* 4 = MSC from Exynos5420 */
+#define PICTURE_GSC_NODE_NUM            (5)  /* 0,1,2 = GSC */
+#define VIDEO_GSC_NODE_NUM              (4)
+
+#define SUPPORT_64BITS
+#define FLITE0_DEV_PATH  "/dev/video101" /* MAIN_CAMERA_FLITE_NUM */
+#define FLITE1_DEV_PATH  "/dev/video102" /* FRONT_CAMERA_FLITE_NUM */
+
+#define ZOOM_FUNCTION       true
+#define FRONT_ZSL           false
+/* #define DUMP_FILE         1 */
+
+#define FIMC1_NODE_NUM (PICTURE_GSC_NODE_NUM) /* for preview */
+#define FIMC2_NODE_NUM (VIDEO_GSC_NODE_NUM)   /* for recording */
+
+/* #define VENDOR_FEATURE (1) */
+
+#define JPEG_THUMBNAIL_QUALITY (30)
+#define JPEG_QUALITY_ADJUST_TARGET    (97)
+
+#define USE_LIMITATION_FOR_THIRD_PARTY
+
+#define USE_DEDICATED_PREVIEW_ENQUEUE_THREAD
+
+#define USE_CAMERA_PREVIEW_FRAME_SCHEDULER
+
+/* video snapshot */
+#define RECORDING_CAPTURE
+
+/* In case of YUV capture on Rear camera */
+#define REAR_USE_YUV_CAPTURE
+
+/* #define FAKE_SENSOR */
+/* #define DEBUG_RECORDING */
+
+#define IsZoomSupported()                   (true)
+#define IsAPZoomSupported()                 (ZOOM_FUNCTION)
+#define IsAutoFocusSupported()              (true)
+#define IsFlashSupported()                  (true)
+#define IsFastCaptureSupportedOnRear()      (false)
+#define IsFastCaptureSupportedOnFront()     (false)
+
+#if (IsFlashSupported())
+#define BACK_FLASH_LED_SUPPORT  (true)
+#define FRONT_FLASH_LED_SUPPORT (false)
+
+#define CHECK_FLASH_LED(id)     ((id)?(FRONT_FLASH_LED_SUPPORT):(BACK_FLASH_LED_SUPPORT))
+#else
+#define CHECK_FLASH_LED(id)     (false)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+#define SENSOR_NAME_GET_FROM_FILE
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+#define SENSOR_FW_GET_FROM_FILE
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+//#define SUPPORT_X4_ZOOM_AND_400STEP
+#endif
+
+namespace android {
+
+#ifdef ANDROID_HARDWARE_SECCAMERAHARDWARE_CPP
+/**
+ * Exif Info dependent on Camera Module
+**/
+
+/* F Number */
+const int Exif::DEFAULT_BACK_FNUMBER_NUM = 22;
+const int Exif::DEFAULT_BACK_FNUMBER_DEN = 10;
+const int Exif::DEFAULT_FRONT_FNUMBER_NUM = 22;
+const int Exif::DEFAULT_FRONT_FNUMBER_DEN = 10;
+
+/* Focal length */
+const int Exif::DEFAULT_BACK_FOCAL_LEN_NUM = 330;
+const int Exif::DEFAULT_BACK_FOCAL_LEN_DEN = 100;
+const int Exif::DEFAULT_FRONT_FOCAL_LEN_NUM = 244;
+const int Exif::DEFAULT_FRONT_FOCAL_LEN_DEN = 100;
+
+/* Focal length 35mm */
+const int Exif::DEFAULT_BACK_FOCAL_LEN_35mm = 33;
+const int Exif::DEFAULT_FRONT_FOCAL_LEN_35mm = 29;
+#endif
+
+/**
+ * Define Supported parameters for ISecCameraHardware
+**/
+#ifdef ANDROID_HARDWARE_ISECCAMERAHARDWARE_CPP
+
+/* Frame Rates */
+#define B_KEY_PREVIEW_FPS_RANGE_VALUE "15000,30000"
+#define B_KEY_SUPPORTED_PREVIEW_FPS_RANGE_VALUE "(7000,7000),(15000,15000),(15000,30000),(30000,30000)"
+#define B_KEY_SUPPORTED_PREVIEW_FRAME_RATES_VALUE "7,15,30"
+#define B_KEY_PREVIEW_FRAME_RATE_VALUE 30
+
+#define F_KEY_PREVIEW_FPS_RANGE_VALUE "15000,30000"
+#define F_KEY_SUPPORTED_PREVIEW_FPS_RANGE_VALUE "(15000,15000),(24000,24000),(15000,30000)"
+#define F_KEY_SUPPORTED_PREVIEW_FRAME_RATES_VALUE "15,24,30"
+#define F_KEY_PREVIEW_FRAME_RATE_VALUE 30
+
+/* Preferred preview size for video.
+ * This preferred preview size must be in supported preview size list
+ */
+#define B_KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO_VALUE "1280x720"
+#define F_KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO_VALUE "640x480"
+
+/* Video */
+#define B_KEY_VIDEO_STABILIZATION_SUPPORTED_VALUE       "false"
+#define F_KEY_VIDEO_STABILIZATION_SUPPORTED_VALUE       "false"
+
+#ifdef RECORDING_CAPTURE
+#define KEY_VIDEO_SNAPSHOT_SUPPORTED_VALUE              "true"
+#else
+#define KEY_VIDEO_SNAPSHOT_SUPPORTED_VALUE              "false"
+#endif
+
+/* Focus */
+#define B_KEY_NORMAL_FOCUS_DISTANCES_VALUE "0.15,1.20,Infinity" /* Normal */
+#define B_KEY_MACRO_FOCUS_DISTANCES_VALUE   "0.10,0.15,0.30" /* Macro*/
+#define F_KEY_FOCUS_DISTANCES_VALUE  "0.20,0.25,Infinity" /* Fixed */
+
+/* Zoom */
+#define B_KEY_ZOOM_SUPPORTED_VALUE                  "true"
+#define B_KEY_SMOOTH_ZOOM_SUPPORTED_VALUE           "false"
+#define F_KEY_ZOOM_SUPPORTED_VALUE                  "false"
+#define F_KEY_SMOOTH_ZOOM_SUPPORTED_VALUE           "false"
+
+/* AE, AWB Lock */
+#define B_KEY_AUTO_EXPOSURE_LOCK_SUPPORTED_VALUE            "true"
+#define B_KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED_VALUE        "true"
+#define F_KEY_AUTO_EXPOSURE_LOCK_SUPPORTED_VALUE            "false"
+#define F_KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED_VALUE        "false"
+
+/* Face Detect */
+#define B_KEY_MAX_NUM_DETECTED_FACES_HW_VALUE "0"
+#define B_KEY_MAX_NUM_DETECTED_FACES_SW_VALUE "3"
+#define F_KEY_MAX_NUM_DETECTED_FACES_HW_VALUE "0"
+#define F_KEY_MAX_NUM_DETECTED_FACES_SW_VALUE "0"
+
+/* AF Status */
+#define AF_STATUS_FOCUSING        (0)
+#define AF_STATUS_FOCUSED        (1)    /*SUCCESS*/
+#define AF_STATUS_UNFOCUSED    (2)    /*FAIL*/
+
+static const image_rect_type backSensorSize = {
+    2576,    1932
+};
+
+static const image_rect_type frontSensorSize = {
+    1600,    1200
+};
+
+static const image_rect_type backFLitePreviewSizes[] = {
+    { 1280,   720 }, /* default */
+    { 1024,   768 },
+    { 720,    720 },
+    { 720,    480 },
+    { 640,    480 },
+    { 352,    288 },
+    { 320,    240 },
+    { 176,    144 },
+};
+
+static const image_rect_type backFLiteCaptureSizes[] = {
+    { 2576,   1932 },
+    { 2560,   1440 },
+    { 2560,   1536 },
+    { 2560,   1920 },
+    { 2048,   1536 },
+    { 2048,   1152 },
+    { 1920,   1920 },
+    { 1600,   1200 },
+    { 1280,   960 },
+    { 1024,   768 },
+    { 640,    480 },
+};
+
+static const image_rect_type frontFLitePreviewSizes[] = {
+    { 640,    480 },
+};
+
+#ifdef USE_LIMITATION_FOR_THIRD_PARTY
+static const image_rect_type frontFLitePreviewSizeHangout = {
+    320,    240
+};
+#endif
+
+static const image_rect_type frontFLiteCaptureSizes[] = {
+    { 1600,    1200 },
+    { 1280,    960 },
+    { 640,    480 },
+};
+
+static const image_rect_type backPreviewSizes[] = {
+    { 1280,   720 },
+    { 1280,   960 },
+    { 1024,   768 },
+    { 720,    720 },
+    { 720,    480 },
+    { 640,    480 },
+    { 352,    288 },
+    { 320,    240 },
+    { 176,    144 },
+};
+
+static const image_rect_type hiddenBackPreviewSizes[0] = {
+};
+
+static const image_rect_type backRecordingSizes[] = {
+    { 1280,   720 }, /* default */
+    { 720,    480 },
+    { 640,    480 },
+    { 320,    240 },
+    { 176,    144 },
+};
+
+static const image_rect_type hiddenBackRecordingSizes[0] = {
+};
+
+static const image_rect_type backPictureSizes[] = {
+    { 2576,   1932 },
+    { 2560,   1440 },
+    { 2560,   1920 },
+    { 2048,   1536 },
+    { 2048,   1152 },
+    { 1920,   1920 },
+    { 1600,   1200 },
+    { 1280,   960 },
+    { 1280,   720 },
+    { 1024,   768 },
+    { 640,    480 },
+};
+
+static const image_rect_type hiddenBackPictureSizes[] = {
+    { 2560,   1536 },
+};
+
+static const image_rect_type frontPreviewSizes[] = {
+    { 800,    600 },    /* Preview */
+    { 640,    480 },    /* Recording */
+    { 320,    240 },
+    { 352,    288 },
+    { 176,    144 },
+};
+
+static const image_rect_type hiddenFrontPreviewSizes[0] = {
+};
+
+static const image_rect_type frontRecordingSizes[] = {
+    { 640,    480 },    /* default */
+    { 352,    288 },
+    { 320,    240 },
+    { 176,    144 },
+};
+
+static const image_rect_type hiddenFrontRecordingSizes[0] = {
+};
+
+static const image_rect_type frontPictureSizes[] = {
+    { 1600,    1200 },
+    { 1280,    960 },
+    { 640,    480 },
+};
+
+static const image_rect_type hiddenFrontPictureSizes[0] = {
+};
+
+static const image_rect_type backThumbSizes[] = {
+    { 160,    120 },    /* default 4 : 3 */
+    { 160,    160 },    /* 1 : 1 */
+    { 160,    90 },    /* 16 : 9 */
+    { 0,      0 },
+};
+
+static const image_rect_type frontThumbSizes[] = {
+    { 160,    120 },    /* default 4 : 3 */
+    { 0,      0 },
+};
+
+static const view_angle_type backHorizontalViewAngle[] = {
+    { SIZE_RATIO(16, 9), 56.0f },
+    { SIZE_RATIO(4, 3), 56.0f },
+    { SIZE_RATIO(1, 1), 45.0f },
+    { SIZE_RATIO(3, 2), 57.2f },
+    { SIZE_RATIO(5, 3), 56.0f },
+};
+
+static const float backVerticalViewAngle = 41.0f;
+
+static const view_angle_type frontHorizontalViewAngle[] = {
+    { SIZE_RATIO(16, 9), 60.3f },
+    { SIZE_RATIO(4, 3), 60.3f },
+};
+
+static const float frontVerticalViewAngle = 47.4f;
+
+static const cam_strmap_t whiteBalances[] = {
+    { CameraParameters::WHITE_BALANCE_AUTO,         WHITE_BALANCE_AUTO },
+    { CameraParameters::WHITE_BALANCE_INCANDESCENT, WHITE_BALANCE_TUNGSTEN },
+    { CameraParameters::WHITE_BALANCE_FLUORESCENT,  WHITE_BALANCE_FLUORESCENT },
+    { CameraParameters::WHITE_BALANCE_DAYLIGHT,     WHITE_BALANCE_SUNNY },
+    { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, WHITE_BALANCE_CLOUDY },
+};
+
+static const cam_strmap_t effects[] = {
+    { CameraParameters::EFFECT_NONE,        IMAGE_EFFECT_NONE },
+    { CameraParameters::EFFECT_MONO,        IMAGE_EFFECT_BNW },
+    { CameraParameters::EFFECT_NEGATIVE,    IMAGE_EFFECT_NEGATIVE },
+    { CameraParameters::EFFECT_SEPIA,       IMAGE_EFFECT_SEPIA }
+};
+
+static const cam_strmap_t sceneModes[] = {
+    { CameraParameters::SCENE_MODE_AUTO,        SCENE_MODE_NONE },
+    { CameraParameters::SCENE_MODE_PORTRAIT,    SCENE_MODE_PORTRAIT },
+    { CameraParameters::SCENE_MODE_LANDSCAPE,   SCENE_MODE_LANDSCAPE },
+    { CameraParameters::SCENE_MODE_NIGHT,       SCENE_MODE_NIGHTSHOT },
+    { CameraParameters::SCENE_MODE_BEACH,       SCENE_MODE_BEACH_SNOW },
+    { CameraParameters::SCENE_MODE_SUNSET,      SCENE_MODE_SUNSET },
+    { CameraParameters::SCENE_MODE_FIREWORKS,    SCENE_MODE_FIREWORKS },
+    { CameraParameters::SCENE_MODE_SPORTS,      SCENE_MODE_SPORTS },
+    { CameraParameters::SCENE_MODE_PARTY,       SCENE_MODE_PARTY_INDOOR },
+    { CameraParameters::SCENE_MODE_CANDLELIGHT, SCENE_MODE_CANDLE_LIGHT },
+};
+
+static const cam_strmap_t flashModes[] = {
+    { CameraParameters::FLASH_MODE_OFF,         FLASH_MODE_OFF },
+    { CameraParameters::FLASH_MODE_AUTO,        FLASH_MODE_AUTO },
+    { CameraParameters::FLASH_MODE_ON,          FLASH_MODE_ON },
+    { CameraParameters::FLASH_MODE_TORCH,       FLASH_MODE_TORCH },
+};
+
+static const cam_strmap_t previewPixelFormats[] = {
+    { CameraParameters::PIXEL_FORMAT_YUV420SP,  CAM_PIXEL_FORMAT_YUV420SP },
+    { CameraParameters::PIXEL_FORMAT_YUV420P,   CAM_PIXEL_FORMAT_YVU420P },
+/*  { CameraParameters::PIXEL_FORMAT_YUV422I,   CAM_PIXEL_FORMAT_YUV422I },
+    { CameraParameters::PIXEL_FORMAT_YUV422SP,  CAM_PIXEL_FORMAT_YUV422SP },
+    { CameraParameters::PIXEL_FORMAT_RGB565,    CAM_PIXEL_FORMAT_RGB565, }, */
+};
+
+static const cam_strmap_t picturePixelFormats[] = {
+    { CameraParameters::PIXEL_FORMAT_JPEG,      CAM_PIXEL_FORMAT_JPEG, },
+};
+
+#if IsAutoFocusSupported()
+static const cam_strmap_t backFocusModes[] = {
+    { CameraParameters::FOCUS_MODE_AUTO,        FOCUS_MODE_AUTO },
+    { CameraParameters::FOCUS_MODE_INFINITY,    FOCUS_MODE_INFINITY },
+    { CameraParameters::FOCUS_MODE_MACRO,       FOCUS_MODE_MACRO },
+    { CameraParameters::FOCUS_MODE_FIXED,       FOCUS_MODE_FIXED },
+/*  { CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, FOCUS_MODE_CONTINUOUS },
+    { SecCameraParameters::FOCUS_MODE_FACEDETECT, FOCUS_MODE_FACEDETECT }, */
+};
+#else
+static const cam_strmap_t backFocusModes[] = {
+    { CameraParameters::FOCUS_MODE_FIXED,       FOCUS_MODE_FIXED },
+};
+#endif
+
+static const cam_strmap_t frontFocusModes[] = {
+    { CameraParameters::FOCUS_MODE_FIXED,   FOCUS_MODE_FIXED },
+    { CameraParameters::FOCUS_MODE_INFINITY,   FOCUS_MODE_INFINITY },
+};
+
+static const cam_strmap_t isos[] = {
+    { SecCameraParameters::ISO_AUTO,    ISO_AUTO },
+    { SecCameraParameters::ISO_100,     ISO_100 },
+    { SecCameraParameters::ISO_200,     ISO_200 },
+    { SecCameraParameters::ISO_400,     ISO_400 },
+};
+
+static const cam_strmap_t meterings[] = {
+    { SecCameraParameters::METERING_CENTER, METERING_CENTER },
+    { SecCameraParameters::METERING_MATRIX, METERING_MATRIX },
+    { SecCameraParameters::METERING_SPOT,   METERING_SPOT },
+};
+
+static const cam_strmap_t antibandings[] = {
+    { CameraParameters::ANTIBANDING_AUTO, ANTI_BANDING_AUTO },
+    { CameraParameters::ANTIBANDING_50HZ, ANTI_BANDING_50HZ },
+    { CameraParameters::ANTIBANDING_60HZ, ANTI_BANDING_60HZ },
+    { CameraParameters::ANTIBANDING_OFF, ANTI_BANDING_OFF },
+};
+
+/* Define initial skip frame count */
+static const int INITIAL_REAR_SKIP_FRAME = 3;
+static const int INITIAL_FRONT_SKIP_FRAME = 3;
+
+#endif /* ANDROID_HARDWARE_ISECCAMERAHARDWARE_CPP */
+}
+#endif /* ANDROID_HARDWARE_SECCAMERAHARDWARE_JOSHUA_H */
diff --git a/libcamera_external/model/include/SecCameraHardware-model.h b/libcamera_external/model/include/SecCameraHardware-model.h
new file mode 100644 (file)
index 0000000..d5ad212
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright (c) 2011, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
+*/
+#ifndef ANDROID_HARDWARE_SECCAMERAHARDWARE_MODEL_H
+#define ANDROID_HARDWARE_SECCAMERAHARDWARE_MODEL_H
+
+//#include "SecCameraHardware-default.h" /* default */
+#include "SecCameraHardware-swatch.h" 
+
+#endif /* ANDROID_HARDWARE_SECCAMERAHARDWARE_MODEL_H */
diff --git a/libcamera_external/model/include/SecCameraHardware-swatch.h b/libcamera_external/model/include/SecCameraHardware-swatch.h
new file mode 100644 (file)
index 0000000..3cab862
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright (c) 2011, Samsung Electronics Co. LTD
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
+*/
+#ifndef ANDROID_HARDWARE_SECCAMERAHARDWARE_JAVA_W_H
+#define ANDROID_HARDWARE_SECCAMERAHARDWARE_JAVA_W_H
+
+#include "Exif.h"
+#include "SecCameraParameters.h"
+
+/**
+ * Define function feature
+**/
+
+#define MFC_7X_BUFFER_OFFSET            (256)
+#define GRALLOC_LOCK_FOR_CAMERA         (GRALLOC_SET_USAGE_FOR_CAMERA)
+
+#define USE_MEM2MEM_GSC
+#ifdef USE_MEM2MEM_GSC
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP | \
+     GRALLOC_USAGE_HW_CAMERA_MASK)
+#else
+#define GRALLOC_SET_USAGE_FOR_CAMERA \
+    (GRALLOC_USAGE_SW_READ_OFTEN | \
+     GRALLOC_USAGE_SW_WRITE_OFTEN | \
+     GRALLOC_USAGE_HW_TEXTURE | \
+     GRALLOC_USAGE_HW_COMPOSER | \
+     GRALLOC_USAGE_EXTERNAL_DISP)
+#endif
+
+#define PREVIEW_GSC_NODE_NUM            (4)  /* 4 = MSC from Exynos5420 */
+#define PICTURE_GSC_NODE_NUM            (4)  /* 0,1,2 = GSC */
+#define VIDEO_GSC_NODE_NUM              (4)
+
+#define SUPPORT_64BITS
+#define FLITE0_DEV_PATH  "/dev/video102" /* MAIN_CAMERA_FLITE_NUM */
+#define FLITE1_DEV_PATH  "/dev/video102" /* FRONT_CAMERA_FLITE_NUM */
+
+#define ZOOM_FUNCTION       true
+#define FRONT_ZSL           false
+
+/* #define DUMP_FILE         1 */
+
+#define FIMC1_NODE_NUM (PICTURE_GSC_NODE_NUM) /* for preview */
+#define FIMC2_NODE_NUM (VIDEO_GSC_NODE_NUM)   /* for recording */
+
+#define JPEG_THUMBNAIL_QUALITY (30)
+#define JPEG_QUALITY_ADJUST_TARGET    (97)
+
+#define USE_DEDICATED_PREVIEW_ENQUEUE_THREAD
+
+#define USE_RECORDING_FLITE_SIZE
+
+#define USE_CAPTURE_FPS_CHANGE
+#define CAPTURE_FRAMERATE (15)
+/* video snapshot */
+#define RECORDING_CAPTURE
+
+/* In case of YUV capture on Rear camera */
+/* #define REAR_USE_YUV_CAPTURE */
+
+/* #define FAKE_SENSOR */
+/* #define DEBUG_RECORDING */
+
+#define IsZoomSupported()                   (true)
+#define IsAPZoomSupported()                 (ZOOM_FUNCTION)
+#define IsAutoFocusSupported()              (false)
+#define IsFlashSupported()                  (false)
+#define IsFastCaptureSupportedOnRear()      (false)
+#define IsFastCaptureSupportedOnFront()     (false)
+
+#if (IsFlashSupported())
+#define BACK_FLASH_LED_SUPPORT     (true)
+#define FRONT_FLASH_LED_SUPPORT    (false)
+
+#define CHECK_FLASH_LED(id)        ((id)?(FRONT_FLASH_LED_SUPPORT):(BACK_FLASH_LED_SUPPORT))
+#else
+#define CHECK_FLASH_LED(id)        (false)
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+#define SENSOR_NAME_GET_FROM_FILE
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+#define SENSOR_FW_GET_FROM_FILE
+#endif
+
+#ifdef CAMERA_GED_FEATURE
+#else
+//#define SUPPORT_X4_ZOOM_AND_400STEP
+#endif
+
+namespace android {
+
+#ifdef ANDROID_HARDWARE_SECCAMERAHARDWARE_CPP
+/**
+ * Exif Info dependent on Camera Module
+**/
+
+/* F Number */
+const int Exif::DEFAULT_BACK_FNUMBER_NUM = 24;
+const int Exif::DEFAULT_BACK_FNUMBER_DEN = 10;
+const int Exif::DEFAULT_FRONT_FNUMBER_NUM = 28;
+const int Exif::DEFAULT_FRONT_FNUMBER_DEN = 10;
+
+/* Focal length */
+const int Exif::DEFAULT_BACK_FOCAL_LEN_NUM = 330;
+const int Exif::DEFAULT_BACK_FOCAL_LEN_DEN = 100;
+const int Exif::DEFAULT_FRONT_FOCAL_LEN_NUM = 244;
+const int Exif::DEFAULT_FRONT_FOCAL_LEN_DEN = 100;
+
+/* Focal length 35mm */
+const int Exif::DEFAULT_BACK_FOCAL_LEN_35mm = 33;
+const int Exif::DEFAULT_FRONT_FOCAL_LEN_35mm = 33;
+#endif
+
+/**
+ * Define Supported parameters for ISecCameraHardware
+**/
+#ifdef ANDROID_HARDWARE_ISECCAMERAHARDWARE_CPP
+
+/* Frame Rates */
+#define B_KEY_PREVIEW_FPS_RANGE_VALUE "15000,30000"
+#define B_KEY_SUPPORTED_PREVIEW_FPS_RANGE_VALUE "(15000,15000),(15000,30000),(30000,30000)"
+#define B_KEY_SUPPORTED_PREVIEW_FRAME_RATES_VALUE "15,30"
+#define B_KEY_PREVIEW_FRAME_RATE_VALUE 30
+
+#define F_KEY_PREVIEW_FPS_RANGE_VALUE "15000,30000"
+#define F_KEY_SUPPORTED_PREVIEW_FPS_RANGE_VALUE "(15000,15000),(15000,30000),(30000,30000)"
+#define F_KEY_SUPPORTED_PREVIEW_FRAME_RATES_VALUE "15,30"
+#define F_KEY_PREVIEW_FRAME_RATE_VALUE 30
+
+/* Preferred preview size for video.
+ * This preferred preview size must be in supported preview size list
+ */
+#define B_KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO_VALUE "640x480"
+#define F_KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO_VALUE "640x480"
+
+/* Video */
+#define B_KEY_VIDEO_STABILIZATION_SUPPORTED_VALUE       "false"
+#define F_KEY_VIDEO_STABILIZATION_SUPPORTED_VALUE       "false"
+
+#ifdef RECORDING_CAPTURE
+#define KEY_VIDEO_SNAPSHOT_SUPPORTED_VALUE              "true"
+#else
+#define KEY_VIDEO_SNAPSHOT_SUPPORTED_VALUE              "false"
+#endif
+
+/* Focus */
+#define B_KEY_NORMAL_FOCUS_DISTANCES_VALUE "0.15,1.20,Infinity" /* Normal */
+#define B_KEY_MACRO_FOCUS_DISTANCES_VALUE   "0.10,0.15,0.30" /* Macro*/
+#define F_KEY_FOCUS_DISTANCES_VALUE  "0.20,0.25,Infinity" /* Fixed */
+
+/* Zoom */
+#define B_KEY_ZOOM_SUPPORTED_VALUE                  "true"
+#define B_KEY_SMOOTH_ZOOM_SUPPORTED_VALUE   "false"
+#define F_KEY_ZOOM_SUPPORTED_VALUE                  "false"
+#define F_KEY_SMOOTH_ZOOM_SUPPORTED_VALUE   "false"
+
+/* AE, AWB Lock */
+#define B_KEY_AUTO_EXPOSURE_LOCK_SUPPORTED_VALUE            "true"
+#define B_KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED_VALUE   "true"
+#define F_KEY_AUTO_EXPOSURE_LOCK_SUPPORTED_VALUE            "false"
+#define F_KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED_VALUE   "false"
+
+/* Face Detect */
+#define B_KEY_MAX_NUM_DETECTED_FACES_HW_VALUE "0"
+#define B_KEY_MAX_NUM_DETECTED_FACES_SW_VALUE "3"
+#define F_KEY_MAX_NUM_DETECTED_FACES_HW_VALUE "0"
+#define F_KEY_MAX_NUM_DETECTED_FACES_SW_VALUE "0"
+
+/* AF Status */
+#define AF_STATUS_FOCUSING        (0)
+#define AF_STATUS_FOCUSED        (1)    /*SUCCESS*/
+#define AF_STATUS_UNFOCUSED    (2)    /*FAIL*/
+
+/* BUSTSHOT FPS and CONTINUOUS SHOT FPS Value */
+#define BURSTSHOT_MAX_FPS 5
+
+static const image_rect_type backSensorSize = {
+    2560,    1920
+};
+
+static const image_rect_type frontSensorSize = {
+    2560,    1920
+};
+
+static const image_rect_type backFLitePreviewSizes[] = {
+    { 2560,   1920 }, /* default */
+};
+
+static const image_rect_type backFLiteCaptureSizes[] = {
+    { 2560,   1920 },
+};
+
+static const image_rect_type backFLiteRecordingSizes[] = {
+    { 1280,   720 }, /* HD : crop */
+    { 1024,   768 }, /* 4:3 */
+    { 1024,   576 }, /* 16:9 */
+};
+
+static const image_rect_type frontFLitePreviewSizes[] = {
+    {   640,   480 },  //VGA_4:3
+};
+
+static const image_rect_type frontFLiteCaptureSizes[] = {
+    { 2560,    1920 },
+};
+
+static const image_rect_type backPreviewSizes[] = {
+    { 2560,   1920 }, //5M_4:3
+    { 2048,   1536 }, //3M_4:3
+    { 1600,   1200 }, //2M_4:3
+    { 1280,   960 },  //1M_4:3
+    { 1024,   768 },  //XGA_4:3
+    {   640,   480 },  //VGA_4:3
+};
+
+static const image_rect_type hiddenBackPreviewSizes[0] = {
+};
+
+static const image_rect_type backRecordingSizes[] = {
+    { 1280,   720 }, /* default */
+    { 640,    480 },
+    { 320,    240 },
+};
+
+static const image_rect_type hiddenBackRecordingSizes[0] = {
+};
+
+static const image_rect_type backPictureSizes[] = {
+    { 2560,   1920 }, //5M_4:3
+    { 2048,   1536 }, //3M_4:3
+    { 1600,   1200 }, //2M_4:3
+    { 1280,   960 },  //1M_4:3
+    { 1024,   768 },  //XGA_4:3
+    {   640,   480 },  //VGA_4:3
+};
+
+static const image_rect_type hiddenBackPictureSizes[0] = {
+};
+
+static const image_rect_type frontPreviewSizes[] = {
+#if 1
+{   400,   400 },  // smartwatch lcd 1:1
+#else
+    { 2560,   1920 }, //5M_4:3
+    { 2048,   1536 }, //3M_4:3
+    { 1600,   1200 }, //2M_4:3
+    { 1280,   960 },  //1M_4:3
+    { 1024,   768 },  //XGA_4:3
+    {   640,   480 },  //VGA_4:3
+#endif
+};
+
+static const image_rect_type hiddenFrontPreviewSizes[0] = {
+};
+
+static const image_rect_type frontRecordingSizes[] = {
+    { 1280,   720 }, /* default */
+    { 640,    480 },
+    { 320,    240 },
+};
+
+static const image_rect_type hiddenFrontRecordingSizes[0] = {
+};
+
+static const image_rect_type frontPictureSizes[] = {
+    { 2560,   1920 }, //5M_4:3
+    { 2048,   1536 }, //3M_4:3
+    { 1600,   1200 }, //2M_4:3
+    { 1280,   960 },  //1M_4:3
+    { 1024,   768 },  //XGA_4:3
+    {   640,   480 },  //VGA_4:3
+};
+
+static const image_rect_type hiddenFrontPictureSizes[0] = {
+};
+
+static const image_rect_type backThumbSizes[] = {
+    { 160,    120 },    /* default 4 : 3 */
+    { 160,    160 },    /* 1 : 1 */
+    { 160,    90 },    /* 16 : 9 */
+    { 0,      0 },
+};
+
+static const image_rect_type frontThumbSizes[] = {
+    { 160,    120 },    /* default 4 : 3 */
+    { 160,    160 },    /* 1 : 1 */
+    { 160,    90 },    /* 16 : 9 */
+    { 0,      0 },
+};
+
+static const view_angle_type backHorizontalViewAngle[] = {
+    { SIZE_RATIO(16, 9), 62.0f },
+    { SIZE_RATIO(4, 3), 62.0f },
+    { SIZE_RATIO(1, 1), 49.2f },
+    { SIZE_RATIO(3, 2), 62.0f },
+    { SIZE_RATIO(5, 3), 56.0f },
+    { SIZE_RATIO(5, 4), 56.0f },
+};
+
+static const float backVerticalViewAngle = 41.0f;
+
+static const view_angle_type frontHorizontalViewAngle[] = {
+    { SIZE_RATIO(16, 9), 55.1f },
+    { SIZE_RATIO(4, 3), 55.1f },
+    { SIZE_RATIO(5, 4), 50.0f },
+};
+
+static const float frontVerticalViewAngle = 47.4f;
+
+static const cam_strmap_t whiteBalances[] = {
+    { CameraParameters::WHITE_BALANCE_AUTO,         WHITE_BALANCE_AUTO },
+    { CameraParameters::WHITE_BALANCE_INCANDESCENT, WHITE_BALANCE_TUNGSTEN },
+    { CameraParameters::WHITE_BALANCE_FLUORESCENT,  WHITE_BALANCE_FLUORESCENT },
+    { CameraParameters::WHITE_BALANCE_DAYLIGHT,     WHITE_BALANCE_SUNNY },
+    { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, WHITE_BALANCE_CLOUDY },
+};
+
+static const cam_strmap_t effects[] = {
+    { CameraParameters::EFFECT_NONE,        IMAGE_EFFECT_NONE },
+    { CameraParameters::EFFECT_MONO,        IMAGE_EFFECT_BNW },
+    { CameraParameters::EFFECT_NEGATIVE,    IMAGE_EFFECT_NEGATIVE },
+    { CameraParameters::EFFECT_SEPIA,       IMAGE_EFFECT_SEPIA }
+};
+
+static const cam_strmap_t sceneModes[] = {
+    { CameraParameters::SCENE_MODE_AUTO,        SCENE_MODE_NONE },
+    { CameraParameters::SCENE_MODE_PORTRAIT,    SCENE_MODE_PORTRAIT },
+    { CameraParameters::SCENE_MODE_LANDSCAPE,   SCENE_MODE_LANDSCAPE },
+    { CameraParameters::SCENE_MODE_NIGHT,       SCENE_MODE_NIGHTSHOT },
+    { CameraParameters::SCENE_MODE_BEACH,       SCENE_MODE_BEACH_SNOW },
+    { CameraParameters::SCENE_MODE_SUNSET,      SCENE_MODE_SUNSET },
+    { CameraParameters::SCENE_MODE_FIREWORKS,    SCENE_MODE_FIREWORKS },
+    { CameraParameters::SCENE_MODE_SPORTS,      SCENE_MODE_SPORTS },
+    { CameraParameters::SCENE_MODE_PARTY,       SCENE_MODE_PARTY_INDOOR },
+    { CameraParameters::SCENE_MODE_CANDLELIGHT, SCENE_MODE_CANDLE_LIGHT },
+};
+
+static const cam_strmap_t flashModes[] = {
+    { CameraParameters::FLASH_MODE_OFF,         FLASH_MODE_OFF },
+    { CameraParameters::FLASH_MODE_AUTO,        FLASH_MODE_AUTO },
+    { CameraParameters::FLASH_MODE_ON,          FLASH_MODE_ON },
+    { CameraParameters::FLASH_MODE_TORCH,       FLASH_MODE_TORCH },
+};
+
+static const cam_strmap_t previewPixelFormats[] = {
+    { CameraParameters::PIXEL_FORMAT_YUV420SP,  CAM_PIXEL_FORMAT_YUV420SP },
+    { CameraParameters::PIXEL_FORMAT_YUV420P,   CAM_PIXEL_FORMAT_YVU420P },
+/*  { CameraParameters::PIXEL_FORMAT_YUV422I,   CAM_PIXEL_FORMAT_YUV422I },
+    { CameraParameters::PIXEL_FORMAT_YUV422SP,  CAM_PIXEL_FORMAT_YUV422SP },
+    { CameraParameters::PIXEL_FORMAT_RGB565,    CAM_PIXEL_FORMAT_RGB565, }, */
+};
+
+static const cam_strmap_t picturePixelFormats[] = {
+    { CameraParameters::PIXEL_FORMAT_JPEG,      CAM_PIXEL_FORMAT_JPEG, },
+};
+
+#if IsAutoFocusSupported()
+static const cam_strmap_t backFocusModes[] = {
+    { CameraParameters::FOCUS_MODE_AUTO,        FOCUS_MODE_AUTO },
+    { CameraParameters::FOCUS_MODE_INFINITY,    FOCUS_MODE_INFINITY },
+    { CameraParameters::FOCUS_MODE_MACRO,       FOCUS_MODE_MACRO },
+    { CameraParameters::FOCUS_MODE_FIXED,       FOCUS_MODE_FIXED },
+/*  { CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, FOCUS_MODE_CONTINUOUS },
+    { SecCameraParameters::FOCUS_MODE_FACEDETECT, FOCUS_MODE_FACEDETECT }, */
+};
+#else
+static const cam_strmap_t backFocusModes[] = {
+    { CameraParameters::FOCUS_MODE_FIXED,       FOCUS_MODE_FIXED },
+};
+#endif
+
+static const cam_strmap_t frontFocusModes[] = {
+    { CameraParameters::FOCUS_MODE_FIXED,   FOCUS_MODE_FIXED },
+    { CameraParameters::FOCUS_MODE_INFINITY,   FOCUS_MODE_INFINITY },
+};
+
+static const cam_strmap_t isos[] = {
+    { SecCameraParameters::ISO_AUTO,    ISO_AUTO },
+    { SecCameraParameters::ISO_100,     ISO_100 },
+    { SecCameraParameters::ISO_200,     ISO_200 },
+    { SecCameraParameters::ISO_400,     ISO_400 },
+};
+
+static const cam_strmap_t meterings[] = {
+    { SecCameraParameters::METERING_CENTER, METERING_CENTER },
+    { SecCameraParameters::METERING_MATRIX, METERING_MATRIX },
+    { SecCameraParameters::METERING_SPOT,   METERING_SPOT },
+};
+
+static const cam_strmap_t antibandings[] = {
+    { CameraParameters::ANTIBANDING_AUTO, ANTI_BANDING_AUTO },
+    { CameraParameters::ANTIBANDING_50HZ, ANTI_BANDING_50HZ },
+    { CameraParameters::ANTIBANDING_60HZ, ANTI_BANDING_60HZ },
+    { CameraParameters::ANTIBANDING_OFF, ANTI_BANDING_OFF },
+};
+
+/* Define initial skip frame count */
+static const int INITIAL_REAR_SKIP_FRAME = 3;
+static const int INITIAL_FRONT_SKIP_FRAME = 3;
+
+#endif /* ANDROID_HARDWARE_ISECCAMERAHARDWARE_CPP */
+}; /* namespace android */
+#endif /* ANDROID_HARDWARE_SECCAMERAHARDWARE_JAVA_W_H */
diff --git a/libdisplaymodule/Android.mk b/libdisplaymodule/Android.mk
new file mode 100644 (file)
index 0000000..395a49a
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_SRC_FILES += \
+       ./../../$(TARGET_SOC)/libdisplaymodule/ExynosPrimaryDisplay.cpp \
+       ./../../$(TARGET_SOC)/libdisplaymodule/ExynosDisplayResourceManagerModule.cpp
+
+ifeq ($(BOARD_USES_DUAL_DISPLAY), true)
+LOCAL_SRC_FILES += ./../../$(TARGET_SOC)/libdisplaymodule/ExynosSecondaryDisplayModule.cpp
+endif
diff --git a/libdisplaymodule/ExynosDisplayResourceManagerModule.cpp b/libdisplaymodule/ExynosDisplayResourceManagerModule.cpp
new file mode 100644 (file)
index 0000000..51e1153
--- /dev/null
@@ -0,0 +1,24 @@
+#define LOG_TAG "DisplayResourceManagerModule"
+#define LOG_NDEBUG 0
+
+#include "ExynosDisplayResourceManagerModule.h"
+#include "ExynosHWCModule.h"
+#include "ExynosMPPModule.h"
+#include "ExynosPrimaryDisplay.h"
+
+ExynosDisplayResourceManagerModule::ExynosDisplayResourceManagerModule(struct exynos5_hwc_composer_device_1_t *pdev)
+    : ExynosDisplayResourceManager(pdev)
+{
+    size_t num_mpp_units = sizeof(AVAILABLE_EXTERNAL_MPP_UNITS)/sizeof(exynos_mpp_t);
+    for (size_t i = 0; i < num_mpp_units; i++) {
+        exynos_mpp_t exynos_mpp = AVAILABLE_EXTERNAL_MPP_UNITS[i];
+        ALOGV("externalMPP type(%d), index(%d)", exynos_mpp.type, exynos_mpp.index);
+        ExynosMPPModule* exynosMPP = new ExynosMPPModule(NULL, exynos_mpp.type, exynos_mpp.index);
+        exynosMPP->setAllocDevice(pdev->primaryDisplay->mAllocDevice);
+        mExternalMPPs.add(exynosMPP);
+    }
+}
+
+ExynosDisplayResourceManagerModule::~ExynosDisplayResourceManagerModule()
+{
+}
diff --git a/libdisplaymodule/ExynosDisplayResourceManagerModule.h b/libdisplaymodule/ExynosDisplayResourceManagerModule.h
new file mode 100644 (file)
index 0000000..7f94688
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef EXYNOS_DISPLAY_RESOURCE_MANAGER_MODULE_H
+#define EXYNOS_DISPLAY_RESOURCE_MANAGER_MODULE_H
+
+#include "ExynosDisplayResourceManager.h"
+
+class ExynosDisplayResourceManagerModule : public ExynosDisplayResourceManager {
+    public:
+        ExynosDisplayResourceManagerModule(struct exynos5_hwc_composer_device_1_t *pdev);
+        virtual ~ExynosDisplayResourceManagerModule();
+};
+
+#endif
diff --git a/libdisplaymodule/ExynosPrimaryDisplay.cpp b/libdisplaymodule/ExynosPrimaryDisplay.cpp
new file mode 100644 (file)
index 0000000..b2bb97b
--- /dev/null
@@ -0,0 +1,452 @@
+#include "ExynosPrimaryDisplay.h"
+#include "ExynosHWCModule.h"
+#include "ExynosHWCUtils.h"
+#include "ExynosMPPModule.h"
+
+#define DISPLAY_LOGD(msg, ...) ALOGD("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGV(msg, ...) ALOGV("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGI(msg, ...) ALOGI("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGW(msg, ...) ALOGW("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGE(msg, ...) ALOGE("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+
+ExynosPrimaryDisplay::ExynosPrimaryDisplay(int numGSCs, struct exynos5_hwc_composer_device_1_t *pdev) :
+    ExynosOverlayDisplay(numGSCs, pdev)
+{
+}
+
+ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
+{
+}
+
+int ExynosPrimaryDisplay::getDeconWinMap(int overlayIndex, int totalOverlays)
+{
+       return 0;
+}
+
+void ExynosPrimaryDisplay::forceYuvLayersToFb(hwc_display_contents_1_t __unused *contents)
+{
+}
+
+int ExynosPrimaryDisplay::getMPPForUHD(hwc_layer_1_t __unused &layer)
+{
+    return 0;
+}
+
+int ExynosPrimaryDisplay::getRGBMPPIndex(int index)
+{
+    return index;
+}
+
+bool ExynosPrimaryDisplay::isOverlaySupported(hwc_layer_1_t &layer, size_t index, bool useVPPOverlay,
+        ExynosMPPModule** supportedInternalMPP, ExynosMPPModule** supportedExternalMPP)
+{
+    // Exynos755555oesn't have any VPP Overlays
+    return ExynosDisplay::isOverlaySupported(layer, index, false, supportedInternalMPP, supportedExternalMPP);
+}
+bool ExynosPrimaryDisplay::isYuvDmaAvailable(int format, uint32_t dma)
+{
+    return (format == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL &&
+        dma == IDMA_G2);
+}
+
+void ExynosPrimaryDisplay::assignWindows(hwc_display_contents_1_t *contents)
+{
+    // call the ExynosDisplay default implementation of assignWindows()
+    ExynosDisplay::assignWindows(contents);
+
+    // allocate the max bandwidth non-rgb layer to IDMA_G2
+    // consider only non-secure dma case - secure dma is already allocated to IDMA_G2
+
+    bool videoLayerFound = 0, curDmaYuvFound = 0, hasDRMlayer = 0;
+    uint32_t videoLayerIndex = 0, curDmaYuvIndex = 0;
+    uint32_t mTemp = 0, bandWidth = 0;
+    int fbLayerIndex = -1;
+
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+        if (!layer.handle)
+            continue;
+
+        private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
+
+        if (layer.compositionType == HWC_FRAMEBUFFER_TARGET)
+            fbLayerIndex = i;
+
+        // If there is DRM layer available, it has to go to IDMA_G2 channel.
+        if (layer.compositionType == HWC_OVERLAY &&
+                getDrmMode(handle->flags) == SECURE_DRM &&
+                !(layer.flags & HWC_SKIP_RENDERING)) {
+            hasDRMlayer = 1;
+            videoLayerFound = 1;
+            videoLayerIndex = i;
+        }
+
+        // If no DRM layer, find non-rgb overlay layer which can be supported by IDMA_G2.
+        if ((layer.compositionType == HWC_OVERLAY) &&
+                    isYuvDmaAvailable(handle->format, IDMA_G2) &&
+                    !(layer.flags & HWC_SKIP_RENDERING) &&
+                    !hasDRMlayer) {
+
+            mTemp = (layer.sourceCropf.right - layer.sourceCropf.left) *
+                (layer.sourceCropf.bottom - layer.sourceCropf.top);
+            if (mTemp > bandWidth) {
+                bandWidth = mTemp;
+                videoLayerFound = 1;
+                videoLayerIndex = i;
+            }
+        }
+
+        if (((layer.compositionType == HWC_OVERLAY) ||
+            (layer.compositionType == HWC_FRAMEBUFFER_TARGET)) &&
+            (!curDmaYuvFound) &&
+            (mLayerInfos[i]->mDmaType == IDMA_G2)) {
+            curDmaYuvFound = 1;
+            curDmaYuvIndex = i;
+        }
+    }
+
+    if (curDmaYuvFound && videoLayerFound) {
+        mTemp = mLayerInfos[videoLayerIndex]->mDmaType;
+        mLayerInfos[videoLayerIndex]->mDmaType = mLayerInfos[curDmaYuvIndex]->mDmaType;
+        mLayerInfos[curDmaYuvIndex]->mDmaType = mTemp;
+    }
+
+    if (videoLayerFound && !curDmaYuvFound) {
+        if (prevfbTargetIdma == IDMA_G2) {
+            prevfbTargetIdma = (enum decon_idma_type) mLayerInfos[videoLayerIndex]->mDmaType;
+            mLayerInfos[videoLayerIndex]->mDmaType = IDMA_G2;
+            return;
+        }
+        mLayerInfos[videoLayerIndex]->mDmaType = IDMA_G2;
+    }
+
+    if (mFbNeeded && mFbWindow < NUM_HW_WINDOWS && fbLayerIndex >= 0)
+       prevfbTargetIdma = (enum decon_idma_type) mLayerInfos[fbLayerIndex]->mDmaType;
+}
+
+int ExynosPrimaryDisplay::postMPPM2M(hwc_layer_1_t &layer, struct decon_win_config *config, int win_map, int index)
+{
+    int dst_format = mExternalMPPDstFormat;
+    private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
+    ExynosMPPModule *exynosMPP = mLayerInfos[index]->mExternalMPP;
+
+    if (exynosMPP == NULL) {
+        DISPLAY_LOGE("postMPPM2M is called but externMPP is NULL");
+        if (layer.acquireFenceFd >= 0)
+            close(layer.acquireFenceFd);
+        layer.acquireFenceFd = -1;
+        layer.releaseFenceFd = -1;
+        return -1;
+    }
+
+    hwc_frect_t sourceCrop = { 0, 0,
+            (float)WIDTH(layer.displayFrame), (float)HEIGHT(layer.displayFrame) };
+    int originalTransform = layer.transform;
+    hwc_rect_t originalDisplayFrame = layer.displayFrame;
+
+    /* OFF_Screen to ON_Screen changes */
+    if (getDrmMode(handle->flags) == SECURE_DRM)
+        recalculateDisplayFrame(layer, mXres, mYres);
+
+    if (mType != EXYNOS_VIRTUAL_DISPLAY &&
+        (isFormatRgb(handle->format) ||
+         (isYuvDmaAvailable(handle->format, mLayerInfos[index]->mDmaType) &&
+          WIDTH(layer.displayFrame) % getIDMAWidthAlign(handle->format) == 0 &&
+          HEIGHT(layer.displayFrame) % getIDMAHeightAlign(handle->format) == 0)))
+        dst_format = handle->format;
+
+    int err = exynosMPP->processM2M(layer, dst_format, &sourceCrop);
+
+    /* Restore displayFrame*/
+    layer.displayFrame = originalDisplayFrame;
+
+    if (err < 0) {
+        DISPLAY_LOGE("failed to configure MPP (type:%u, index:%u) for layer %u",
+                exynosMPP->mType, exynosMPP->mIndex, index);
+        return -1;
+    }
+
+    buffer_handle_t dst_buf = exynosMPP->mDstBuffers[exynosMPP->mCurrentBuf];
+    private_handle_t *dst_handle =
+            private_handle_t::dynamicCast(dst_buf);
+    int fence = exynosMPP->mDstConfig.releaseFenceFd;
+    hwc_frect originalCrop = layer.sourceCropf;
+
+    /* ExtMPP out is the input of Decon
+     * and Trsform was processed by ExtMPP
+     */
+    layer.sourceCropf = sourceCrop;
+    layer.transform = 0;
+    configureHandle(dst_handle, index, layer,  fence, config[win_map]);
+
+    /* Restore sourceCropf and transform */
+    layer.sourceCropf = originalCrop;
+    layer.transform = originalTransform;
+    return 0;
+}
+
+void ExynosPrimaryDisplay::handleStaticLayers(hwc_display_contents_1_t *contents,
+    struct decon_win_config_data &win_data, int __unused tot_ovly_wins)
+{
+    unsigned int bitmap = 0;
+    bool incorrect_mapping = false;
+
+    ExynosDisplay::handleStaticLayers(contents, win_data, tot_ovly_wins);
+
+    if (mLastFbWindow >= NUM_HW_WINDOWS) {
+        DISPLAY_LOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow);
+        return;
+    }
+
+    win_data.config[mLastFbWindow].idma_type = prevfbTargetIdma;
+
+    for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
+        if (win_data.config[i].state == win_data.config[i].DECON_WIN_STATE_BUFFER) {
+            if (bitmap & (1 << win_data.config[i].idma_type)) {
+                ALOGE("handleStaticLayers: Channel-%d is mapped to multiple windows\n", win_data.config[i].idma_type);
+                incorrect_mapping = true;
+            }
+
+            bitmap |= 1 << win_data.config[i].idma_type;
+        }
+    }
+
+    if (incorrect_mapping) {
+        android::String8 result;
+        result.clear();
+        dump(result);
+        ALOGE("%s", result.string());
+        result.clear();
+        dumpLayerInfo(result);
+        ALOGE("%s", result.string());
+        ALOGE("Display Config:");
+        dump_win_config(&win_data.config[0]);
+    }
+}
+
+void ExynosPrimaryDisplay::dump_win_config(struct decon_win_config *config)
+{
+    int win;
+    struct decon_win_config *cfg;
+    const char *state[] = { "DSBL", "COLR", "BUFF", "UPDT" };
+    const char *blending[] = { "NOBL", "PMUL", "COVR" };
+    const char *idma[] = { "G0", "G1", "V0", "V1", "VR0", "VR1", "G2" };
+
+    for (win = 0; win < MAX_DECON_WIN; win++) {
+        cfg = &config[win];
+
+        if (cfg->state == cfg->DECON_WIN_STATE_DISABLED)
+        continue;
+
+        if (cfg->state == cfg->DECON_WIN_STATE_COLOR) {
+            ALOGE("Win[%d]: %s, C(%d), Dst(%d,%d,%d,%d) "
+                "P(%d)\n",
+                win, state[cfg->state], cfg->color,
+                cfg->dst.x, cfg->dst.y,
+                cfg->dst.x + cfg->dst.w,
+                cfg->dst.y + cfg->dst.h,
+                cfg->protection);
+        } else {
+            ALOGE("Win[%d]: %s,(%d,%d,%d), F(%d) P(%d)"
+                " A(%d), %s, %s, fmt(%d) Src(%d,%d,%d,%d,f_w=%d,f_h=%d) ->"
+                " Dst(%d,%d,%d,%d,f_w=%d,f_h=%d) T(%d,%d,%d,%d) B(%d,%d,%d,%d)\n",
+                win, state[cfg->state], cfg->fd_idma[0],
+                cfg->fd_idma[1], cfg->fd_idma[2],
+                cfg->fence_fd, cfg->protection,
+                cfg->plane_alpha, blending[cfg->blending],
+                idma[cfg->idma_type], cfg->format,
+                cfg->src.x, cfg->src.y, cfg->src.x + cfg->src.w, cfg->src.y + cfg->src.h,
+                cfg->src.f_w, cfg->src.f_h,
+                cfg->dst.x, cfg->dst.y, cfg->dst.x + cfg->dst.w, cfg->dst.y + cfg->dst.h,
+                cfg->dst.f_w, cfg->dst.f_h,
+                cfg->transparent_area.x, cfg->transparent_area.y,
+                cfg->transparent_area.w, cfg->transparent_area.h,
+                cfg->covered_opaque_area.x, cfg->covered_opaque_area.y,
+                cfg->covered_opaque_area.w, cfg->covered_opaque_area.h);
+        }
+    }
+}
+
+int ExynosPrimaryDisplay::handleWindowUpdate(hwc_display_contents_1_t __unused *contents,
+    struct decon_win_config __unused *config)
+{
+    int layerIdx = -1;
+    int updatedWinCnt = 0;
+    int totalWinCnt = 0;
+    int bitsPerPixel = 0;
+    size_t winUpdateInfoIdx;
+    hwc_rect updateRect = {this->mXres, this->mYres, 0, 0};
+    hwc_rect currentRect = {0, 0, 0, 0};
+    bool burstLengthCheckDone = false;
+    int alignAdjustment = 0;
+    int intersectionWidth = 0;
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.hwc.winupdate", value, NULL);
+
+    if (!(!strcmp(value, "1") || !strcmp(value, "true")))
+        return -eWindowUpdateDisabled;
+
+    if (DECON_WIN_UPDATE_IDX < 0)
+        return -eWindowUpdateInvalidIndex;
+    winUpdateInfoIdx = DECON_WIN_UPDATE_IDX;
+
+    if (contents->flags & HWC_GEOMETRY_CHANGED)
+        return -eWindowUpdateGeometryChanged;
+
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
+            continue;
+
+        if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
+            continue;
+        int32_t windowIndex = mLayerInfos[i]->mWindowIndex;
+        if (config[windowIndex].state != config[windowIndex].DECON_WIN_STATE_DISABLED) {
+            totalWinCnt++;
+
+            if (winConfigChanged(&config[windowIndex], &this->mLastConfigData.config[windowIndex])) {
+                updatedWinCnt++;
+
+                currentRect.left   = config[windowIndex].dst.x;
+                currentRect.right  = config[windowIndex].dst.x + config[windowIndex].dst.w;
+                currentRect.top    = config[windowIndex].dst.y;
+                currentRect.bottom = config[windowIndex].dst.y + config[windowIndex].dst.h;
+
+                if (hwcHasApiVersion((hwc_composer_device_1_t*)mHwc, HWC_DEVICE_API_VERSION_1_5))
+                {
+                    private_handle_t *handle = NULL;
+                    hwc_rect damageRect = {0, 0, 0, 0};
+                    hwc_layer_1_t &layer = contents->hwLayers[i];
+                    if (layer.handle)
+                        handle = private_handle_t::dynamicCast(layer.handle);
+                    getLayerRegion(layer, damageRect, eDamageRegion);
+
+                    if (handle && !isScaled(layer) && !isRotated(layer)
+                            && !(!(damageRect.left) && !(damageRect.top) && !(damageRect.right) && !(damageRect.bottom))) {
+                        HLOGD("[WIN_UPDATE][surfaceDamage]  layer w(%4d) h(%4d),  dirty (%4d, %4d) - (%4d, %4d)",
+                                handle->width, handle->height, damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
+
+                        currentRect.left   = config[windowIndex].dst.x - (int32_t)layer.sourceCropf.left + damageRect.left;
+                        currentRect.right  = config[windowIndex].dst.x - (int32_t)layer.sourceCropf.left + damageRect.right;
+                        currentRect.top    = config[windowIndex].dst.y - (int32_t)layer.sourceCropf.top  + damageRect.top;
+                        currentRect.bottom = config[windowIndex].dst.y - (int32_t)layer.sourceCropf.top  + damageRect.bottom;
+
+                    }
+                }
+
+                if ((currentRect.left > currentRect.right) || (currentRect.top > currentRect.bottom)) {
+                    HLOGD("[WIN_UPDATE] window(%d) layer(%d) invalid region (%4d, %4d) - (%4d, %4d)",
+                        i, layerIdx, currentRect.left, currentRect.top, currentRect.right, currentRect.bottom);
+                    return -eWindowUpdateInvalidRegion;
+                }
+                HLOGD("[WIN_UPDATE] Updated Window(%d) Layer(%d)  (%4d, %4d) - (%4d, %4d)",
+                    windowIndex, i, currentRect.left, currentRect.top, currentRect.right, currentRect.bottom);
+                updateRect = expand(updateRect, currentRect);
+            }
+        }
+    }
+    if (updatedWinCnt == 0)
+        return -eWindowUpdateNotUpdated;
+
+    updateRect.left  = ALIGN_DOWN(updateRect.left, WINUPDATE_X_ALIGNMENT);
+    updateRect.right = updateRect.left + ALIGN_UP(WIDTH(updateRect), WINUPDATE_W_ALIGNMENT);
+
+    if (HEIGHT(updateRect) < WINUPDATE_MIN_HEIGHT) {
+        if (updateRect.top + WINUPDATE_MIN_HEIGHT <= mYres)
+            updateRect.bottom = updateRect.top + WINUPDATE_MIN_HEIGHT;
+        else
+            updateRect.top = updateRect.bottom - WINUPDATE_MIN_HEIGHT;
+    }
+
+    if ((100 * (WIDTH(updateRect) * HEIGHT(updateRect)) / (this->mXres * this->mYres)) > WINUPDATE_THRESHOLD)
+        return -eWindowUpdateOverThreshold;
+
+    alignAdjustment = max(WINUPDATE_X_ALIGNMENT, WINUPDATE_W_ALIGNMENT);
+
+    while (1) {
+        burstLengthCheckDone = true;
+
+        for (size_t i = 0; i < contents->numHwLayers; i++) {
+            if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
+                continue;
+            if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
+                continue;
+            int32_t windowIndex = mLayerInfos[i]->mWindowIndex;
+            if (config[windowIndex].state != config[windowIndex].DECON_WIN_STATE_DISABLED) {
+                enum decon_pixel_format fmt = config[windowIndex].format;
+
+                if (fmt == DECON_PIXEL_FORMAT_RGBA_5551 || fmt == DECON_PIXEL_FORMAT_RGB_565 )
+                        bitsPerPixel = 16;
+                else if (fmt == DECON_PIXEL_FORMAT_NV12 || fmt == DECON_PIXEL_FORMAT_NV21 ||
+                    fmt == DECON_PIXEL_FORMAT_NV12M || fmt == DECON_PIXEL_FORMAT_NV21M)
+                        bitsPerPixel = 12;
+                else
+                        bitsPerPixel = 32;
+
+                currentRect.left   = config[windowIndex].dst.x;
+                currentRect.right  = config[windowIndex].dst.x + config[windowIndex].dst.w;
+                currentRect.top    = config[windowIndex].dst.y;
+                currentRect.bottom = config[windowIndex].dst.y + config[windowIndex].dst.h;
+
+                intersectionWidth = WIDTH(intersection(currentRect, updateRect));
+
+                HLOGV("[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", windowIndex, currentRect.left, currentRect.right, intersectionWidth);
+
+                if (intersectionWidth != 0 && (size_t)((intersectionWidth * bitsPerPixel) / 8) < BURSTLEN_BYTES) {
+                    HLOGV("[WIN_UPDATE] win[%d] insufficient burst length ((%d)*(%d)/8) < %d", windowIndex, intersectionWidth, bitsPerPixel, BURSTLEN_BYTES);
+                    burstLengthCheckDone = false;
+                    break;
+                }
+            }
+        }
+
+        if (burstLengthCheckDone)
+            break;
+        HLOGD("[WIN_UPDATE] Adjusting update width. current left(%d) right(%d)", updateRect.left, updateRect.right);
+        if (updateRect.left >= alignAdjustment) {
+            updateRect.left -= alignAdjustment;
+        } else if (updateRect.right + alignAdjustment <= this->mXres) {
+            updateRect.right += alignAdjustment;
+        } else {
+            DISPLAY_LOGD("[WIN_UPDATE] Error during update width adjustment");
+            return -eWindowUpdateAdjustmentFail;
+        }
+    }
+
+    config[winUpdateInfoIdx].state = config[winUpdateInfoIdx].DECON_WIN_STATE_UPDATE;
+    config[winUpdateInfoIdx].dst.x = updateRect.left;
+    config[winUpdateInfoIdx].dst.y = updateRect.top;
+    config[winUpdateInfoIdx].dst.w = ALIGN_UP(WIDTH(updateRect), WINUPDATE_W_ALIGNMENT);
+    config[winUpdateInfoIdx].dst.h = HEIGHT(updateRect);
+
+    HLOGD("[WIN_UPDATE] UpdateRegion cfg  (%4d, %4d) w(%4d) h(%4d) updatedWindowCnt(%d)",
+        config[winUpdateInfoIdx].dst.x, config[winUpdateInfoIdx].dst.y, config[winUpdateInfoIdx].dst.w, config[winUpdateInfoIdx].dst.h, updatedWinCnt);
+
+    /* Disable block mode if window update region is not full screen */
+    if ((config[winUpdateInfoIdx].dst.x != 0) || (config[winUpdateInfoIdx].dst.y != 0) ||
+        (config[winUpdateInfoIdx].dst.w != (uint32_t)mXres) || (config[winUpdateInfoIdx].dst.h != (uint32_t)mXres)) {
+        for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
+            memset(&config[i].transparent_area, 0, sizeof(config[i].transparent_area));
+            memset(&config[i].covered_opaque_area, 0, sizeof(config[i].covered_opaque_area));
+        }
+    }
+
+    return 1;
+}
+
+int ExynosPrimaryDisplay::getIDMAWidthAlign(int format)
+{
+    if (isFormatRgb(format))
+        return 1;
+    else
+        return 2;
+}
+
+int ExynosPrimaryDisplay::getIDMAHeightAlign(int format)
+{
+    if (isFormatRgb(format))
+        return 1;
+    else
+        return 2;
+}
diff --git a/libdisplaymodule/ExynosPrimaryDisplay.h b/libdisplaymodule/ExynosPrimaryDisplay.h
new file mode 100644 (file)
index 0000000..0148400
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef EXYNOS_DISPLAY_MODULE_H
+#define EXYNOS_DISPLAY_MODULE_H
+
+#include "ExynosOverlayDisplay.h"
+
+class ExynosPrimaryDisplay : public ExynosOverlayDisplay {
+        enum decon_idma_type prevfbTargetIdma;
+
+    public:
+        ExynosPrimaryDisplay(int numGSCs, struct exynos5_hwc_composer_device_1_t *pdev);
+        ~ExynosPrimaryDisplay();
+
+        virtual int getDeconWinMap(int overlayIndex, int totalOverlays);
+        virtual void forceYuvLayersToFb(hwc_display_contents_1_t *contents);
+        virtual int getMPPForUHD(hwc_layer_1_t &layer);
+        virtual int getRGBMPPIndex(int index);
+
+        void assignWindows(hwc_display_contents_1_t *contents);
+        int postMPPM2M(hwc_layer_1_t &layer, struct decon_win_config *config, int win_map, int index);
+        bool isOverlaySupported(hwc_layer_1_t &layer, size_t index,
+                bool useVPPOverlay,
+                ExynosMPPModule** supportedInternalMPP,
+                ExynosMPPModule** supportedExternalMPP);
+        bool isYuvDmaAvailable(int format, uint32_t dma);
+        void handleStaticLayers(hwc_display_contents_1_t *contents,
+                struct decon_win_config_data &win_data,
+                int __unused tot_ovly_wins);
+        int handleWindowUpdate(hwc_display_contents_1_t __unused *contents,
+                struct decon_win_config __unused *config);
+        void dump_win_config(struct decon_win_config *config);
+        int getIDMAWidthAlign(int format);
+        int getIDMAHeightAlign(int format);
+};
+
+#endif
diff --git a/libdisplaymodule/ExynosSecondaryDisplayModule.cpp b/libdisplaymodule/ExynosSecondaryDisplayModule.cpp
new file mode 100644 (file)
index 0000000..7a33137
--- /dev/null
@@ -0,0 +1,13 @@
+#include "ExynosSecondaryDisplayModule.h"
+#include "ExynosHWCModule.h"
+#include "ExynosHWCUtils.h"
+#include "ExynosMPPModule.h"
+
+ExynosSecondaryDisplayModule::ExynosSecondaryDisplayModule(struct exynos5_hwc_composer_device_1_t *pdev) :
+    ExynosSecondaryDisplay(pdev)
+{
+}
+
+ExynosSecondaryDisplayModule::~ExynosSecondaryDisplayModule()
+{
+}
diff --git a/libdisplaymodule/ExynosSecondaryDisplayModule.h b/libdisplaymodule/ExynosSecondaryDisplayModule.h
new file mode 100644 (file)
index 0000000..9dcde17
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef EXYNOS_SECONDARY_DISPLAY_MODULE_H
+#define EXYNOS_SECONDARY_DISPLAY_MODULE_H
+
+#include "ExynosSecondaryDisplay.h"
+
+class ExynosSecondaryDisplayModule : public ExynosSecondaryDisplay {
+    public:
+        ExynosSecondaryDisplayModule(struct exynos5_hwc_composer_device_1_t *pdev);
+        ~ExynosSecondaryDisplayModule();
+};
+
+#endif
diff --git a/libdisplaymodule/NOTICE b/libdisplaymodule/NOTICE
new file mode 100644 (file)
index 0000000..c1c71a2
--- /dev/null
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2014, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/libgatekeeper/Android.mk b/libgatekeeper/Android.mk
new file mode 100644 (file)
index 0000000..64389ce
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+MOBICORE_PATH := hardware/samsung_slsi/$(TARGET_SOC)/mobicore
+CURRENT_PATH := hardware/samsung_slsi/$(TARGET_SOC)/libgatekeeper
+
+LOCAL_MODULE := gatekeeper.$(TARGET_SOC)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_SRC_FILES := exynos_gatekeeper.cpp \
+                  tlcTeeGatekeeper_if.cpp
+
+LOCAL_C_INCLUDES := \
+       $(CURRENT_PATH)/include \
+       $(MOBICORE_PATH)/daemon/ClientLib/public \
+       $(MOBICORE_PATH)/common/MobiCore/inc/
+
+LOCAL_CFLAGS := -fvisibility=hidden
+LOCAL_CFLAGS += -Wall -Werror
+
+ifeq ($(PRODUCT_TRUSTZONE_ENABLED), true)
+LOCAL_CFLAGS += -DACCESS_EFS_POSSIBLE
+endif
+LOCAL_SHARED_LIBRARIES := liblog \
+                         libMcClient
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libgatekeeper/exynos_gatekeeper.cpp b/libgatekeeper/exynos_gatekeeper.cpp
new file mode 100644 (file)
index 0000000..9fa782e
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2015, Samsung Electronics Co., LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed toggle an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gatekeeper.h>
+#include <hardware/hw_auth_token.h>
+
+#include <UniquePtr.h>
+
+#include "tlcTeeGatekeeper_if.h"
+#include "password_handle.h"
+
+#include <utils/Log.h>
+#include <cutils/log.h>
+
+typedef UniquePtr<gatekeeper_device_t> Unique_gatekeeper_device_t;
+
+#define MAX_PASSWORD_LEN 100
+
+#undef GATEKEEPER_DEBUG
+
+#ifdef GATEKEEPER_DEBUG
+uint8_t temp[1000];
+#endif
+
+#ifdef GATEKEEPER_DEBUG
+void dump(const uint8_t *ptr, uint32_t size)
+{
+       unsigned int i;
+
+       memset(temp, 0x0, sizeof(temp));
+
+       ALOGE("[exy_gk] DUMP=================");
+       for (i = 0; i < size; i++) {
+               if(i % 16 == 0){
+                       ALOGE("[exy_gk] %s", temp);
+                       memset(temp, 0x0, sizeof(temp));
+               }
+               sprintf((char*)(temp + ((i % 16) * 3)), "%02x ", *(ptr + i));
+       }
+
+       if (i % 16)
+               ALOGE("[exy_gk] %s", temp);
+}
+#endif
+
+int enroll(const struct gatekeeper_device *dev, uint32_t uid,
+               const uint8_t *current_password_handle,
+               uint32_t current_password_handle_length,
+               const uint8_t *current_password, uint32_t current_password_length,
+               const uint8_t *desired_password, uint32_t desired_password_length,
+               uint8_t **enrolled_password_handle,
+               uint32_t *enrolled_password_handle_length)
+{
+       teeResult_t teeRet = TEE_ERR_NONE;
+       int32_t retry_timeout = 0;
+       password_handle_t *handle;
+
+       if (dev == NULL ||
+                       desired_password == NULL ||
+                       enrolled_password_handle == NULL ||
+                       enrolled_password_handle_length == NULL) {
+               ALOGE("[exy_gk][%s][%d] Wrong parameter.", __func__, __LINE__);
+               return -1;
+       }
+
+       if (current_password_handle == NULL || current_password_handle_length == 0 ||
+                       current_password == NULL || current_password_length == 0) {
+               current_password_handle = NULL;
+               current_password_handle_length = 0;
+               current_password = NULL;
+               current_password_length = 0;
+       }
+
+       if (current_password_handle_length > sizeof(struct password_handle_t) ||
+                       current_password_length > MAX_PASSWORD_LEN ||
+                       desired_password_length > MAX_PASSWORD_LEN) {
+               ALOGE("[exy_gk][%s][%d] Wrong parameter.", __func__, __LINE__);
+               return -1;
+       }
+
+#ifdef GATEKEEPER_DEBUG
+       ALOGE("[exy_gk][%s][%d]", __func__, __LINE__);
+
+       memset(temp, 0x0, sizeof(temp));
+       if (current_password_length > sizeof(temp)) {
+                ALOGE("[exy_gk][%s][%d] current_password_length is too long.",
+                                __func__, __LINE__);
+                return -1;
+       }
+       memcpy(temp, current_password, current_password_length);
+       ALOGE("[exy_gk] current_password [%s]",temp);
+
+       memset(temp, 0x0, sizeof(temp));
+       if (desired_password_length > sizeof(temp)) {
+                ALOGE("[exy_gk][%s][%d] desired_password_length is too long.",
+                                __func__, __LINE__);
+                return -1;
+       }
+       memcpy(temp, desired_password, desired_password_length);
+       ALOGE("[exy_gk] desired_password [%s]",temp);
+#endif
+       if (enrolled_password_handle == NULL) {
+               ALOGE("[exy_gk] enrolled_password_handle ptr is NULL. [%s][%d]", __func__, __LINE__);
+               return -1;
+       }
+       if (enrolled_password_handle_length == NULL) {
+               ALOGE("[exy_gk] enrolled_password_handle_length ptr is NULL. [%s][%d]", __func__, __LINE__);
+               return -1;
+       }
+
+       // the handle will be removed in the reture process of gatekeeprd.
+       handle = new password_handle_t;
+       *enrolled_password_handle = (uint8_t*)handle;
+       *enrolled_password_handle_length = sizeof(password_handle_t);
+
+       if (current_password_handle_length != 0) {
+#ifdef GATEKEEPER_DEBUG
+               ALOGE("[exy_gk] Dump current_handle");
+               dump(current_password_handle, current_password_handle_length);
+#endif
+       }
+       teeRet = TEE_Enroll(uid, current_password_handle,
+                               current_password_handle_length,
+                               current_password,
+                               current_password_length,
+                               desired_password, desired_password_length,
+                               (uint8_t*)handle,
+                               enrolled_password_handle_length,
+                               &retry_timeout, dev);
+
+       if (teeRet != TEE_ERR_NONE) {
+               return (retry_timeout ? retry_timeout : -1);
+       }
+
+#ifdef GATEKEEPER_DEBUG
+       ALOGE("[exy_gk] Dump new_handle");
+       dump(*enrolled_password_handle, *enrolled_password_handle_length);
+       ALOGE("[exy_gk] enrolled user_id [%llx]",handle->user_id);
+#endif
+
+       return 0;
+}
+
+int verify(const struct gatekeeper_device *dev, uint32_t uid,
+               uint64_t challenge, const uint8_t *enrolled_password_handle,
+               uint32_t enrolled_password_handle_length,
+               const uint8_t *provided_password,
+               uint32_t provided_password_length, uint8_t **auth_token,
+               uint32_t *auth_token_length, bool *request_reenroll)
+{
+       teeResult_t teeRet = TEE_ERR_NONE;
+       int32_t retry_timeout = 0;
+       hw_auth_token_t *token;
+
+       if (dev == NULL ||
+                       enrolled_password_handle == NULL ||
+                       provided_password == NULL ||
+                       auth_token == NULL ||
+                       auth_token_length == NULL ||
+                       request_reenroll == NULL) {
+               ALOGE("[exy_gk][%s][%d] Wrong parameter.", __func__, __LINE__);
+               return -1;
+       }
+
+       if (enrolled_password_handle_length > sizeof(struct password_handle_t) ||
+                       provided_password_length > MAX_PASSWORD_LEN) {
+               ALOGE("[exy_gk][%s][%d] Wrong parameter.", __func__, __LINE__);
+               return -1;
+       }
+#ifdef GATEKEEPER_DEBUG
+       ALOGE("[exy_gk][%s][%d]", __func__, __LINE__);
+
+       memset(temp, 0x0, sizeof(temp));
+       if (provided_password_length > sizeof(temp)) {
+                ALOGE("[exy_gk][%s][%d] provided_password_length is too long.",
+                                __func__, __LINE__);
+                return -1;
+       }
+       memcpy(temp, provided_password, provided_password_length);
+       ALOGE("[exy_gk] provided_password [%s]",temp);
+#endif
+       if (auth_token == NULL) {
+               ALOGE("[exy_gk] auth_token ptr is NULL. [%s][%d]", __func__, __LINE__);
+               return -1;
+       }
+
+       if (auth_token_length == NULL) {
+               ALOGE("[exy_gk] auth_token_length ptr is NULL. [%s][%d]", __func__, __LINE__);
+               return -1;
+       }
+
+       // the handle will be removed in the return process of keymaster.
+       token = new hw_auth_token_t;
+
+       *auth_token = (uint8_t*)token;
+       *auth_token_length = sizeof(hw_auth_token_t);
+
+       teeRet = TEE_Verify(uid, challenge,
+                               enrolled_password_handle,
+                               enrolled_password_handle_length,
+                               provided_password, provided_password_length,
+                               auth_token, auth_token_length, request_reenroll,
+                               &retry_timeout, dev);
+
+       if (teeRet != TEE_ERR_NONE) {
+               return (retry_timeout ? retry_timeout : -1);
+       }
+
+       return 0;
+}
+
+/* Close an opened Exynos GK instance */
+static int exynos_gk_close(hw_device_t *dev)
+{
+#ifdef GATEKEEPER_DEBUG
+       ALOGE("[exy_gk][%s][%d]", __func__, __LINE__);
+#endif
+       free(dev);
+       return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int exynos_gk_open(const hw_module_t *module, const char *name,
+                               hw_device_t **device)
+{
+       if (module == NULL || name == NULL) {
+               ALOGE("[exy_gk][%s][%d] Wrong parameter.", __func__, __LINE__);
+               return -1;
+       }
+#ifdef GATEKEEPER_DEBUG
+       ALOGE("[exy_gk][%s][%d]", __func__, __LINE__);
+#endif
+       if (strncmp(name, HARDWARE_GATEKEEPER, strlen(HARDWARE_GATEKEEPER)) != 0) {
+               ALOGE("[exy_gk]requested name = [%s], my name = [%s]\n",
+                               name, HARDWARE_GATEKEEPER);
+               return -EINVAL;
+       }
+
+       Unique_gatekeeper_device_t dev(new gatekeeper_device_t);
+       if (dev.get() == NULL)
+               return -ENOMEM;
+
+       dev->common.tag = HARDWARE_DEVICE_TAG;
+       dev->common.version = 1;
+       dev->common.module = (struct hw_module_t*) module;
+       dev->common.close = exynos_gk_close;
+
+       dev->enroll = enroll;
+       dev->verify = verify;
+       dev->delete_user = NULL;
+       dev->delete_all_users = NULL;
+
+       *device = reinterpret_cast<hw_device_t*>(dev.release());
+
+       return 0;
+}
+
+static struct hw_module_methods_t gatekeeper_module_methods = {
+    open: exynos_gk_open,
+};
+
+
+struct gatekeeper_module HAL_MODULE_INFO_SYM
+__attribute__ ((visibility ("default"))) = {
+       .common =
+       {
+               .tag = HARDWARE_MODULE_TAG,
+               .module_api_version = GATEKEEPER_MODULE_API_VERSION_0_1,
+               .hal_api_version = HARDWARE_HAL_API_VERSION,
+               .id = GATEKEEPER_HARDWARE_MODULE_ID,
+               .name = HARDWARE_GATEKEEPER,
+               .author = "The Android Open Source Project",
+               .methods = &gatekeeper_module_methods,
+               .dso = 0,
+               .reserved = {},
+       },
+};
diff --git a/libgatekeeper/include/password_handle.h b/libgatekeeper/include/password_handle.h
new file mode 100644 (file)
index 0000000..33943ba
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GATEKEEPER_PASSWORD_HANDLE_H_
+#define GATEKEEPER_PASSWORD_HANDLE_H_
+
+#define HANDLE_FLAG_THROTTLE_SECURE 1
+
+#define HANDLE_VERSION_THROTTLE 2
+
+typedef uint64_t secure_id_t;
+typedef uint64_t salt_t;
+/**
+ * structure for easy serialization
+ * and deserialization of password handles.
+ */
+static const uint8_t HANDLE_VERSION = 2;
+struct __attribute__ ((__packed__)) password_handle_t {
+    // fields included in signature
+    uint8_t version;
+    secure_id_t user_id;
+    uint64_t flags;
+
+    // fields not included in signature
+    salt_t salt;
+    uint8_t signature[32];
+
+    bool hardware_backed;
+};
+
+#endif // GATEKEEPER_PASSWORD_HANDLE_H_
diff --git a/libgatekeeper/include/tci.h b/libgatekeeper/include/tci.h
new file mode 100644 (file)
index 0000000..27363f2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TCI_H__
+#define __TCI_H__
+
+
+typedef uint32_t tciCommandId_t;
+typedef uint32_t tciResponseId_t;
+typedef uint32_t tciReturnCode_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)
+
+
+/**
+ * Return codes
+ */
+#define RET_OK                 0x00
+#define RET_ERR_UNKNOWN_CMD    0x01
+#define RET_ERR_NOT_SUPPORTED  0x02
+#define RET_ERR_WRONG_PASSWORD 0x03
+#define RET_ERR_INTERNAL_ERROR 0xFF
+/* ... add more error codes when needed */
+
+
+/**
+ * TCI command header.
+ */
+typedef struct{
+    tciCommandId_t commandId; /**< Command ID */
+} tciCommandHeader_t;
+
+
+/**
+ * TCI response header.
+ */
+typedef struct{
+    tciResponseId_t     responseId; /**< Response ID (must be command ID | RSP_ID_MASK )*/
+    tciReturnCode_t     returnCode; /**< Return code of command */
+} tciResponseHeader_t;
+
+#endif // __TCI_H__
diff --git a/libgatekeeper/include/tlTeeGatekeeper_Api.h b/libgatekeeper/include/tlTeeGatekeeper_Api.h
new file mode 100644 (file)
index 0000000..7111647
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015, Samsung Electronics Co., LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed toggle an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TLTEEGATEKEEPERAPI_H__
+#define __TLTEEGATEKEEPERAPI_H__
+
+#include "tci.h"
+
+/* Command ID's */
+#define CMD_ID_TEE_ENROLL              1
+#define CMD_ID_TEE_VERIFY              2
+
+/* Command message */
+typedef struct {
+       tciCommandHeader_t  header;
+       uint32_t            len;
+} command_t;
+
+
+/* Response structure */
+typedef struct {
+       tciResponseHeader_t header;
+       uint32_t            len;
+} response_t;
+
+typedef struct {
+       /* in params */
+       uint32_t uid;
+       uint32_t current_password_handle_va;
+       uint32_t current_password_handle_length;
+       uint32_t current_password_va;
+       uint32_t current_password_length;
+       uint32_t desired_password_va;
+       uint32_t desired_password_length;
+       uint64_t nw_timestamp; /* deprecated, it should be changed to secure timer */
+       /* out params */
+       uint32_t enrolled_password_handle_va;
+       uint32_t enrolled_password_handle_length;
+       int32_t retry_timeout;
+       /* Wrapping */
+       uint32_t secure_object_va;
+} gk_enroll_t;
+
+typedef struct {
+       /* in params */
+       uint32_t uid;
+       uint64_t challenge;
+       uint32_t enrolled_password_handle_va;
+       uint32_t enrolled_password_handle_length;
+       uint32_t provided_password_va;
+       uint32_t provided_password_length;
+       uint64_t nw_timestamp; /* deprecated, it should be changed to secure timer */
+       /* out params */
+       uint32_t auth_token_va;
+       uint32_t auth_token_length;
+       int32_t retry_timeout;
+       /* in / out params */
+       bool request_reenroll;
+       /* Wrapping */
+       uint32_t secure_object_va;
+} gk_verify_t;
+
+/* TCI message data. */
+typedef struct {
+       union {
+               command_t     command;
+               response_t    response;
+       };
+       union {
+               gk_verify_t  gk_verify;
+               gk_enroll_t  gk_enroll;
+       };
+} tciMessage_t, *tciMessage_ptr;
+
+/* Overall TCI structure */
+typedef struct {
+       tciMessage_t message;
+} tci_t;
+
+/* Trustlet UUID */
+#define TEE_GATEKEEPER_TL_UUID {{0x08, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
+
+#endif // __TLTEEGATEKEEPERAPI_H__
diff --git a/libgatekeeper/include/tlcTeeGatekeeper_if.h b/libgatekeeper/include/tlcTeeGatekeeper_if.h
new file mode 100644 (file)
index 0000000..09d4df8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLCTEEGATEKEEPERIF_H__
+#define __TLCTEEGATEKEEPERIF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+/* error codes */
+typedef enum
+{
+    TEE_ERR_NONE             = 0,
+    TEE_ERR_FAIL             = 1,
+    TEE_ERR_INVALID_BUFFER   = 2,
+    TEE_ERR_BUFFER_TOO_SMALL = 3,
+    TEE_ERR_NOT_IMPLEMENTED  = 4,
+    TEE_ERR_SESSION          = 5,
+    TEE_ERR_MC_DEVICE        = 6,
+    TEE_ERR_NOTIFICATION     = 7,
+    TEE_ERR_MEMORY           = 8,
+    TEE_ERR_MAP              = 9,
+    TEE_ERR_UNMAP            = 10,
+    TEE_ERR_INVALID_INPUT    = 11
+    /* more can be added as required */
+} teeResult_t;
+
+teeResult_t TEE_Enroll(uint32_t uid,
+               const uint8_t *current_password_handle,
+               uint32_t current_password_handle_length,
+               const uint8_t *current_password,
+               uint32_t current_password_length,
+               const uint8_t *desired_password,
+               uint32_t desired_password_length,
+               uint8_t *enrolled_password_handle,
+               uint32_t *enrolled_password_handle_length,
+               int32_t *retry_timeout,
+               const struct gatekeeper_device * /* not used */);
+
+teeResult_t TEE_Verify(uint32_t uid,
+               uint64_t challenge, const uint8_t *enrolled_password_handle,
+               uint32_t enrolled_password_handle_length,
+               const uint8_t *provided_password,
+               uint32_t provided_password_length,
+               uint8_t **auth_token, uint32_t *auth_token_length,
+               bool *request_reenroll, int32_t *retry_timeout,
+               const struct gatekeeper_device * /* not used */);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __TLCTEEGATEKEEPERIF_H__
diff --git a/libgatekeeper/include/tlcTeeGatekeeper_log.h b/libgatekeeper/include/tlcTeeGatekeeper_log.h
new file mode 100644 (file)
index 0000000..70490f9
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLCTEEGATEKEEPERLOG_H__
+#define __TLCTEEGATEKEEPERLOG_H__
+
+#include <android/log.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "TlcTeeGatekeeper"
+#endif // LOG_TAG
+
+/* Macro definitions */
+#define LOG_D(...) __android_log_print(ANDROID_LOG_DEBUG , LOG_TAG, __VA_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__)
+
+
+#endif // __TLCTEEGATEKEEPERLOG_H__
diff --git a/libgatekeeper/tlcTeeGatekeeper_if.cpp b/libgatekeeper/tlcTeeGatekeeper_if.cpp
new file mode 100644 (file)
index 0000000..46f26c9
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2015, Samsung Electronics Co., LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed toggle an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <hardware/hw_auth_token.h>
+
+#include "MobiCoreDriverApi.h"
+
+#include "password_handle.h"
+#include "tlTeeGatekeeper_Api.h"
+#include "tlcTeeGatekeeper_if.h"
+#include "tlcTeeGatekeeper_log.h"
+#include "tci.h"
+
+#include <utils/Log.h>
+#include <cutils/log.h>
+
+#include <time.h>
+#include <stdio.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef ACCESS_EFS_POSSIBLE
+#define FNAME  "/efs/TEE/gk_context_"
+#define FNAME_SUB      "/efs/TEE/gk_context_sub_"
+#else
+#define FNAME  "/data/app/gk_context_"
+#define FNAME_SUB      "/data/app/gk_context_sub_"
+#endif
+#define SECURE_OBJECT_SIZE 108
+
+#define SEC_TO_MS (1000)
+#define NS_TO_MS (1000*1000)
+
+/* Global definitions */
+static const uint32_t gDeviceId = MC_DEVICE_ID_DEFAULT;
+tciMessage_ptr     pTci = NULL;
+mcSessionHandle_t  sessionHandle;
+
+/** File path for Trusted Application */
+char secureSecDispTrustedApp[] = "/system/app/mcRegistry/08130000000000000000000000000000.tlbin";
+
+#define TEE_SESSION_CLOSED 0
+#define TEE_SESSION_OPENED 1
+
+/* va_gap for mcMap */
+/* mcMap in Enroll - current_password_handle(0x0) | secure_object(0x400) | current_password(0x800) | desired_password(0xc00) | enrolled_password_handle(0x1000) */
+/* mcMap in Verify - enrolled_password_handle(0x0) | secure_object(0x400) | provided_password(0x800) | auth_token(0xc00) */
+#define vagap_secure_object (0x400)
+#define vagap_current_password (0x800)
+#define vagap_desired_password (0xc00)
+#define vagap_enrolled_password_handle (0x1000)
+
+#define vagap_provided_password (0x800)
+#define vagap_auth_token (0xc00)
+
+static uint32_t session_status = TEE_SESSION_CLOSED;
+
+uint64_t clock_gettime_millisec(void)
+{
+       struct timespec time;
+       uint64_t sec;
+       long ns;
+
+       clock_gettime(CLOCK_MONOTONIC_RAW, &time);
+
+       if (time.tv_sec >= 0)
+               sec = time.tv_sec;
+       else
+               return 0;
+
+       ns = time.tv_nsec;
+       return (sec * SEC_TO_MS) + (ns / NS_TO_MS);
+}
+
+static size_t getFileContent(const char *pPath, uint8_t **ppContent)
+{
+       FILE    *pStream;
+       long    filesize;
+       uint8_t *content = NULL;
+       /*
+       * The stat function is not used (not available in WinCE).
+       */
+
+       /* Open the file */
+       pStream = fopen(pPath, "rb");
+       if (pStream == NULL) {
+               fprintf(stderr, "Error: Cannot open file: %s.\n", pPath);
+               return 0;
+       }
+       if (fseek(pStream, 0L, SEEK_END) != 0) {
+               fprintf(stderr, "Error: Cannot read file: %s.\n", pPath);
+               goto error;
+       }
+
+       filesize = ftell(pStream);
+
+       if (filesize < 0) {
+               fprintf(stderr, "Error: Cannot get the file size: %s.\n", pPath);
+               goto error;
+       }
+
+       if (filesize == 0) {
+               fprintf(stderr, "Error: Empty file: %s.\n", pPath);
+               goto error;
+       }
+       /* Set the file pointer at the beginning of the file */
+       if (fseek(pStream, 0L, SEEK_SET) != 0) {
+               fprintf(stderr, "Error: Cannot read file: %s.\n", pPath);
+               goto error;
+       }
+       /* Allocate a buffer for the content */
+       content = (uint8_t *)malloc(filesize);
+       if (content == NULL) {
+               fprintf(stderr, "Error: Cannot read file: Out of memory.\n");
+               goto error;
+       }
+
+       /* Read data from the file into the buffer */
+       if (fread(content, (size_t)filesize, 1, pStream) != 1) {
+               fprintf(stderr, "Error: Cannot read file: %s.\n", pPath);
+               goto error;
+       }
+
+       /*Close the file */
+       fclose(pStream);
+       *ppContent = content;
+       /* Return number of bytes read */
+       return (size_t)filesize;
+
+error:
+       if (content != NULL) {
+               free(content);
+       }
+       fclose(pStream);
+       return 0;
+}
+
+/**
+* TEE_Open
+*
+* Open session to the TEE Gatekeeper trusted application
+*
+* @param  pSessionHandle  [out] Return pointer to the session handle
+*/
+static tciMessage_ptr TEE_Open(mcSessionHandle_t *SessionHandle)
+{
+       mcResult_t mcRet;
+       uint32_t nTrustedAppLength;
+       uint8_t* pTrustedAppData;
+       tciMessage_t *tci = NULL;
+
+       LOG_I("Opening <t-base device");
+       mcRet = mcOpenDevice(gDeviceId);
+       if (mcRet != MC_DRV_OK) {
+               LOG_E("Error opening device: %d", mcRet);
+               return false;
+       }
+
+       LOG_I("Allocating buffer for TCI");
+       tci = (tciMessage_t *)malloc(sizeof(tciMessage_t));
+
+       if (tci == NULL) {
+               LOG_I("Allocation of TCI failed");
+               //LOG_ERRNO("Allocation of TCI failed");
+               return false;
+       }
+       memset(tci, 0x00, sizeof(tciMessage_t));
+       nTrustedAppLength = getFileContent(secureSecDispTrustedApp,
+                                               &pTrustedAppData);
+
+       if (nTrustedAppLength == 0) {
+               LOG_E("Trusted Application not found");
+               free(tci);
+               tci = NULL;
+               return false;
+       }
+
+       LOG_I("Opening the Trusted Application session");
+       memset(SessionHandle, 0, sizeof(*SessionHandle)); // Clear the session handle
+       SessionHandle->deviceId = gDeviceId; // The device ID (default device is used)
+       mcRet = mcOpenTrustlet(SessionHandle,
+                               MC_SPID_RESERVED_TEST, /* mcSpid_t */
+                               pTrustedAppData,
+                               nTrustedAppLength,
+                               (uint8_t*)tci,
+                               (uint32_t)sizeof(tciMessage_t));
+       free(pTrustedAppData);
+       if (MC_DRV_OK != mcRet){
+               LOG_E("Open session failed: %d", mcRet);
+               free(tci);
+               tci= NULL;
+               return false;
+       }
+
+       LOG_I("mcOpenTrustlet() succeeded");
+       return (tciMessage_ptr)tci;
+}
+
+
+/**
+ * TEE_Close
+ *
+ * Close session to the TEE Gatekeeper trusted application
+ *
+ * @param  sessionHandle  [in] Session handle
+ */
+static void TEE_Close(mcSessionHandle_t *pSessionHandle)
+{
+       mcResult_t    mcRet;
+
+       do {
+               /* Validate session handle */
+               if (pSessionHandle == NULL) {
+                       LOG_E("TEE_Close(): Invalid session handle\n");
+                       break;
+               }
+
+               /* Close session */
+               mcRet = mcCloseSession(pSessionHandle);
+               if (MC_DRV_OK != mcRet) {
+                       LOG_E("TEE_Close(): mcCloseSession returned: %d\n", mcRet);
+                       break;
+               }
+
+               /* Close MobiCore device */
+               mcRet = mcCloseDevice(gDeviceId);
+               if (MC_DRV_OK != mcRet)
+                       LOG_E("TEE_Close(): mcCloseDevice returned: %d\n", mcRet);
+
+       } while (false);
+}
+#if 0
+teeResult_t TEE_SessionTest()
+{
+       teeResult_t        ret  = TEE_ERR_NONE;
+       tciMessage_ptr     pTci = NULL;
+       mcSessionHandle_t  sessionHandle;
+       mcResult_t         mcRet;
+
+       do {
+               /* Open session to the trusted application */
+               pTci = TEE_Open(&sessionHandle);
+               if (pTci == NULL) {
+                       ret = TEE_ERR_MEMORY;
+                       break;
+               }
+       } while (false);
+
+       /* Close session to the trusted application */
+       TEE_Close(&sessionHandle);
+
+       return ret;
+}
+#endif
+
+teeResult_t TEE_Enroll(uint32_t uid,
+               const uint8_t *current_password_handle,
+               uint32_t current_password_handle_length,
+               const uint8_t *current_password,
+               uint32_t current_password_length,
+               const uint8_t *desired_password,
+               uint32_t desired_password_length,
+               uint8_t *enrolled_password_handle,
+               uint32_t *enrolled_password_handle_length,
+               int32_t *retry_timeout,
+               const struct gatekeeper_device * /* not used */)
+{
+       teeResult_t     ret  = TEE_ERR_NONE;
+       mcResult_t      mcRet;
+       mcBulkMap_t     mapinfo_va_mapping = {0, 0};
+       uint8_t va_mapping[1024 * 5] = {0,};
+       int     fd = 0;
+       char    buf[100];
+
+       if (enrolled_password_handle_length == NULL || *enrolled_password_handle_length == 0) {
+               LOG_E("enrolled_password_handle_length is NULL, or the size is zero.");
+               return TEE_ERR_INVALID_INPUT;
+       }
+
+       if (retry_timeout == NULL) {
+               LOG_E("retry_timeout is NULL.");
+               return TEE_ERR_INVALID_INPUT;
+       }
+
+       if ((current_password_handle_length > (0x400)) || (current_password_length > (0x400)) || (desired_password_length > (0x400)))
+               return TEE_ERR_INVALID_INPUT;
+
+       do {
+               if (session_status == TEE_SESSION_CLOSED) {
+                       /* Open session to the trusted application */
+                       pTci = TEE_Open(&sessionHandle);
+                       if (pTci == NULL) {
+                               ret = TEE_ERR_MEMORY;
+                               break;
+                       }
+                       session_status = TEE_SESSION_OPENED;
+               }
+
+               LOG_I("%s:%d mcMap - current_password_handle\n", __func__, __LINE__);
+               mcRet = mcMap(&sessionHandle,
+                               (void*)va_mapping,
+                               sizeof(va_mapping),
+                               &mapinfo_va_mapping);
+               if (MC_DRV_OK != mcRet) {
+                       ret = TEE_ERR_MAP;
+                       break;
+               }
+
+               memcpy(va_mapping, current_password_handle, current_password_handle_length);
+               memcpy(va_mapping + vagap_current_password, current_password, current_password_length);
+               memcpy(va_mapping + vagap_desired_password, desired_password, desired_password_length);
+
+               /* Update TCI buffer */
+               pTci->command.header.commandId = CMD_ID_TEE_ENROLL;
+               pTci->gk_enroll.uid = uid;
+               pTci->gk_enroll.current_password_handle_va = (uint32_t)mapinfo_va_mapping.sVirtualAddr;
+               pTci->gk_enroll.current_password_handle_length = current_password_handle_length;
+               pTci->gk_enroll.current_password_va = (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_current_password;
+               pTci->gk_enroll.current_password_length = current_password_length;
+               pTci->gk_enroll.desired_password_va = (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_desired_password;
+               pTci->gk_enroll.desired_password_length = desired_password_length;
+               pTci->gk_enroll.enrolled_password_handle_va = (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_enrolled_password_handle;
+               pTci->gk_enroll.secure_object_va = (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_secure_object;
+
+               /* Notify the trusted application */
+               mcRet = mcNotify(&sessionHandle);
+               if (MC_DRV_OK != mcRet) {
+                       ret = TEE_ERR_NOTIFICATION;
+                       break;
+               }
+
+               /* Get Time for sending TA */
+               pTci->gk_enroll.nw_timestamp = clock_gettime_millisec();
+
+               /* Wait for response from the trusted application */
+               if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT)) {
+                       ret = TEE_ERR_NOTIFICATION;
+                       break;
+               }
+
+               if (RET_OK != pTci->response.header.returnCode) {
+                       LOG_E("TEE_GetKeyInfo(): TEE Gatekeeper trusted application returned: 0x%08x\n",
+                                       pTci->response.header.returnCode);
+                       *retry_timeout = pTci->gk_enroll.retry_timeout;
+                       ret = TEE_ERR_FAIL;
+                       break;
+               } else {
+                       /* Copy password handle from WSM */
+                       memcpy(enrolled_password_handle,
+                               va_mapping + vagap_enrolled_password_handle,
+                               pTci->gk_enroll.enrolled_password_handle_length);
+                       *enrolled_password_handle_length =
+                               pTci->gk_enroll.enrolled_password_handle_length;
+
+                       snprintf(buf, sizeof(buf), FNAME"%x", uid);
+                       if ((fd = open(buf, O_WRONLY | O_CREAT, 0600)) == -1) {
+                               LOG_E("Error: Cannot open file : %s\n", buf);
+                               ret =  TEE_ERR_FAIL;
+                               break;
+                       } else {
+                               write(fd, va_mapping + vagap_secure_object, SECURE_OBJECT_SIZE);
+                               fsync(fd);
+                               close(fd);
+                       }
+
+                       snprintf(buf, sizeof(buf), FNAME_SUB"%x", uid);
+                       if ((fd = open(buf, O_WRONLY | O_CREAT, 0600)) == -1) {
+                               LOG_E("Error: Cannot open file : %s\n", buf);
+                               ret =  TEE_ERR_FAIL;
+                               break;
+                       } else {
+                               write(fd, va_mapping + vagap_secure_object, SECURE_OBJECT_SIZE);
+                               fsync(fd);
+                               close(fd);
+                       }
+               }
+       } while (false);
+
+       /* Removing to mapped buffer */
+       memset(va_mapping, 0x00, sizeof(va_mapping));
+
+       if (mapinfo_va_mapping.sVirtualAddr != 0) {
+               mcRet = mcUnmap(&sessionHandle,
+                               (void*)va_mapping,
+                               &mapinfo_va_mapping);
+               if (MC_DRV_OK != mcRet) {
+                       ret = TEE_ERR_MAP;
+               }
+       }
+
+       return ret;
+}
+
+teeResult_t TEE_Verify(uint32_t uid,
+               uint64_t challenge, const uint8_t *enrolled_password_handle,
+               uint32_t enrolled_password_handle_length,
+               const uint8_t *provided_password,
+               uint32_t provided_password_length,
+               uint8_t **auth_token, uint32_t *auth_token_length,
+               bool *request_reenroll, int32_t *retry_timeout,
+               const struct gatekeeper_device * /* not used */)
+{
+       teeResult_t     ret  = TEE_ERR_NONE;
+       mcResult_t      mcRet;
+       mcBulkMap_t     mapinfo_va_mapping = {0, 0};
+       uint8_t va_mapping[1024 * 4] = {0,};
+       int     fd = 0;
+       char    buf[100];
+       ssize_t rd_size;
+
+       if (auth_token_length == NULL) {
+               LOG_E("auth_token_length is NULL.");
+               return TEE_ERR_INVALID_INPUT;
+       }
+       if (request_reenroll == NULL) {
+               LOG_E("request_reenroll is NULL.");
+               return TEE_ERR_INVALID_INPUT;
+       }
+
+       if((enrolled_password_handle_length > (0x400)) || (provided_password_length > (0x400)))
+               return TEE_ERR_INVALID_INPUT;
+
+       snprintf(buf, sizeof(buf), FNAME"%x", uid);
+       if ((fd = open(buf, O_RDONLY)) == -1) {
+               LOG_E("Error: Cannot open file : %s\n", buf);
+       } else {
+               rd_size = read(fd, va_mapping + vagap_secure_object, SECURE_OBJECT_SIZE);
+               if (rd_size == -1) {
+                       close(fd);
+                       return TEE_ERR_FAIL;
+               }
+               close(fd);
+       }
+
+       snprintf(buf, sizeof(buf), FNAME_SUB"%x", uid);
+       if ((fd = open(buf, O_RDONLY))== -1) {
+               LOG_E("Error: Cannot open file : %s\n", buf);
+       } else {
+               rd_size = read(fd, va_mapping + vagap_secure_object + SECURE_OBJECT_SIZE, SECURE_OBJECT_SIZE);
+               if (rd_size == -1) {
+                       close(fd);
+                       return TEE_ERR_FAIL;
+               }
+               close(fd);
+       }
+
+       do {
+               if (session_status == TEE_SESSION_CLOSED ) {
+                       /* Open session to the trusted application */
+                       pTci = TEE_Open(&sessionHandle);
+                       if (pTci == NULL) {
+                               ret = TEE_ERR_MEMORY;
+                               break;
+                       }
+                       session_status = TEE_SESSION_OPENED;
+               }
+
+               LOG_I("%s:%d mcMap - current_password_handle\n", __func__, __LINE__);
+               mcRet = mcMap(&sessionHandle,
+                               (void*)va_mapping,
+                               sizeof(va_mapping),
+                               &mapinfo_va_mapping);
+               if (MC_DRV_OK != mcRet) {
+                       ret = TEE_ERR_MAP;
+                       break;
+               }
+
+               memcpy(va_mapping, enrolled_password_handle,
+                       enrolled_password_handle_length);
+
+               memcpy(va_mapping + vagap_provided_password, provided_password,
+                       provided_password_length);
+
+               /* Update TCI buffer */
+               pTci->command.header.commandId = CMD_ID_TEE_VERIFY;
+               pTci->gk_verify.uid = uid;
+               pTci->gk_verify.challenge = challenge;
+               pTci->gk_verify.enrolled_password_handle_va =
+                       (uint32_t)mapinfo_va_mapping.sVirtualAddr;
+               pTci->gk_verify.enrolled_password_handle_length =
+                       enrolled_password_handle_length;
+               pTci->gk_verify.provided_password_va =
+                       (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_provided_password;
+               pTci->gk_verify.provided_password_length =
+                       provided_password_length;
+               pTci->gk_verify.auth_token_va =
+                       (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_auth_token;
+               pTci->gk_verify.auth_token_length = *auth_token_length;
+               pTci->gk_verify.request_reenroll = *request_reenroll;
+               pTci->gk_verify.secure_object_va =
+                       (uint32_t)mapinfo_va_mapping.sVirtualAddr + vagap_secure_object;
+
+               /* Get Time for sending TA */
+               pTci->gk_verify.nw_timestamp = clock_gettime_millisec();
+
+               /* Notify the trusted application */
+               mcRet = mcNotify(&sessionHandle);
+               if (MC_DRV_OK != mcRet) {
+                       ret = TEE_ERR_NOTIFICATION;
+                       break;
+               }
+
+               /* Wait for response from the trusted application */
+               if (MC_DRV_OK != mcWaitNotification(&sessionHandle,
+                                                       MC_INFINITE_TIMEOUT)) {
+                       ret = TEE_ERR_NOTIFICATION;
+                       break;
+               }
+
+               if (RET_OK != pTci->response.header.returnCode) {
+                       LOG_E("TEE_GetKeyInfo(): TEE Gatekeeper trusted application returned: 0x%08x\n",
+                                       pTci->response.header.returnCode);
+//                     LOG_E("TEE_GetKeyInfo(): previous failure count : 0x%x\n", failure_count);
+//                     LOG_E("TEE_GetKeyInfo(): returned failure count : 0x%x\n", pTci->gk_verify.failure_count);
+//                     LOG_E("TEE_GetKeyInfo(): Failure count : 0x%x\n", failure_count);
+                       *retry_timeout = pTci->gk_verify.retry_timeout;
+                       ret = TEE_ERR_FAIL;
+                       break;
+               }
+
+               /* Copy Auth_Token from WSM */
+               memcpy(*auth_token, va_mapping + vagap_auth_token,
+                       pTci->gk_verify.auth_token_length);
+
+               *auth_token_length = pTci->gk_verify.auth_token_length;
+               *request_reenroll = pTci->gk_verify.request_reenroll;
+       } while (false);
+
+       snprintf(buf, sizeof(buf), FNAME"%x", uid);
+       if ((fd = open(buf, O_WRONLY | O_CREAT, 0600)) == -1) {
+               LOG_E("Error: Cannot open file : %s\n", buf);
+               ret = TEE_ERR_FAIL;
+       } else {
+               write(fd, va_mapping + vagap_secure_object, SECURE_OBJECT_SIZE);
+               fsync(fd);
+               close(fd);
+       }
+
+       snprintf(buf, sizeof(buf), FNAME_SUB"%x", uid);
+       if ((fd = open(buf, O_WRONLY | O_CREAT, 0600)) == -1) {
+               LOG_E("Error: Cannot open file : %s\n", buf);
+               ret =  TEE_ERR_FAIL;
+       } else {
+               write(fd, va_mapping + vagap_secure_object, SECURE_OBJECT_SIZE);
+               fsync(fd);
+               close(fd);
+       }
+
+       /* Removing to mapped buffer */
+       memset(va_mapping, 0x00, sizeof(va_mapping));
+
+       if (mapinfo_va_mapping.sVirtualAddr != 0) {
+               mcRet = mcUnmap(&sessionHandle,
+                               (void*)va_mapping,
+                               &mapinfo_va_mapping);
+               if (MC_DRV_OK != mcRet) {
+                       ret = TEE_ERR_MAP;
+               }
+       }
+       return ret;
+}
diff --git a/libhdmimodule/Android.mk b/libhdmimodule/Android.mk
new file mode 100644 (file)
index 0000000..613a99c
--- /dev/null
@@ -0,0 +1,22 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifeq ($(BOARD_HDMI_INCAPABLE), true)
+LOCAL_C_INCLUDES += $(TOP)/hardware/samsung_slsi/exynos/libhdmi_dummy
+else
+LOCAL_C_INCLUDES += $(TOP)/hardware/samsung_slsi/exynos/libvpphdmi
+endif
+
+LOCAL_SRC_FILES += \
+       ./../../$(TARGET_SOC)/libhdmimodule/ExynosExternalDisplayModule.cpp
diff --git a/libhdmimodule/ExynosExternalDisplayModule.cpp b/libhdmimodule/ExynosExternalDisplayModule.cpp
new file mode 100644 (file)
index 0000000..0e0b33b
--- /dev/null
@@ -0,0 +1,10 @@
+#include "ExynosExternalDisplayModule.h"
+
+ExynosExternalDisplayModule::ExynosExternalDisplayModule(struct exynos5_hwc_composer_device_1_t *pdev)
+    : ExynosExternalDisplay(pdev)
+{
+}
+
+ExynosExternalDisplayModule::~ExynosExternalDisplayModule()
+{
+}
diff --git a/libhdmimodule/ExynosExternalDisplayModule.h b/libhdmimodule/ExynosExternalDisplayModule.h
new file mode 100644 (file)
index 0000000..5639fb8
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef EXYNOS_EXTERNAL_DISPLAY_MODULE_H
+#define EXYNOS_EXTERNAL_DISPLAY_MODULE_H
+
+#include "ExynosExternalDisplay.h"
+
+class ExynosExternalDisplayModule : public ExynosExternalDisplay {
+    public:
+        ExynosExternalDisplayModule(struct exynos5_hwc_composer_device_1_t *pdev);
+        ~ExynosExternalDisplayModule();
+};
+
+#endif
diff --git a/libhdmimodule/NOTICE b/libhdmimodule/NOTICE
new file mode 100644 (file)
index 0000000..c1c71a2
--- /dev/null
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2014, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/libhwcmodule/ExynosHWCModule.h b/libhwcmodule/ExynosHWCModule.h
new file mode 100644 (file)
index 0000000..2b9469d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EXYNOS_HWC_MODULE_H_
+#define ANDROID_EXYNOS_HWC_MODULE_H_
+#include <hardware/hwcomposer.h>
+
+#define VSYNC_DEV_PREFIX "/sys/devices/"
+#define VSYNC_DEV_MIDDLE "14850000.sysmmu/14850000.sysmmu/"
+#define VSYNC_DEV_NAME  "14830000.decon_fb/vsync"
+
+#define FIMD_WORD_SIZE_BYTES   16
+#define FIMD_BURSTLEN   16
+#define FIMD_BW_OVERLAP_CHECK
+
+#define TRY_SECOND_VSYNC_DEV
+#ifdef TRY_SECOND_VSYNC_DEV
+#define VSYNC_DEV_NAME2  "exynos5-fb.1/vsync"
+#define VSYNC_DEV_MIDDLE2  "platform/exynos-sysmmu.30/exynos-sysmmu.11/"
+#endif
+
+#define HDMI_RESERVE_MEM_DEV_NAME "/sys/class/ion_cma/ion_video_ext/isolated"
+#define SMEM_PATH "/dev/s5p-smem"
+#define SECMEM_IOC_SET_VIDEO_EXT_PROC   _IOWR('S', 13, int)
+
+#define HWC_VERSION HWC_DEVICE_API_VERSION_1_5
+
+#define DUAL_VIDEO_OVERLAY_SUPPORT
+
+/* Max number windows available in Exynos7570 is 3. */
+#define NUM_AVAILABLE_HW_WINDOWS       3
+
+#ifdef FIMD_BW_OVERLAP_CHECK
+const size_t MAX_NUM_FIMD_DMA_CH = 3;
+const uint32_t FIMD_DMA_CH_IDX[] = {0, 1, 2};
+const uint32_t FIMD_DMA_CH_BW_SET1[MAX_NUM_FIMD_DMA_CH] = {1920 * 1080, 1920 * 1080, 1920 * 1080};
+const uint32_t FIMD_DMA_CH_BW_SET2[MAX_NUM_FIMD_DMA_CH] = {1920 * 1200, 1920 * 1200, 1920 * 1200};
+const uint32_t FIMD_DMA_CH_OVERLAP_CNT_SET1[MAX_NUM_FIMD_DMA_CH] = {1, 1, 1};
+const uint32_t FIMD_DMA_CH_OVERLAP_CNT_SET2[MAX_NUM_FIMD_DMA_CH] = {1, 1, 1};
+
+/*
+ * TODO: All channels are enabled for WUXGA channels. Need to check
+ * if this is supported. If yes disable BW CHK else fine tune.
+ */
+
+inline void fimd_bw_overlap_limits_init(int xres, int yres,
+            uint32_t *fimd_dma_chan_max_bw, uint32_t *fimd_dma_chan_max_overlap_cnt)
+{
+    if (xres * yres > 1920 * 1080) {
+        for (size_t i = 0; i < MAX_NUM_FIMD_DMA_CH; i++) {
+            fimd_dma_chan_max_bw[i] = FIMD_DMA_CH_BW_SET2[i];
+            fimd_dma_chan_max_overlap_cnt[i] = FIMD_DMA_CH_OVERLAP_CNT_SET2[i];
+        }
+    } else {
+        for (size_t i = 0; i < MAX_NUM_FIMD_DMA_CH; i++) {
+            fimd_dma_chan_max_bw[i] = FIMD_DMA_CH_BW_SET1[i];
+            fimd_dma_chan_max_overlap_cnt[i] = FIMD_DMA_CH_OVERLAP_CNT_SET1[i];
+        }
+    }
+}
+#endif
+
+const size_t GSC_DST_W_ALIGNMENT_RGB888 = 1;
+const size_t GSC_DST_CROP_W_ALIGNMENT_RGB888 = 1;
+const size_t GSC_W_ALIGNMENT = 16;
+const size_t GSC_H_ALIGNMENT = 16;
+const size_t GSC_DST_H_ALIGNMENT_RGB888 = 1;
+
+const size_t FIMD_GSC_IDX = 0;
+const size_t FIMD_EXT_MPP_IDX = 0;
+/* HDMI_GSC_IDX is not used but added for build issue */
+const size_t HDMI_GSC_IDX = 2;
+const size_t HDMI_EXT_MPP_IDX = 2;
+const size_t WFD_GSC_IDX = 1;
+const size_t WFD_EXT_MPP_IDX = 1;
+
+const int FIMD_GSC_USAGE_IDX[] = {FIMD_GSC_IDX};
+const int AVAILABLE_GSC_UNITS[] = { 0, 1};
+
+#define MPP_VG          0
+#define MPP_VGR         2
+#define MPP_MSC         4
+#define MPP_MSC_1      5
+
+#define EXTERNAL_MPPS   2
+
+struct exynos_mpp_t {
+    int type;
+    unsigned int index;
+};
+
+const exynos_mpp_t AVAILABLE_EXTERNAL_MPP_UNITS[] = {{MPP_MSC, 0}, {MPP_MSC_1, 0} };
+
+#endif
diff --git a/libhwcutilsmodule/Android.mk b/libhwcutilsmodule/Android.mk
new file mode 100644 (file)
index 0000000..0279d9d
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_SRC_FILES += \
+       ./../../$(TARGET_SOC)/libhwcutilsmodule/ExynosMPPModule.cpp
diff --git a/libhwcutilsmodule/ExynosMPPModule.cpp b/libhwcutilsmodule/ExynosMPPModule.cpp
new file mode 100644 (file)
index 0000000..b483888
--- /dev/null
@@ -0,0 +1,57 @@
+#include "ExynosMPPModule.h"
+#include "ExynosHWCUtils.h"
+
+ExynosMPPModule::ExynosMPPModule()
+    : ExynosMPP()
+{
+}
+
+ExynosMPPModule::ExynosMPPModule(ExynosDisplay *display, int gscIndex)
+    : ExynosMPP(display, gscIndex)
+{
+}
+
+ExynosMPPModule::ExynosMPPModule(ExynosDisplay *display, unsigned int mppType, unsigned int mppIndex)
+    : ExynosMPP(display, mppType, mppIndex)
+{
+}
+
+int ExynosMPPModule::getBufferUsage(private_handle_t *srcHandle)
+{
+    int usage = GRALLOC_USAGE_SW_READ_NEVER |
+            GRALLOC_USAGE_SW_WRITE_NEVER |
+            GRALLOC_USAGE_NOZEROED |
+            GRALLOC_USAGE_HW_COMPOSER;
+
+    if (getDrmMode(srcHandle->flags) == SECURE_DRM) {
+        usage |= GRALLOC_USAGE_PROTECTED;
+        usage &= ~GRALLOC_USAGE_PRIVATE_NONSECURE;
+    } else if (getDrmMode(srcHandle->flags) == NORMAL_DRM) {
+        usage |= GRALLOC_USAGE_PROTECTED;
+        usage |= GRALLOC_USAGE_PRIVATE_NONSECURE;
+    }
+    if (srcHandle->flags & GRALLOC_USAGE_VIDEO_EXT)
+        usage |= GRALLOC_USAGE_VIDEO_EXT;
+
+    /* HACK: for distinguishing FIMD_VIDEO_region */
+    if (!((usage & GRALLOC_USAGE_PROTECTED) &&
+         !(usage & GRALLOC_USAGE_PRIVATE_NONSECURE) &&
+         !(usage & GRALLOC_USAGE_VIDEO_EXT))) {
+        usage |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER);
+    }
+
+    return usage;
+}
+
+bool ExynosMPPModule::isFormatSupportedByMPP(int format)
+{
+    switch (format) {
+        case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN:
+        case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+        case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED:
+            if (mType == MPP_MSC)
+                return true;
+            break;
+    }
+    return ExynosMPP::isFormatSupportedByMPP(format);
+}
diff --git a/libhwcutilsmodule/ExynosMPPModule.h b/libhwcutilsmodule/ExynosMPPModule.h
new file mode 100644 (file)
index 0000000..c7a18db
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef EXYNOS_GSC_MODULE_H
+#define EXYNOS_GSC_MODULE_H
+
+#include "ExynosMPPv2.h"
+
+class ExynosDisplay;
+
+class ExynosMPPModule : public ExynosMPP {
+    public:
+        ExynosMPPModule();
+        ExynosMPPModule(ExynosDisplay *display, int gscIndex);
+        ExynosMPPModule(ExynosDisplay *display, unsigned int mppType, unsigned int mppIndex);
+        virtual bool isFormatSupportedByMPP(int format);
+    protected:
+        virtual int getBufferUsage(private_handle_t *srcHandle);
+};
+
+#endif
diff --git a/libhwcutilsmodule/NOTICE b/libhwcutilsmodule/NOTICE
new file mode 100644 (file)
index 0000000..c1c71a2
--- /dev/null
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2014, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/libkeymaster/Android.mk b/libkeymaster/Android.mk
new file mode 100644 (file)
index 0000000..b8db57b
--- /dev/null
@@ -0,0 +1,53 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+
+MOBICORE_PATH := hardware/samsung_slsi/$(TARGET_SOC)/mobicore
+
+LOCAL_MODULE := keystore.exynos7570
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+ifeq ($(BOARD_USES_KEYMASTER_VER1), true)
+LOCAL_CPPFLAGS := -Wall
+LOCAL_CPPFLAGS += -Wextra
+LOCAL_CPPFLAGS += -Werror
+
+ALL_SRC_FILES := $(wildcard ${LOCAL_PATH}/ver1/src/*.cpp \
+                            ${LOCAL_PATH}/ver1/src/*.c)
+LOCAL_SRC_FILES := $(ALL_SRC_FILES:$(LOCAL_PATH)/ver1/%=ver1/%)
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/ver1/include
+else
+LOCAL_SRC_FILES := \
+       ver0/keymaster_mobicore.cpp \
+       ver0/tlcTeeKeymaster_if.c
+LOCAL_C_INCLUDES := \
+       $(LOCAL_PATH)/ver0 \
+       $(MOBICORE_PATH)/daemon/ClientLib/public \
+       $(MOBICORE_PATH)/common/MobiCore/inc/
+LOCAL_C_FLAGS = -fvisibility=hidden -Wall -Werror
+
+ifeq ($(BOARD_USES_KEYMASTER_VER0_3), true)
+       LOCAL_CFLAGS += -DKEYMASTER_VER0_3
+endif
+endif
+
+LOCAL_SHARED_LIBRARIES := libcrypto liblog libMcClient libcutils
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libkeymaster/ver0/NOTICE b/libkeymaster/ver0/NOTICE
new file mode 100644 (file)
index 0000000..316b4eb
--- /dev/null
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2014, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libkeymaster/ver0/buildTag.h b/libkeymaster/ver0/buildTag.h
new file mode 100644 (file)
index 0000000..91948ac
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define MOBICORE_COMPONENT_BUILD_TAG \
+       "t-base-EXYNOS64-Android-310A-V002-20150826_162546_62"
diff --git a/libkeymaster/ver0/keymaster_mobicore.cpp b/libkeymaster/ver0/keymaster_mobicore.cpp
new file mode 100644 (file)
index 0000000..ade9f11
--- /dev/null
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co., LTD
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster0.h>
+
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/rsa.h>
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+#include <UniquePtr.h>
+
+#define LOG_TAG "ExynosKeyMaster"
+#include <cutils/log.h>
+
+#include <tlcTeeKeymaster_if.h>
+
+#define KEY_BUFFER_SIZE                4096
+#define PUBKEY_BUFFER_SIZE     1204
+#define RSA_SIG_MAX_SIZE       (4096 >> 3)
+#define DSA_SIG_MAX_SIZE       ((256 >> 3) * 2)
+#define ECDSA_SIG_MAX_SIZE     (((521 >> 3) + 1) * 2)
+
+struct BIGNUM_Delete {
+    void operator()(BIGNUM* p) const {
+        BN_free(p);
+    }
+};
+typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
+
+struct EVP_PKEY_Delete {
+    void operator()(EVP_PKEY* p) const {
+        EVP_PKEY_free(p);
+    }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct PKCS8_PRIV_KEY_INFO_Delete {
+    void operator()(PKCS8_PRIV_KEY_INFO* p) const {
+        PKCS8_PRIV_KEY_INFO_free(p);
+    }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
+struct RSA_Delete {
+    void operator()(RSA* p) const {
+        RSA_free(p);
+    }
+};
+typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
+
+struct DSA_Delete {
+    void operator()(DSA* p) const {
+        DSA_free(p);
+    }
+};
+typedef UniquePtr<DSA, DSA_Delete> Unique_DSA;
+
+struct EC_KEY_Delete {
+    void operator()(EC_KEY* p) const {
+        EC_KEY_free(p);
+    }
+};
+typedef UniquePtr<EC_KEY, EC_KEY_Delete> Unique_EC_KEY;
+
+struct EC_POINT_Delete {
+    void operator()(EC_POINT* p) const {
+        EC_POINT_free(p);
+    }
+};
+typedef UniquePtr<EC_POINT, EC_POINT_Delete> Unique_EC_POPINT;
+
+struct EC_GROUP_Delete {
+    void operator()(EC_GROUP* p) const {
+        EC_GROUP_free(p);
+    }
+};
+typedef UniquePtr<EC_GROUP, EC_GROUP_Delete> Unique_EC_GROUP;
+
+struct Malloc_Free {
+    void operator()(void* p) const {
+       free(p);
+    }
+};
+
+typedef UniquePtr<keymaster0_device_t> Unique_keymaster0_device_t;
+
+/**
+ * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
+ * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
+ * without triggering a warning by not using the result of release().
+ */
+#define OWNERSHIP_TRANSFERRED(obj) \
+    typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
+
+/*
+ * Checks this thread's error queue and logs if necessary.
+ */
+static void logOpenSSLError(const char* location) {
+    int error = ERR_get_error();
+
+    if (error != 0) {
+        char message[256];
+        ERR_error_string_n(error, message, sizeof(message));
+        ALOGE("OpenSSL error in %s %d: %s", location, error, message);
+    }
+
+    ERR_clear_error();
+    ERR_remove_state(0);
+}
+
+static int km_generate_rsa_keypair(const keymaster_rsa_keygen_params_t *rsa_params,
+                               uint8_t *keyData, size_t *keyLength) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    ret = TEE_RSAGenerateKeyPair(TEE_KEYPAIR_RSACRT, keyData, KEY_BUFFER_SIZE,
+                               rsa_params->modulus_size,
+                               (uint32_t)rsa_params->public_exponent,
+                               (uint32_t *)keyLength);
+    if (ret != TEE_ERR_NONE)
+        ALOGE("TEE_RSAGenerateKeyPair() is failed: %d", ret);
+
+    return ret;
+}
+
+static int km_generate_dsa_keypair(const keymaster_dsa_keygen_params_t *dsa_params,
+                               uint8_t *keyData, size_t *keyLength) {
+    teeDsaParams_t tee_dsa_params;
+    teeResult_t ret = TEE_ERR_NONE;
+
+    if (dsa_params->generator_len == 0 ||
+            dsa_params->prime_p_len == 0 ||
+            dsa_params->prime_q_len == 0 ||
+            dsa_params->generator == NULL||
+            dsa_params->prime_p == NULL ||
+            dsa_params->prime_q == NULL) {
+       Unique_DSA dsa(DSA_new());
+
+       if (dsa.get() == NULL) {
+           logOpenSSLError("openssl_verify_data");
+           return -1;
+       }
+
+       if (DSA_generate_parameters_ex(dsa.get(), dsa_params->key_size, NULL, 0,
+                               NULL, NULL, NULL) != 1) {
+           logOpenSSLError("generate_dsa_keypair");
+           return -1;
+       }
+
+       UniquePtr<uint8_t, Malloc_Free> prime_p(static_cast<uint8_t*>(malloc(BN_num_bytes(dsa->p))));
+       if (prime_p.get() == NULL) {
+           ALOGE("Could not allocate memory for prime p");
+           return -1;
+       }
+
+       UniquePtr<uint8_t, Malloc_Free> prime_q(static_cast<uint8_t*>(malloc(BN_num_bytes(dsa->q))));
+       if (prime_q.get() == NULL) {
+           ALOGE("Could not allocate memory for prime q");
+           return -1;
+       }
+
+       UniquePtr<uint8_t, Malloc_Free> generator(static_cast<uint8_t*>(malloc(BN_num_bytes(dsa->g))));
+       if (generator.get() == NULL) {
+           ALOGE("Could not allocate memory for generator");
+           return -1;
+       }
+
+       tee_dsa_params.pLen = BN_bn2bin(dsa->p, prime_p.get());
+       tee_dsa_params.qLen = BN_bn2bin(dsa->q, prime_q.get());
+       tee_dsa_params.gLen = BN_bn2bin(dsa->g, generator.get());
+       tee_dsa_params.xLen = tee_dsa_params.qLen;
+       tee_dsa_params.yLen = tee_dsa_params.pLen;
+       tee_dsa_params.p = (uint8_t*)prime_p.get();
+       tee_dsa_params.q = (uint8_t*)prime_q.get();
+       tee_dsa_params.g = (uint8_t*)generator.get();
+
+       ret = TEE_DSAGenerateKeyPair(keyData, KEY_BUFFER_SIZE, &tee_dsa_params,
+                               (uint32_t *)keyLength);
+       if (ret != TEE_ERR_NONE) {
+            ALOGE("TEE_DSAGenerateKeyPair() is failed: %d", ret);
+           return -1;
+       }
+    } else {
+       /* binder gives us read-only mappings we can't use with mobicore */
+       void *tmpP = malloc(dsa_params->prime_p_len);
+       void *tmpQ = malloc(dsa_params->prime_q_len);
+       void *tmpG = malloc(dsa_params->generator_len);
+       uint32_t i;
+
+       tee_dsa_params.p = (uint8_t*)tmpP;
+       tee_dsa_params.q = (uint8_t*)tmpQ;
+       tee_dsa_params.g = (uint8_t*)tmpG;
+
+       /* decide p length */
+       for (i = 0; i < dsa_params->prime_p_len; i++)
+               if (*(dsa_params->prime_p + i) != 0)
+                       break;
+       tee_dsa_params.pLen = dsa_params->prime_p_len - i;
+       memcpy(tmpP, dsa_params->prime_p + i, tee_dsa_params.pLen);
+
+       /* decide q length */
+       for (i = 0; i < dsa_params->prime_q_len; i++)
+               if (*(dsa_params->prime_q + i) != 0)
+                       break;
+       tee_dsa_params.qLen = dsa_params->prime_q_len - i;
+       memcpy(tmpQ, dsa_params->prime_q + i, tee_dsa_params.qLen);
+
+       /* decide g length */
+       for (i = 0; i < dsa_params->generator_len; i++)
+               if (*(dsa_params->generator + i) != 0)
+                       break;
+       tee_dsa_params.gLen = dsa_params->generator_len - i;
+       memcpy(tmpG, dsa_params->generator + i, tee_dsa_params.gLen);
+
+       tee_dsa_params.xLen = tee_dsa_params.qLen;
+       tee_dsa_params.yLen = tee_dsa_params.pLen;
+
+       ret = TEE_DSAGenerateKeyPair(keyData, KEY_BUFFER_SIZE, &tee_dsa_params,
+                               (uint32_t *)keyLength);
+       free(tmpP);
+       free(tmpQ);
+       free(tmpG);
+       if (ret != TEE_ERR_NONE) {
+           ALOGE("TEE_DSAGenerateKeyPair() is failed: %d", ret);
+           return -1;
+       }
+    }
+
+    return ret;
+}
+
+static int km_generate_ec_keypair(const keymaster_ec_keygen_params_t *ec_params,
+                               uint8_t *keyData, size_t *keyLength) {
+    teeEccCurveType_t curve;
+    teeResult_t ret = TEE_ERR_NONE;
+
+    switch (ec_params->field_size) {
+    case 192:
+       curve = TEE_ECC_CURVE_NIST_P192;
+       break;
+    case 224:
+       curve = TEE_ECC_CURVE_NIST_P224;
+       break;
+    case 256:
+       curve = TEE_ECC_CURVE_NIST_P256;
+       break;
+    case 384:
+       curve = TEE_ECC_CURVE_NIST_P384;
+       break;
+    case 521:
+       curve = TEE_ECC_CURVE_NIST_P521;
+       break;
+    default:
+       ALOGE("curve(%d) is not valid\n", ec_params->field_size);
+       return -1;
+    }
+
+    ret = TEE_ECDSAGenerateKeyPair(keyData, KEY_BUFFER_SIZE, curve,
+                               (uint32_t *)keyLength);
+    if (ret != TEE_ERR_NONE)
+        ALOGE("TEE_ECDSAGenerateKeyPair() is failed: %d", ret);
+
+    return ret;
+}
+
+static int exynos_km_generate_keypair(const keymaster0_device_t*,
+                               const keymaster_keypair_t key_type,
+                               const void* key_params, uint8_t** keyBlob,
+                               size_t* keyBlobLength) {
+    /* keyBlobLength will be casted as uint32_t to call TAC API, so in 64bit
+     * architecture, upper 32bit can have unexpected value. To prevent it,
+     * it's modified to use temporary variable. */
+    size_t tmp_blob_length = 0;
+
+    if (key_params == NULL) {
+       ALOGE("key_params = NULL");
+       return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> keyDataPtr(reinterpret_cast<uint8_t*>(malloc(KEY_BUFFER_SIZE)));
+    if (keyDataPtr.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    } else if (keyBlobLength == NULL) {
+        ALOGE("keyBlobLength = NULL");
+       return -1;
+    }
+
+    if (key_type == TYPE_RSA) {
+       const keymaster_rsa_keygen_params_t * rsa_params =
+               (const keymaster_rsa_keygen_params_t*) key_params;
+       if(km_generate_rsa_keypair(rsa_params, keyDataPtr.get(), &tmp_blob_length))
+           return -1;
+    } else if (key_type == TYPE_DSA) {
+       const keymaster_dsa_keygen_params_t * dsa_params =
+               (const keymaster_dsa_keygen_params_t*) key_params;
+       if(km_generate_dsa_keypair(dsa_params, keyDataPtr.get(), &tmp_blob_length))
+           return -1;
+    } else if (key_type == TYPE_EC) {
+       const keymaster_ec_keygen_params_t * ec_params =
+               (const keymaster_ec_keygen_params_t*) key_params;
+       if(km_generate_ec_keypair(ec_params, keyDataPtr.get(), &tmp_blob_length))
+           return -1;
+    } else {
+        ALOGE("Invalid key type (%d)\n", key_type);
+        return -1;
+    }
+
+    *keyBlob = keyDataPtr.release();
+    *keyBlobLength = tmp_blob_length;
+
+    return 0;
+}
+
+static int km_import_rsa_keypair(EVP_PKEY *pkey, uint8_t *kbuf, uint32_t *key_len) {
+    teeKeyMeta_t meta;
+    teeRsaKeyMeta_t rsa_meta;
+    uint32_t len = *key_len;
+    BIGNUM *tmp = NULL;
+    BN_CTX *ctx = NULL;
+
+    /* change key format */
+    Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey));
+    if (rsa.get() == NULL) {
+        logOpenSSLError("get rsa key format");
+       return -1;
+    }
+
+    if (BN_cmp(rsa->p, rsa->q) < 0) {
+        /* p <-> q */
+        tmp = rsa->p;
+        rsa->p = rsa->q;
+        rsa->q = tmp;
+        /* dp <-> dq */
+        tmp = rsa->dmp1;
+        rsa->dmp1 = rsa->dmq1;
+        rsa->dmq1 = tmp;
+        /* calulate inverse of q mod p */
+        ctx = BN_CTX_new();
+        if (!BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) {
+            ALOGE("Calculating inverse of q mod p is failed\n");
+            BN_CTX_free(ctx);
+            return -1;
+        }
+        BN_CTX_free(ctx);
+    }
+
+    meta.keytype = TEE_KEYTYPE_RSA;
+    len += sizeof(meta);
+
+    rsa_meta.lenpubmod = BN_bn2bin(rsa->n, kbuf + len);
+
+    len += rsa_meta.lenpubmod;
+    if (rsa_meta.lenpubmod == (512 >> 3))
+        rsa_meta.keysize = TEE_RSA_KEY_SIZE_512;
+    else if (rsa_meta.lenpubmod == (1024 >> 3))
+        rsa_meta.keysize = TEE_RSA_KEY_SIZE_1024;
+    else if (rsa_meta.lenpubmod == (2048 >> 3))
+        rsa_meta.keysize = TEE_RSA_KEY_SIZE_2048;
+    else if (rsa_meta.lenpubmod == (3072 >> 3))
+        rsa_meta.keysize = TEE_RSA_KEY_SIZE_3072;
+    else if (rsa_meta.lenpubmod == (4096 >> 3))
+        rsa_meta.keysize = TEE_RSA_KEY_SIZE_4096;
+    else {
+        ALOGE("key size(%d) is not supported\n", rsa_meta.lenpubmod << 3);
+        return -1;
+    }
+
+    rsa_meta.lenpubexp = BN_bn2bin(rsa->e, kbuf + len);
+    len += rsa_meta.lenpubexp;
+
+    if ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) &&
+       (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) {
+       rsa_meta.type = TEE_KEYPAIR_RSACRT;
+       rsa_meta.rsacrtpriv.lenp = BN_bn2bin(rsa->p, kbuf + len);
+       len += rsa_meta.rsacrtpriv.lenp;
+       rsa_meta.rsacrtpriv.lenq = BN_bn2bin(rsa->q, kbuf + len);
+       len += rsa_meta.rsacrtpriv.lenq;
+       rsa_meta.rsacrtpriv.lendp = BN_bn2bin(rsa->dmp1, kbuf + len);
+       len += rsa_meta.rsacrtpriv.lendp;
+       rsa_meta.rsacrtpriv.lendq = BN_bn2bin(rsa->dmq1, kbuf + len);
+       len += rsa_meta.rsacrtpriv.lendq;
+       rsa_meta.rsacrtpriv.lenqinv = BN_bn2bin(rsa->iqmp, kbuf + len);
+       len += rsa_meta.rsacrtpriv.lenqinv;
+    } else {
+       rsa_meta.type = TEE_KEYPAIR_RSA;
+       rsa_meta.rsapriv.lenpriexp = BN_bn2bin(rsa->d, kbuf + len);
+       len += rsa_meta.rsapriv.lenpriexp;
+    }
+
+    memcpy(&meta.rsakey, &rsa_meta, sizeof(rsa_meta));
+    memcpy(kbuf, &meta, sizeof(meta));
+
+    *key_len = len;
+
+    return 0;
+}
+
+static int km_import_dsa_keypair(EVP_PKEY *pkey, uint8_t *kbuf, uint32_t *key_len) {
+    teeKeyMeta_t meta;
+    uint32_t len = *key_len;
+
+    /* change key format */
+    Unique_DSA dsa(EVP_PKEY_get1_DSA(pkey));
+    if (dsa.get() == NULL) {
+       logOpenSSLError("get dsa key format");
+       return -1;
+    }
+
+    meta.keytype = TEE_KEYTYPE_DSA;
+    len += sizeof(meta);
+
+    meta.dsakey.pLen = BN_bn2bin(dsa->p, kbuf + len);
+
+    len += meta.dsakey.pLen;
+    meta.dsakey.qLen = BN_bn2bin(dsa->q, kbuf + len);
+
+    len += meta.dsakey.qLen;
+    meta.dsakey.gLen = BN_bn2bin(dsa->g, kbuf + len);
+
+    len += meta.dsakey.gLen;
+    meta.dsakey.yLen = BN_bn2bin(dsa->pub_key, kbuf + len);
+
+    len += meta.dsakey.yLen;
+    meta.dsakey.xLen = BN_bn2bin(dsa->priv_key, kbuf + len);
+
+    len += meta.dsakey.xLen;
+
+    memcpy(kbuf, &meta, sizeof(meta));
+
+    *key_len = len;
+
+    return 0;
+}
+
+static int km_import_ec_keypair(EVP_PKEY *pkey, uint8_t *kbuf, uint32_t *key_len) {
+    teeKeyMeta_t meta;
+    uint32_t len = *key_len;
+    int ret;
+
+    /* change key format */
+    Unique_EC_KEY eckey(EVP_PKEY_get1_EC_KEY(pkey));
+    if (eckey.get() == NULL) {
+        logOpenSSLError("get ec key format");
+       return -1;
+    }
+
+    const EC_GROUP *group = EC_KEY_get0_group(eckey.get());
+    const EC_POINT *pub_key = EC_KEY_get0_public_key(eckey.get());
+    const BIGNUM *priv_key = EC_KEY_get0_private_key(eckey.get());
+    Unique_BIGNUM affine_x(BN_new());
+    Unique_BIGNUM affine_y(BN_new());
+
+    /* transform to affine coordinate */
+    ret = EC_POINT_get_affine_coordinates_GFp(group, pub_key, affine_x.get(),
+                                       affine_y.get(), NULL);
+    if (!ret) {
+       logOpenSSLError("get affine coordinates");
+       return -1;
+    }
+
+    meta.keytype = TEE_KEYTYPE_ECDSA;
+    len += sizeof(meta);
+
+    /* Add to compare with nist prime */
+
+    switch (EC_GROUP_get_curve_name(group)) {
+    case NID_X9_62_prime192v1:
+       meta.ecdsakey.curve = TEE_ECC_CURVE_NIST_P192;
+       meta.ecdsakey.curveLen = 192 >> 3;
+       break;
+    case NID_secp224r1:
+       meta.ecdsakey.curve = TEE_ECC_CURVE_NIST_P224;
+       meta.ecdsakey.curveLen = 224 >> 3;
+       break;
+    case NID_X9_62_prime256v1:
+       meta.ecdsakey.curve = TEE_ECC_CURVE_NIST_P256;
+       meta.ecdsakey.curveLen = 256 >> 3;
+       break;
+    case NID_secp384r1:
+       meta.ecdsakey.curve = TEE_ECC_CURVE_NIST_P384;
+       meta.ecdsakey.curveLen = 384 >> 3;
+       break;
+    case NID_secp521r1:
+       meta.ecdsakey.curve = TEE_ECC_CURVE_NIST_P521;
+       meta.ecdsakey.curveLen = (521 >> 3) + 1;
+       break;
+    default:
+       ALOGE("curve(%d) is not valid\n", EC_GROUP_get_curve_name(group));
+       return -1;
+    }
+
+    len += BN_bn2bin(affine_x.get(), kbuf + len);
+    len += BN_bn2bin(affine_y.get(), kbuf + len);
+    if (len != (sizeof(meta) + 2 * meta.ecdsakey.curveLen)) {
+       ALOGE("got invalid public key(len: 0x%x)\n", len);
+       return -1;
+    }
+
+    len += BN_bn2bin(priv_key, kbuf + len);
+    if (len != (sizeof(meta) + 3 * meta.ecdsakey.curveLen)) {
+       ALOGE("got invalid private key");
+       return -1;
+    }
+
+    memcpy(kbuf, &meta, sizeof(meta));
+
+    *key_len = len;
+
+    return 0;
+}
+
+static int exynos_km_import_keypair(const keymaster0_device_t*,
+                               const uint8_t* key, const size_t key_length,
+                               uint8_t** key_blob, size_t* key_blob_length) {
+    uint8_t kbuf[KEY_BUFFER_SIZE];
+    uint32_t key_len = 0;
+    teeResult_t ret = TEE_ERR_NONE;
+
+    if (key == NULL) {
+        ALOGE("input key == NULL");
+        return -1;
+    } else if (key_blob == NULL || key_blob_length == NULL) {
+        ALOGE("output key blob or length == NULL");
+        return -1;
+    }
+
+    /* decoding */
+    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL,
+                                               &key, key_length));
+    if (pkcs8.get() == NULL) {
+        logOpenSSLError("pkcs4.get");
+        return -1;
+    }
+
+    /* assign to EVP */
+    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+    if (pkey.get() == NULL) {
+        logOpenSSLError("pkey.get");
+        return -1;
+    }
+    OWNERSHIP_TRANSFERRED(pkcs8);
+
+    int type = EVP_PKEY_type(pkey->type);
+    if (type == EVP_PKEY_RSA) {
+       if (km_import_rsa_keypair(pkey.get(), kbuf, &key_len))
+           return -1;
+    } else if (type == EVP_PKEY_DSA) {
+       if (km_import_dsa_keypair(pkey.get(), kbuf, &key_len))
+           return -1;
+    } else if (type == EVP_PKEY_EC) {
+       if (km_import_ec_keypair(pkey.get(), kbuf, &key_len))
+           return -1;
+    } else {
+       ALOGE("Unsupported key type");
+       return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> outPtr(reinterpret_cast<uint8_t*>(malloc(KEY_BUFFER_SIZE)));
+    if (outPtr.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    *key_blob_length = KEY_BUFFER_SIZE;
+
+    ret = TEE_KeyImport(kbuf, key_len, outPtr.get(), (uint32_t *)key_blob_length);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_KeyImport() is failed: %d", ret);
+        return -1;
+    }
+
+    *key_blob = outPtr.release();
+
+    return ret;
+}
+
+static int km_get_rsa_keypair_public(uint8_t *pubkey, EVP_PKEY *pkey) {
+    teePubKeyMeta_t *meta;
+    uint8_t *modulus;
+    uint8_t *pubexp;
+    size_t mod_len;
+    size_t exp_len;
+
+    meta = (teePubKeyMeta_t*)pubkey;
+    modulus = pubkey + sizeof(teePubKeyMeta_t);
+    mod_len = meta->rsakey.lenpubmod;
+    pubexp = pubkey + sizeof(teePubKeyMeta_t) + mod_len;
+    exp_len = meta->rsakey.lenpubexp;
+
+    Unique_BIGNUM bn_mod(BN_new());
+    if (bn_mod.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    Unique_BIGNUM bn_exp(BN_new());
+    if (bn_exp.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    BN_bin2bn(modulus, mod_len, bn_mod.get());
+    BN_bin2bn(pubexp, exp_len, bn_exp.get());
+
+    /* assign to RSA */
+    Unique_RSA rsa(RSA_new());
+    if (rsa.get() == NULL) {
+        logOpenSSLError("rsa.get");
+        return -1;
+    }
+
+    RSA* rsa_tmp = rsa.get();
+
+    rsa_tmp->n = bn_mod.release();
+    rsa_tmp->e = bn_exp.release();
+
+    /* assign to EVP */
+    if (EVP_PKEY_assign_RSA(pkey, rsa.get()) == 0) {
+        logOpenSSLError("assing RSA to EVP_PKEY");
+        return -1;
+    }
+    OWNERSHIP_TRANSFERRED(rsa);
+
+    return 0;
+}
+
+static int km_get_dsa_keypair_public(uint8_t *pubkey, EVP_PKEY *pkey) {
+    teePubKeyMeta_t *meta;
+    uint8_t *p, *q, *g, *y;
+    size_t p_len, q_len, g_len, y_len;
+
+    meta = (teePubKeyMeta_t*)pubkey;
+    p = pubkey + sizeof(teePubKeyMeta_t);
+    p_len = meta->dsakey.pLen;
+    q = pubkey + sizeof(teePubKeyMeta_t) + p_len;
+    q_len = meta->dsakey.qLen;
+    g = pubkey + sizeof(teePubKeyMeta_t) + p_len + q_len;
+    g_len = meta->dsakey.gLen;
+    y = pubkey + sizeof(teePubKeyMeta_t) + p_len + q_len + g_len;
+    y_len = meta->dsakey.yLen;
+
+    Unique_BIGNUM bn_p(BN_new());
+    if (bn_p.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    Unique_BIGNUM bn_q(BN_new());
+    if (bn_q.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    Unique_BIGNUM bn_g(BN_new());
+    if (bn_g.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    Unique_BIGNUM bn_y(BN_new());
+    if (bn_y.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    BN_bin2bn(p, p_len, bn_p.get());
+    BN_bin2bn(q, q_len, bn_q.get());
+    BN_bin2bn(g, g_len, bn_g.get());
+    BN_bin2bn(y, y_len, bn_y.get());
+
+    Unique_DSA dsa(DSA_new());
+    if (dsa.get() == NULL) {
+        logOpenSSLError("dsa.get");
+        return -1;
+    }
+
+    DSA* dsa_tmp = dsa.get();
+
+    dsa_tmp->p = bn_p.release();
+    dsa_tmp->q = bn_q.release();
+    dsa_tmp->g = bn_g.release();
+    dsa_tmp->pub_key = bn_y.release();
+
+    /* assign to EVP */
+    if (EVP_PKEY_assign_DSA(pkey, dsa.get()) == 0) {
+        logOpenSSLError("assing DSA to EVP_PKEY");
+        return -1;
+    }
+    OWNERSHIP_TRANSFERRED(dsa);
+
+    return 0;
+}
+
+static int km_get_ecdsa_keypair_public(uint8_t *pubkey, EVP_PKEY *pkey) {
+    teePubKeyMeta_t *meta;
+    uint8_t *x, *y;
+    size_t x_len, y_len, curve_len;
+    int curve;
+    int ret;
+
+    meta = (teePubKeyMeta_t*)pubkey;
+    switch (meta->ecdsakey.curve) {
+    case TEE_ECC_CURVE_NIST_P192:
+       curve = NID_X9_62_prime192v1;
+       curve_len = 192 >> 3;
+       break;
+    case TEE_ECC_CURVE_NIST_P224:
+       curve = NID_secp224r1;
+       curve_len = 224 >> 3;
+       break;
+    case TEE_ECC_CURVE_NIST_P256:
+       curve = NID_X9_62_prime256v1;
+       curve_len = 256 >> 3;
+       break;
+    case TEE_ECC_CURVE_NIST_P384:
+       curve = NID_secp384r1;
+       curve_len = 384 >> 3;
+       break;
+    case TEE_ECC_CURVE_NIST_P521:
+       curve = NID_secp521r1;
+       curve_len = (521 >> 3) + 1;
+       break;
+    default:
+       ALOGE("curve(%d) is not valid\n", meta->ecdsakey.curve);
+       return -1;
+    }
+
+    EC_GROUP *group;
+
+    /* Get group with curve */
+    group = EC_GROUP_new_by_curve_name(curve);
+    if (!group) {
+        ALOGE("fail to get group");
+       return -1;
+    }
+
+    x = pubkey + sizeof(teePubKeyMeta_t);
+    y = pubkey + sizeof(teePubKeyMeta_t) + curve_len;
+
+    Unique_BIGNUM bn_x(BN_new());
+    if (bn_x.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    Unique_BIGNUM bn_y(BN_new());
+    if (bn_y.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    BN_bin2bn(x, curve_len, bn_x.get());
+    BN_bin2bn(y, curve_len, bn_y.get());
+
+    Unique_EC_KEY eckey(EC_KEY_new());
+    if (eckey.get() == NULL) {
+       logOpenSSLError("eckey.get");
+        return -1;
+    }
+
+    ret = EC_KEY_set_group(eckey.get(), group);
+    if (!ret) {
+       logOpenSSLError("set group");
+       return -1;
+    }
+
+    ret = EC_KEY_set_public_key_affine_coordinates(eckey.get(), bn_x.release(), bn_y.release());
+    if (!ret) {
+       logOpenSSLError("set affine coordinates");
+       return -1;
+    }
+
+    /* assign to EVP */
+    if (EVP_PKEY_assign_EC_KEY(pkey, eckey.get()) == 0) {
+        logOpenSSLError("assing EC_KEY to EVP_PKEY");
+        return -1;
+    }
+    OWNERSHIP_TRANSFERRED(eckey);
+
+    return 0;
+}
+
+static int exynos_km_get_keypair_public(const struct keymaster0_device*,
+                               const uint8_t* key_blob, const size_t key_blob_length,
+                               uint8_t** x509_data, size_t* x509_data_length) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    Unique_EVP_PKEY pkey(EVP_PKEY_new());
+    if (pkey.get() == NULL) {
+        logOpenSSLError("allocate EVP_PKEY");
+        return -1;
+    }
+
+    if (x509_data == NULL || x509_data_length == NULL) {
+        ALOGE("output public key buffer == NULL");
+        return -1;
+    }
+
+    size_t pubkey_len = sizeof(teePubKeyMeta_t) + PUBKEY_BUFFER_SIZE;
+
+    UniquePtr<uint8_t, Malloc_Free> pubkey(reinterpret_cast<uint8_t*>(malloc(pubkey_len)));
+    if (pubkey.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    ret = TEE_GetPubKey(key_blob, (uint32_t)key_blob_length, pubkey.get(), (uint32_t *)&pubkey_len);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_GetPubKey() is failed: %d", ret);
+        return -1;
+    }
+
+    teePubKeyMeta_t *meta = (teePubKeyMeta_t*)pubkey.get();
+    switch (meta->keytype) {
+    case TEE_KEYTYPE_RSA:
+       if (km_get_rsa_keypair_public(pubkey.get(), pkey.get()))
+           return -1;
+       break;
+    case TEE_KEYTYPE_DSA:
+       if (km_get_dsa_keypair_public(pubkey.get(), pkey.get()))
+           return -1;
+       break;
+    case TEE_KEYTYPE_ECDSA:
+       if (km_get_ecdsa_keypair_public(pubkey.get(), pkey.get()))
+           return -1;
+       break;
+    default:
+       ALOGE("Unsupported key type");
+       return -1;
+    }
+
+    /* change to x.509 format */
+    int len = i2d_PUBKEY(pkey.get(), NULL);
+    if (len <= 0) {
+        logOpenSSLError("i2d_PUBKEY");
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> key(static_cast<uint8_t*>(malloc(len)));
+    if (key.get() == NULL) {
+        ALOGE("Could not allocate memory for public key data");
+        return -1;
+    }
+
+    unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
+    if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
+        logOpenSSLError("Compare results");
+        return -1;
+    }
+
+    *x509_data_length = len;
+    *x509_data = key.release();
+
+    return ret;
+}
+
+static int km_rsa_sign_data(const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* data,
+                       const size_t dataLength, uint8_t** signedData,
+                       size_t* signedDataLength) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    } else if (sign_params->padding_type != PADDING_NONE) {
+        ALOGE("Cannot handle padding type %d", sign_params->padding_type);
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(RSA_SIG_MAX_SIZE)));
+    if (signedDataPtr.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    *signedDataLength = RSA_SIG_MAX_SIZE;
+
+    /* binder gives us read-only mappings we can't use with mobicore */
+    void *tmpData = malloc(dataLength);
+    memcpy(tmpData, data, dataLength);
+    ret = TEE_RSASign(keyBlob, (uint32_t)keyBlobLength, (const uint8_t *)tmpData,
+               dataLength, signedDataPtr.get(), (uint32_t *)signedDataLength,
+               TEE_RSA_NODIGEST_NOPADDING);
+    free(tmpData);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_RSASign() is failed: %d", ret);
+        return -1;
+    }
+
+    *signedData = signedDataPtr.release();
+
+    return ret;
+}
+
+static int km_dsa_sign_data(const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* data,
+                       const size_t dataLength, uint8_t** signedData,
+                       size_t* signedDataLength) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    keymaster_dsa_sign_params_t* sign_params = (keymaster_dsa_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free>
+    signedDataPtr(reinterpret_cast<uint8_t*>(malloc(DSA_SIG_MAX_SIZE)));
+    if (signedDataPtr.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+    uint8_t *tmp_sig = signedDataPtr.get();
+
+    *signedDataLength = DSA_SIG_MAX_SIZE;
+
+    /* binder gives us read-only mappings we can't use with mobicore */
+    void *tmpData = malloc(dataLength);
+    memcpy(tmpData, data, dataLength);
+    ret = TEE_DSASign(keyBlob, keyBlobLength, (const uint8_t *)tmpData,
+               dataLength, signedDataPtr.get(), (uint32_t *)signedDataLength);
+    free(tmpData);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_DSASign() is failed: %d", ret);
+        return -1;
+    }
+
+    /* DER encode signature */
+    unsigned int slen = *signedDataLength/2;
+
+    Unique_BIGNUM bn_sig_r(BN_new());
+    if (bn_sig_r.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    Unique_BIGNUM bn_sig_s(BN_new());
+    if (bn_sig_s.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    DSA_SIG *s = DSA_SIG_new();
+    if (!s) {
+       ALOGE("memory allocation is failed");
+       return -1;
+    }
+
+    s->r = bn_sig_r.get();
+    s->s = bn_sig_s.get();
+
+    BN_bin2bn(tmp_sig, slen, s->r);
+    BN_bin2bn(tmp_sig + slen, slen, s->s);
+
+    UniquePtr<uint8_t, Malloc_Free> encodedSig(reinterpret_cast<uint8_t*>(malloc(DSA_SIG_MAX_SIZE)));
+    if (encodedSig.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        DSA_SIG_free(s);
+        return -1;
+    }
+    uint8_t *tmp = encodedSig.get();
+
+    *signedDataLength = i2d_DSA_SIG(s, &tmp);
+
+    *signedData = encodedSig.release();
+
+    DSA_SIG_free(s);
+
+    return ret;
+}
+
+static int km_ecdsa_sign_data(const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* data,
+                       const size_t dataLength, uint8_t** signedData,
+                       size_t* signedDataLength) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    keymaster_ec_sign_params_t* sign_params = (keymaster_ec_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free>
+    signedDataPtr(reinterpret_cast<uint8_t*>(malloc(ECDSA_SIG_MAX_SIZE)));
+    if (signedDataPtr.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+    uint8_t *tmp_sig = signedDataPtr.get();
+
+    *signedDataLength = ECDSA_SIG_MAX_SIZE;
+
+    /* binder gives us read-only mappings we can't use with mobicore */
+    void *tmpData = malloc(dataLength);
+    memcpy(tmpData, data, dataLength);
+    ret = TEE_ECDSASign(keyBlob, (uint32_t)keyBlobLength, (const uint8_t *)tmpData,
+                       dataLength, signedDataPtr.get(), (uint32_t *)signedDataLength);
+    free(tmpData);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_ECDSASign() is failed: %d", ret);
+        return -1;
+    }
+
+    /* DER encode signature */
+    unsigned int curve = *signedDataLength/2;
+    ECDSA_SIG *s = ECDSA_SIG_new();
+    if (!s) {
+       ALOGE("memory allocation is failed");
+       return -1;
+    }
+
+    BN_bin2bn(tmp_sig, curve, s->r);
+    BN_bin2bn(tmp_sig + curve, curve, s->s);
+
+    UniquePtr<uint8_t, Malloc_Free> encodedSig(reinterpret_cast<uint8_t*>(malloc(ECDSA_SIG_MAX_SIZE)));
+    if (encodedSig.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        ECDSA_SIG_free(s);
+        return -1;
+    }
+    uint8_t *tmp = encodedSig.get();
+
+    *signedDataLength = i2d_ECDSA_SIG(s, &tmp);
+
+    *signedData = encodedSig.release();
+
+    ECDSA_SIG_free(s);
+
+    return ret;
+}
+
+static int exynos_km_sign_data(const keymaster0_device_t*, const void* params,
+                       const uint8_t* keyBlob, const size_t keyBlobLength,
+                       const uint8_t* data, const size_t dataLength,
+                       uint8_t** signedData, size_t* signedDataLength) {
+    teeResult_t ret = TEE_ERR_NONE;
+    teeKeyMeta_t meta;
+
+    if (data == NULL) {
+        ALOGE("input data to sign == NULL");
+        return -1;
+    } else if (signedData == NULL || signedDataLength == NULL) {
+        ALOGE("output signature buffer == NULL");
+        return -1;
+    }
+
+    /* find the algorithm */
+    ret = TEE_GetKeyInfo(keyBlob, keyBlobLength, &meta);
+    if (ret != TEE_ERR_NONE) {
+       ALOGE("TEE_GetKeyInfo() is failed: %d", ret);
+       return -1;
+    }
+
+    switch (meta.keytype) {
+    case TEE_KEYTYPE_RSA:
+       if (km_rsa_sign_data(params, keyBlob, keyBlobLength, data,
+                       dataLength, signedData, signedDataLength))
+           return -1;
+       break;
+    case TEE_KEYTYPE_DSA:
+       if (km_dsa_sign_data(params, keyBlob, keyBlobLength, data,
+                       dataLength, signedData, signedDataLength))
+           return -1;
+       break;
+    case TEE_KEYTYPE_ECDSA:
+       if (km_ecdsa_sign_data(params, keyBlob, keyBlobLength, data,
+                       dataLength, signedData, signedDataLength))
+           return -1;
+       break;
+    default:
+       ALOGE("Invalid key type");
+       return -1;
+    }
+
+    return ret;
+}
+
+static int km_rsa_verify_data(const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* signedData,
+                       const size_t signedDataLength, const uint8_t* signature,
+                       const size_t signatureLength, bool* result) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    } else if (sign_params->padding_type != PADDING_NONE) {
+        ALOGE("Cannot handle padding type %d", sign_params->padding_type);
+        return -1;
+    } else if (signatureLength != signedDataLength) {
+        ALOGE("signed data length must be signature length");
+        return -1;
+    }
+
+    /* binder gives us read-only mappings we can't use with mobicore */
+    void *tmpSignedData = malloc(signedDataLength);
+    void *tmpSig = malloc(signatureLength);
+
+    memcpy(tmpSignedData, signedData, signedDataLength);
+    memcpy(tmpSig, signature, signatureLength);
+
+    ret = TEE_RSAVerify(keyBlob, keyBlobLength, (const uint8_t*)tmpSignedData, signedDataLength, (const uint8_t *)tmpSig,
+                       signatureLength, TEE_RSA_NODIGEST_NOPADDING, result);
+
+    free(tmpSignedData);
+    free(tmpSig);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_RSAVerify() is failed: %d", ret);
+        return -1;
+    }
+
+    return ret;
+}
+
+static int km_dsa_verify_data(const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* signedData,
+                       const size_t signedDataLength, const uint8_t* signature,
+                       const size_t signatureLength, bool* result) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    keymaster_dsa_sign_params_t* sign_params = (keymaster_dsa_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> tmpData(reinterpret_cast<uint8_t*>(malloc(signedDataLength)));
+    if (tmpData.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+    memcpy(tmpData.get(), signedData, signedDataLength);
+
+    UniquePtr<uint8_t, Malloc_Free> encSig(reinterpret_cast<uint8_t*>(malloc(signatureLength)));
+    if (encSig.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+    memcpy(encSig.get(), signature, signatureLength);
+
+    /* Decodes a DER encoded signature */
+    DSA_SIG *s = DSA_SIG_new();
+    if (!s) {
+       ALOGE("memory allocation is failed");
+       return -1;
+    }
+
+    uint8_t *tmpEncSig = encSig.get();
+    if (!d2i_DSA_SIG(&s, (const unsigned char**)&tmpEncSig, signatureLength)) {
+       ALOGE("failed to decodes a signature");
+       return -1;
+    }
+
+    size_t rlen, slen;
+    UniquePtr<uint8_t, Malloc_Free> sig(reinterpret_cast<uint8_t*>(malloc(signatureLength)));
+    if (sig.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    rlen = BN_bn2bin(s->r, sig.get());
+    slen = BN_bn2bin(s->s, sig.get() + rlen);
+
+    ret = TEE_DSAVerify(keyBlob, keyBlobLength, (const uint8_t*)tmpData.get(),
+                       signedDataLength, (const uint8_t *)sig.get(),
+                       rlen + slen, result);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_RSAVerify() is failed: %d", ret);
+        return -1;
+    }
+
+    return ret;
+}
+
+static int km_ecdsa_verify_data(const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* signedData,
+                       const size_t signedDataLength, const uint8_t* signature,
+                       const size_t signatureLength, bool* result) {
+    teeResult_t ret = TEE_ERR_NONE;
+
+    keymaster_ec_sign_params_t* sign_params = (keymaster_ec_sign_params_t*) params;
+    if (sign_params->digest_type != DIGEST_NONE) {
+        ALOGE("Cannot handle digest type %d", sign_params->digest_type);
+        return -1;
+    }
+
+    UniquePtr<uint8_t, Malloc_Free> tmpData(reinterpret_cast<uint8_t*>(malloc(signedDataLength)));
+    if (tmpData.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+    memcpy(tmpData.get(), signedData, signedDataLength);
+
+    UniquePtr<uint8_t, Malloc_Free> encSig(reinterpret_cast<uint8_t*>(malloc(signatureLength)));
+    if (encSig.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+    memcpy(encSig.get(), signature, signatureLength);
+
+    /* Decodes a DER encoded signature */
+    ECDSA_SIG *s = ECDSA_SIG_new();
+    if (!s) {
+       ALOGE("memory allocation is failed");
+       return -1;
+    }
+
+    uint8_t *tmpEncSig = encSig.get();
+    if (!d2i_ECDSA_SIG(&s, (const unsigned char**)&tmpEncSig, signatureLength)) {
+       ALOGE("failed to decodes a signature");
+       return -1;
+    }
+
+    size_t rlen, slen;
+    UniquePtr<uint8_t, Malloc_Free> sig(reinterpret_cast<uint8_t*>(malloc(signatureLength)));
+    if (sig.get() == NULL) {
+        ALOGE("memory allocation is failed");
+        return -1;
+    }
+
+    rlen = BN_bn2bin(s->r, sig.get());
+    slen = BN_bn2bin(s->s, sig.get() + rlen);
+
+    ret = TEE_ECDSAVerify(keyBlob, keyBlobLength, (const uint8_t*)tmpData.get(),
+                       signedDataLength, (const uint8_t *)sig.get(),
+                       rlen + slen, result);
+    if (ret != TEE_ERR_NONE) {
+        ALOGE("TEE_RSAVerify() is failed: %d", ret);
+        return -1;
+    }
+
+   return ret;
+}
+
+static int exynos_km_verify_data(const keymaster0_device_t*,
+                       const void* params, const uint8_t* keyBlob,
+                       const size_t keyBlobLength, const uint8_t* signedData,
+                       const size_t signedDataLength, const uint8_t* signature,
+                       const size_t signatureLength) {
+    bool result;
+    teeResult_t ret = TEE_ERR_NONE;
+    teeKeyMeta_t meta;
+
+    if (signedData == NULL || signature == NULL) {
+        ALOGE("data or signature buffers == NULL");
+        return -1;
+    }
+
+    /* find the algorithm */
+    ret = TEE_GetKeyInfo(keyBlob, keyBlobLength, &meta);
+    if (ret != TEE_ERR_NONE) {
+       ALOGE("TEE_GetKeyInfo() is failed: %d", ret);
+       return -1;
+    }
+
+    switch (meta.keytype) {
+    case TEE_KEYTYPE_RSA:
+       if (km_rsa_verify_data(params, keyBlob, keyBlobLength,
+                       signedData, signedDataLength, signature,
+                       signatureLength, &result))
+           return -1;
+       break;
+    case TEE_KEYTYPE_DSA:
+       if (km_dsa_verify_data(params, keyBlob, keyBlobLength,
+                       signedData, signedDataLength, signature,
+                       signatureLength, &result))
+           return -1;
+       break;
+    case TEE_KEYTYPE_ECDSA:
+       if (km_ecdsa_verify_data(params, keyBlob, keyBlobLength,
+                       signedData, signedDataLength, signature,
+                       signatureLength, &result))
+           return -1;
+       break;
+    default:
+       ALOGE("Invalid key type");
+       return -1;
+    }
+
+    return (result == true) ? 0 : -1;
+}
+
+/* Close an opened Exynos KM instance */
+static int exynos_km_close(hw_device_t *dev) {
+    free(dev);
+    return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int exynos_km_open(const hw_module_t* module, const char* name,
+        hw_device_t** device) {
+    if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
+        return -EINVAL;
+
+    Unique_keymaster0_device_t dev(new keymaster0_device_t);
+    if (dev.get() == NULL)
+        return -ENOMEM;
+
+    dev->common.tag = HARDWARE_DEVICE_TAG;
+    dev->common.version = 1;
+    dev->common.module = (struct hw_module_t*) module;
+    dev->common.close = exynos_km_close;
+
+#if defined(KEYMASTER_VER0_3)
+    dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE;
+#else
+    dev->flags = 0;
+#endif
+
+    dev->generate_keypair = exynos_km_generate_keypair;
+    dev->import_keypair = exynos_km_import_keypair;
+    dev->get_keypair_public = exynos_km_get_keypair_public;
+    dev->delete_keypair = NULL;
+    dev->delete_all = NULL;
+    dev->sign_data = exynos_km_sign_data;
+    dev->verify_data = exynos_km_verify_data;
+
+    ERR_load_crypto_strings();
+    ERR_load_BIO_strings();
+
+    *device = reinterpret_cast<hw_device_t*>(dev.release());
+
+    return 0;
+}
+
+static struct hw_module_methods_t keystore_module_methods = {
+    open: exynos_km_open,
+};
+
+struct keystore_module HAL_MODULE_INFO_SYM
+__attribute__ ((visibility ("default"))) = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+#if defined(KEYMASTER_VER0_3)
+        version_major: 3,
+#else
+        version_major: 2,
+#endif
+        version_minor: 0,
+        id: KEYSTORE_HARDWARE_MODULE_ID,
+        name: "Keymaster Exynos HAL",
+        author: "Samsung S.LSI",
+        methods: &keystore_module_methods,
+        dso: 0,
+        reserved: {},
+    },
+};
diff --git a/libkeymaster/ver0/tci.h b/libkeymaster/ver0/tci.h
new file mode 100644 (file)
index 0000000..dd558c3
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TCI_H__
+#define __TCI_H__
+
+
+typedef uint32_t tciCommandId_t;
+typedef uint32_t tciResponseId_t;
+typedef uint32_t tciReturnCode_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)
+
+
+/**
+ * Return codes
+ */
+#define RET_OK                    0
+#define RET_ERR_UNKNOWN_CMD       1
+#define RET_ERR_NOT_SUPPORTED     2
+#define RET_ERR_INVALID_BUFFER    3
+#define RET_ERR_INVALID_KEY_SIZE  4
+#define RET_ERR_INVALID_KEY_TYPE  5
+#define RET_ERR_INVALID_LENGTH    6
+#define RET_ERR_INVALID_EXPONENT  7
+#define RET_ERR_INVALID_CURVE     8
+#define RET_ERR_KEY_GENERATION    9
+#define RET_ERR_SIGN              10
+#define RET_ERR_VERIFY            11
+#define RET_ERR_DIGEST            12
+#define RET_ERR_SECURE_OBJECT     13
+#define RET_ERR_INTERNAL_ERROR    14
+#define RET_ERR_OUT_OF_MEMORY     15
+/* ... add more error codes when needed */
+
+
+/**
+ * TCI command header.
+ */
+typedef struct{
+    tciCommandId_t commandId; /**< Command ID */
+} tciCommandHeader_t;
+
+
+/**
+ * TCI response header.
+ */
+typedef struct{
+    tciResponseId_t     responseId; /**< Response ID (must be command ID | RSP_ID_MASK )*/
+    tciReturnCode_t     returnCode; /**< Return code of command */
+} tciResponseHeader_t;
+
+#endif // __TCI_H__
diff --git a/libkeymaster/ver0/tlTeeKeymaster_Api.h b/libkeymaster/ver0/tlTeeKeymaster_Api.h
new file mode 100644 (file)
index 0000000..d242c11
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLTEEKEYMASTERAPI_H__
+#define __TLTEEKEYMASTERAPI_H__
+
+#include "tci.h"
+
+
+
+/**
+ * Command ID's
+ */
+#define CMD_ID_TEE_RSA_GEN_KEY_PAIR    1
+#define CMD_ID_TEE_RSA_SIGN            2
+#define CMD_ID_TEE_RSA_VERIFY          3
+#define CMD_ID_TEE_KEY_IMPORT          4
+#define CMD_ID_TEE_GET_PUB_KEY         5
+#define CMD_ID_TEE_DSA_GEN_KEY_PAIR    6
+#define CMD_ID_TEE_DSA_SIGN            7
+#define CMD_ID_TEE_DSA_VERIFY          8
+#define CMD_ID_TEE_ECDSA_GEN_KEY_PAIR  9
+#define CMD_ID_TEE_ECDSA_SIGN          10
+#define CMD_ID_TEE_ECDSA_VERIFY        11
+#define CMD_ID_TEE_GET_KEY_INFO        12
+/*... add more command ids when needed */
+
+
+/**
+ * Curve types
+ */
+#define ECC_CURVE_NIST_P192 1
+#define ECC_CURVE_NIST_P224 2
+#define ECC_CURVE_NIST_P256 3
+#define ECC_CURVE_NIST_P384 4
+#define ECC_CURVE_NIST_P521 5
+/*... add more curves when needed */
+
+/**
+ * Command message.
+ *
+ * @param len Length of the data to process.
+ * @param data Data to be processed
+ */
+typedef struct {
+    tciCommandHeader_t  header;     /**< Command header */
+    uint32_t            len;        /**< Length of data to process */
+} command_t;
+
+
+/**
+ * Response structure
+ */
+typedef struct {
+    tciResponseHeader_t header;     /**< Response header */
+    uint32_t            len;
+} response_t;
+
+
+/**
+ * RSA private key metadata (Private modulus and exponent lengths)
+ */
+typedef struct {
+    uint32_t  priv_exp_len; /**< Private key exponent length */
+} rsa_priv_key_meta_t;
+
+
+/**
+ * RSA CRT private key metadata
+ */
+typedef struct {
+    uint32_t  p_len;          /**< Prime p length */
+    uint32_t  q_len;          /**< Prime q length */
+    uint32_t  dp_len;         /**< DP length */
+    uint32_t  dq_len;         /**< DQ length */
+    uint32_t  qinv_len;       /**< QP length */
+} rsa_crt_priv_key_meta_t;
+
+
+/**
+ * RSA key metadata (key size, modulus/exponent lengths, etc..)
+ */
+typedef struct {
+    uint32_t  type;           /**< RSA key pair type. RSA or RSA CRT */
+    uint32_t  key_size;      /**<  RSA key size */
+    uint32_t  pub_mod_len;    /**< Public key modulus length */
+    uint32_t  pub_exp_len;    /**< Public key exponent length */
+    union {
+        rsa_priv_key_meta_t     rsa_priv;     /**< RSA private key */
+        rsa_crt_priv_key_meta_t rsa_crt_priv; /**< RSA CRT private key */
+    };
+} rsa_key_meta_t;
+
+
+/**
+ * DSA key metadata (p, q, g, x and y lengths)
+ */
+typedef struct {
+    uint32_t  p_len;      /**< q length */
+    uint32_t  q_len;      /**< q length */
+    uint32_t  g_len;      /**< Generator length */
+    uint32_t  x_len;      /**< x length */
+    uint32_t  y_len;      /**< y length */
+} dsa_key_meta_t;
+
+
+/**
+ * ECDSA key metadata
+ */
+typedef struct {
+    uint32_t  curve;        /**< Curve type */
+    uint32_t  curve_length; /**< curve length */
+} ecdsa_key_meta_t;
+
+
+/**
+ * Key metadata
+ */
+typedef struct {
+    uint32_t  key_type;      /**< Key type (RSA, DSA, ECDSA,..) */
+    union {
+        rsa_key_meta_t   rsa_key;   /**< RSA key */
+        dsa_key_meta_t   dsa_key;   /**< DSA key */
+        ecdsa_key_meta_t ecdsa_key; /**< ECDSA key */
+    };
+} key_meta_t;
+
+
+/**
+ * RSA public key metadata (modulus and exponent lengths)
+ */
+typedef struct {
+    uint32_t  pub_mod_len;     /**< Public key modulus length */
+    uint32_t  pub_exp_len;     /**< Public key exponent length */
+} rsa_pub_key_meta_t;
+
+
+/**
+ * DSA public key metadata (p, q, g, and y lengths)
+ */
+typedef struct {
+    uint32_t  p_len;        /**< q length */
+    uint32_t  q_len;        /**< q length */
+    uint32_t  g_len;        /**< Generator length */
+    uint32_t  y_len;        /**< y length */
+} dsa_pub_key_meta_t;
+
+
+/**
+ * ECDSA public key metadata
+ */
+typedef struct {
+    uint32_t  curve;        /**< Curve e.g. P192, P224,..,P521*/
+} ecdsa_pub_key_meta_t;
+
+
+/**
+ * Public key metadata
+ */
+typedef struct {
+    uint32_t     key_type;  /**< Key type (RSA, DSA, ECDSA,..) */
+    union {
+        rsa_pub_key_meta_t   rsa_pub_key;   /**< RSA public key */
+        dsa_pub_key_meta_t   dsa_pub_key;   /**< DSA public key */
+        ecdsa_pub_key_meta_t ecdsa_pub_key; /**< ECDSA public key */
+    };
+} pub_key_meta_t;
+
+
+/**
+ * Generate RSA key data
+ * Response data contains generated RSA key pair data is
+ * wrapped as below:
+ *
+ * |-- Key metadata --|-- Public key (plaintext) --|-- Private key (encrypted) --|
+ */
+typedef struct {
+    uint32_t  type;           /**< Key pair type. RSA or RSACRT */
+    uint32_t  key_size;       /**< Key size in bits, e.g. 1024, 2048,.. */
+    uint32_t  exponent;       /**< Exponent number */
+    uint32_t  key_data;       /**< Key data buffer passed by TLC  */
+    uint32_t  key_data_len;   /**< Length of key data buffer */
+    uint32_t  so_len;        /**< Secure object length  (of key data) (provided by the trustlet)  */
+} rsa_gen_key_t;
+
+
+/**
+ *  RSA sign data structure
+ */
+typedef struct {
+    uint32_t  key_data;           /**< Key data buffer */
+    uint32_t  key_data_len;       /**< Length of key data buffer */
+    uint32_t  plain_data;         /**< Plaintext data buffer */
+    uint32_t  plain_data_len;     /**< Length of plaintext data buffer */
+    uint32_t  signature_data;     /**< Signature data buffer */
+    uint32_t  signature_data_len; /**< Length of signature data buffer */
+    uint32_t  algorithm;          /**< Signing algorithm */
+} rsa_sign_t;
+
+
+/**
+ *  RSA signature verify data structure
+ */
+typedef struct {
+    uint32_t  key_data;           /**< Key data buffer */
+    uint32_t  key_data_len;       /**< Length of key data buffer */
+    uint32_t  plain_data;         /**< Plaintext data buffer */
+    uint32_t  plain_data_len;     /**< Length of plaintext data buffer */
+    uint32_t  signature_data;     /**< Signature data buffer */
+    uint32_t  signature_data_len; /**< Length of signature data buffer */
+    uint32_t  algorithm;          /**< Signing algorithm */
+    bool      validity;           /**< Signature validity */
+} rsa_verify_t;
+
+
+/**
+ *  Key import data structure
+ */
+typedef struct {
+    uint32_t  key_data;        /**< Key data buffer */
+    uint32_t  key_data_len;    /**< Length of key data buffer */
+    uint32_t  so_data;         /**< Wrapped buffer */
+    uint32_t  so_data_len;     /**< Length of wrapped data buffer */
+} key_import_t;
+
+
+/**
+ *  Get public key data structure
+ */
+typedef struct {
+    uint32_t  type;              /**< Key type */
+    uint32_t  key_data;          /**< Key data buffer */
+    uint32_t  key_data_len;      /**< Length of key data buffer */
+    uint32_t  pub_key_data;      /**< Public key data */
+    uint32_t  pub_key_data_len;  /**< Public key length */
+} get_pub_key_t;
+
+
+/**
+ * Generate DSA key data
+ * Response data contains generated DSA key pair data is
+ * wrapped as below:
+ *
+ * |-- Key metadata --|-- Public key (plaintext) --|-- Private key (encrypted) --|
+ *
+ * Public key data includes p, q, g and y
+ */
+typedef struct {
+    uint32_t  p;            /**< p */
+    uint32_t  q;            /**< q */
+    uint32_t  g;            /**< g */
+    uint32_t  p_len;        /**< p length */
+    uint32_t  q_len;        /**< q length */
+    uint32_t  g_len;        /**< g length */
+    uint32_t  x_len;        /**< x length */
+    uint32_t  y_len;        /**< y length */
+    uint32_t  key_data;     /**< Key data buffer passed by TLC  */
+    uint32_t  key_data_len; /**< Length of key data buffer */
+    uint32_t  so_len;       /**< Secure object length (of key data) */
+} dsa_gen_key_t;
+
+
+/**
+ *  DSA sign data structure
+ */
+typedef struct {
+    uint32_t  key_data;            /**< Key data buffer */
+    uint32_t  key_data_len;        /**< Length of key data buffer */
+    uint32_t  digest_data;         /**< Digest data buffer */
+    uint32_t  digest_data_len;     /**< Length of digest data buffer */
+    uint32_t  signature_data;      /**< Signature data buffer */
+    uint32_t  signature_data_len;  /**< Length of signature data buffer */
+} dsa_sign_t;
+
+
+/**
+ *  DSA signature verify data structure
+ */
+typedef struct {
+    uint32_t  key_data;           /**< Key data buffer */
+    uint32_t  key_data_len;       /**< Length of key data buffer */
+    uint32_t  digest_data;        /**< Plaintext data buffer */
+    uint32_t  digest_data_len;    /**< Length of plaintext data buffer */
+    uint32_t  signature_data;     /**< Signature data buffer */
+    uint32_t  signature_data_len; /**< Length of signature data buffer */
+    bool      validity;           /**< Signature validity */
+} dsa_verify_t;
+
+
+/**
+ * Generate ECDSA key data
+ * Response data contains generated ECDSA key pair data is
+ * wrapped as below:
+ *
+ * |-- Key metadata --|-- Public key (plaintext) --|-- Private key (encrypted) --|
+ *
+ * Public key data includes x and y
+ */
+typedef struct {
+    uint32_t  curve;        /**< Curve type P192=1, P224=2, P256=3, P384=4, P521=5  */
+    uint32_t  key_data;     /**< Key data buffer passed by TLC  */
+    uint32_t  key_data_len; /**< Length of key data buffer */
+    uint32_t  so_len;       /**< Secure object length (of key data) */
+} ecdsa_gen_key_t;
+
+
+/**
+ *  ECDSA sign data structure
+ */
+typedef struct {
+    uint32_t  key_data;           /**< Key data buffer */
+    uint32_t  key_data_len;       /**< Length of key data buffer */
+    uint32_t  digest_data;        /**< Digest data buffer */
+    uint32_t  digest_data_len;    /**< Length of digest data buffer */
+    uint32_t  signature_data;     /**< Signature data buffer */
+    uint32_t  signature_data_len; /**< Length of signature data buffer */
+} ecdsa_sign_t;
+
+
+/**
+ *  ECDSA signature verify data structure
+ */
+typedef struct {
+    uint32_t  key_data;           /**< Key data buffer */
+    uint32_t  key_data_len;       /**< Length of key data buffer */
+    uint32_t  digest_data;        /**< Digest data buffer */
+    uint32_t  digest_data_len;    /**< Length of digest data buffer */
+    uint32_t  signature_data;     /**< Signature data buffer */
+    uint32_t  signature_data_len; /**< Length of signature data buffer */
+    bool      validity;           /**< Signature validity */
+} ecdsa_verify_t;
+
+
+/**
+ *  Key info data structure
+ */
+typedef struct {
+    uint32_t  key_blob;           /**< Key blob buffer */
+    uint32_t  key_blob_len;       /**< Length of key blob buffer */
+    uint32_t  key_metadata;       /**< Key metadata */
+} get_key_info_t;
+
+/**
+ * TCI message data.
+ */
+typedef struct {
+    union {
+        command_t     command;
+        response_t    response;
+    };
+
+    union {
+        rsa_gen_key_t    rsa_gen_key;
+        rsa_sign_t       rsa_sign;
+        rsa_verify_t     rsa_verify;
+        key_import_t     key_import;
+        get_pub_key_t    get_pub_key;
+        dsa_gen_key_t    dsa_gen_key;
+        dsa_sign_t       dsa_sign;
+        dsa_verify_t     dsa_verify;
+        ecdsa_gen_key_t  ecdsa_gen_key;
+        ecdsa_sign_t     ecdsa_sign;
+        ecdsa_verify_t   ecdsa_verify;
+        get_key_info_t   get_key_info;
+    };
+
+} tciMessage_t, *tciMessage_ptr;
+
+
+/**
+ * Overall TCI structure.
+ */
+typedef struct {
+    tciMessage_t message;   /**< TCI message */
+} tci_t;
+
+
+/**
+ * Trustlet UUID
+ */
+#define TEE_KEYMASTER_TL_UUID { { 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
+
+
+#endif // __TLTEEKEYMASTERAPI_H__
diff --git a/libkeymaster/ver0/tlTeeKeymaster_log.h b/libkeymaster/ver0/tlTeeKeymaster_log.h
new file mode 100644 (file)
index 0000000..6665f96
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLTEEKEYMASTERLOG_H__
+#define __TLTEEKEYMASTERLOG_H__
+
+#include <android/log.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "TlcTeeKeyMaster"
+#endif // LOG_TAG
+
+/* Macro definitions */
+#define LOG_D(...) __android_log_print(ANDROID_LOG_DEBUG , LOG_TAG, __VA_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__)
+
+
+#endif // __TLTEEKEYMASTERLOG_H__
diff --git a/libkeymaster/ver0/tlcTeeKeymaster_if.c b/libkeymaster/ver0/tlcTeeKeymaster_if.c
new file mode 100644 (file)
index 0000000..816df99
--- /dev/null
@@ -0,0 +1,1771 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MobiCoreDriverApi.h"
+#include "tlTeeKeymaster_Api.h"
+#include "tlcTeeKeymaster_if.h"
+#include "buildTag.h"
+
+#define LOG_TAG "TlcTeeKeyMaster"
+#include "log.h"
+
+/* Global definitions */
+static const __attribute__((used)) char* buildtag = MOBICORE_COMPONENT_BUILD_TAG;
+static const uint32_t gDeviceId = MC_DEVICE_ID_DEFAULT;
+static const mcUuid_t gUuid = TEE_KEYMASTER_TL_UUID;
+
+/**
+ * TEE_Open
+ *
+ * Open session to the TEE Keymaster trusted application
+ *
+ * @param  pSessionHandle  [out] Return pointer to the session handle
+ */
+static tciMessage_ptr TEE_Open(
+    mcSessionHandle_t *pSessionHandle
+){
+    tciMessage_ptr pTci = NULL;
+    mcResult_t     mcRet;
+
+    do
+    {
+        /* Validate session handle */
+        if (pSessionHandle == NULL)
+        {
+            LOG_E("TEE_Open(): Invalid session handle\n");
+            break;
+        }
+
+        /* Initialize session handle data */
+        memset(pSessionHandle, 0, sizeof(mcSessionHandle_t));
+
+        /* Open MobiCore device */
+        mcRet = mcOpenDevice(gDeviceId);
+        if ((MC_DRV_OK != mcRet) &&
+            (MC_DRV_ERR_DEVICE_ALREADY_OPEN != mcRet))
+        {
+            LOG_E("TEE_Open(): mcOpenDevice returned: %d\n", mcRet);
+            break;
+        }
+
+        /* Allocating WSM for TCI */
+        mcRet = mcMallocWsm(gDeviceId, 0, sizeof(tciMessage_t), (uint8_t **) &pTci, 0);
+        if (MC_DRV_OK != mcRet)
+        {
+            LOG_E("TEE_Open(): mcMallocWsm returned: %d\n", mcRet);
+            break;
+        }
+
+        /* Open session the TEE Keymaster trusted application */
+        pSessionHandle->deviceId = gDeviceId;
+        mcRet = mcOpenSession(pSessionHandle,
+                              &gUuid,
+                              (uint8_t *) pTci,
+                              (uint32_t) sizeof(tciMessage_t));
+        if (MC_DRV_OK != mcRet)
+        {
+            LOG_E("TEE_Open(): mcOpenSession returned: %d\n", mcRet);
+            break;
+        }
+
+    } while (false);
+
+    LOG_I("TEE_Open(): returning pointer to TCI buffer: 0x%p\n", pTci);
+
+    return pTci;
+}
+
+
+/**
+ * TEE_Close
+ *
+ * Close session to the TEE Keymaster trusted application
+ *
+ * @param  sessionHandle  [in] Session handle
+ */
+static void TEE_Close(
+    mcSessionHandle_t *pSessionHandle
+){
+    mcResult_t    mcRet;
+
+    do
+    {
+        /* Validate session handle */
+        if (pSessionHandle == NULL)
+        {
+            LOG_E("TEE_Close(): Invalid session handle\n");
+            break;
+        }
+
+        /* Close session */
+        mcRet = mcCloseSession(pSessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            LOG_E("TEE_Close(): mcCloseSession returned: %d\n", mcRet);
+            break;
+        }
+
+        /* Close MobiCore device */
+        mcRet = mcCloseDevice(gDeviceId);
+        if (MC_DRV_OK != mcRet)
+        {
+            LOG_E("TEE_Close(): mcCloseDevice returned: %d\n", mcRet);
+        }
+
+    } while (false);
+}
+
+
+/**
+ * TEE_RSAGenerateKeyPair
+ *
+ * Generates RSA key pair and returns key pair data as wrapped object
+ *
+ * @param  keyType        [in]  Key pair type. RSA or RSACRT
+ * @param  keyData        [in]  Pointer to the key data buffer
+ * @param  keyDataLength  [in]  Key data buffer length
+ * @param  keySize        [in]  Key size
+ * @param  exponent       [in]  Exponent number
+ * @param  soLen          [out] Key data secure object length
+ */
+teeResult_t TEE_RSAGenerateKeyPair(
+    teeRsaKeyPairType_t keyType,
+    uint8_t*            keyData,
+    uint32_t            keyDataLength,
+    uint32_t            keySize,
+    uint32_t            exponent,
+    uint32_t*           soLen
+){
+    teeResult_t         ret = TEE_ERR_NONE;
+    tciMessage_ptr      pTci = NULL;
+    mcSessionHandle_t   sessionHandle;
+    mcBulkMap_t         mapInfo = {0};
+    mcResult_t          mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL) || (soLen == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Validate key pair type */
+        if ((keyType != TEE_KEYPAIR_RSA) &&
+            (keyType != TEE_KEYPAIR_RSACRT))
+        {
+            ret = TEE_ERR_INVALID_INPUT;
+            break;
+        }
+
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, keyData, keyDataLength, &mapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId = CMD_ID_TEE_RSA_GEN_KEY_PAIR;
+        pTci->rsa_gen_key.type         = keyType;
+        pTci->rsa_gen_key.key_size     = keySize;
+        pTci->rsa_gen_key.key_data     = (uint32_t)mapInfo.sVirtualAddr;
+        pTci->rsa_gen_key.key_data_len = keyDataLength;
+        pTci->rsa_gen_key.exponent     = exponent;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            LOG_E("mcNotify failed with %x\n", mcRet);
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        mcRet = mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT);
+        if (MC_DRV_OK != mcRet)
+        {
+            LOG_E("TEE_RSAGenerateKeyPair(): mcWaitNotification failed with %x\n", mcRet);
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_RSAGenerateKeyPair(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Update secure object length */
+        *soLen =  pTci->rsa_gen_key.so_len;
+
+    } while (false);
+
+    /* Unmap memory */
+    if (mapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, keyData, &mapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_RSASign
+ *
+ * Signs given plain data and returns signature data
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  plainData        [in]  Pointer to plain data to be signed
+ * @param  plainDataLength  [in]  Plain data length
+ * @param  signatureData    [out] Pointer to signature data
+ * @param  signatureDataLength  [out] Signature data length
+ * @param  algorithm        [in]  RSA signature algorithm
+ */
+teeResult_t TEE_RSASign(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  plainData,
+    const uint32_t  plainDataLength,
+    uint8_t*        signatureData,
+    uint32_t*       signatureDataLength,
+    teeRsaSigAlg_t  algorithm
+){
+    teeResult_t        ret = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyMapInfo       = {0};
+    mcBulkMap_t        plainMapInfo     = {0};
+    mcBulkMap_t        signatureMapInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)       ||
+        (plainData == NULL)     ||
+        (signatureData == NULL) ||
+        (signatureDataLength == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId    = CMD_ID_TEE_RSA_SIGN;
+        pTci->rsa_sign.key_data           = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->rsa_sign.plain_data         = (uint32_t)plainMapInfo.sVirtualAddr;
+        pTci->rsa_sign.signature_data     = (uint32_t)signatureMapInfo.sVirtualAddr;
+        pTci->rsa_sign.key_data_len       = keyDataLength;
+        pTci->rsa_sign.plain_data_len     = plainDataLength;
+        pTci->rsa_sign.signature_data_len = *signatureDataLength;
+        pTci->rsa_sign.algorithm          = algorithm;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_RSASign(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Retrieve signature data length */
+        *signatureDataLength = pTci->rsa_sign.signature_data_len;
+
+    } while (false);
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (plainMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (signatureMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_RSAVerify
+ *
+ * Verifies given data with RSA public key and return status
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  plainData        [in]  Pointer to plain data to be signed
+ * @param  plainDataLength  [in]  Plain data length
+ * @param  signatureData    [in]  Pointer to signed data
+ * @param  signatureData    [in]  Plain  data length
+ * @param  algorithm        [in]  RSA signature algorithm
+ * @param  validity         [out] Signature validity
+ */
+teeResult_t TEE_RSAVerify(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  plainData,
+    const uint32_t  plainDataLength,
+    const uint8_t*  signatureData,
+    const uint32_t  signatureDataLength,
+    teeRsaSigAlg_t  algorithm,
+    bool            *validity
+){
+    teeResult_t        ret = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyMapInfo       = {0};
+    mcBulkMap_t        plainMapInfo     = {0};
+    mcBulkMap_t        signatureMapInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)       ||
+        (plainData == NULL)     ||
+        (signatureData == NULL) ||
+        (validity == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)plainData, plainDataLength, &plainMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId      = CMD_ID_TEE_RSA_VERIFY;
+        pTci->rsa_verify.key_data           = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->rsa_verify.plain_data         = (uint32_t)plainMapInfo.sVirtualAddr;
+        pTci->rsa_verify.signature_data     = (uint32_t)signatureMapInfo.sVirtualAddr;
+        pTci->rsa_verify.key_data_len       = keyDataLength;
+        pTci->rsa_verify.plain_data_len     = plainDataLength;
+        pTci->rsa_verify.signature_data_len = signatureDataLength;
+        pTci->rsa_verify.algorithm          = algorithm;
+        pTci->rsa_verify.validity           = false;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_RSAVerify(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        *validity =  pTci->rsa_verify.validity;
+
+    } while (false);
+
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (plainMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)plainData, &plainMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (signatureMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_KeyImport
+ *
+ * Imports key data and returns key data as secure object
+ *
+ * Key data needs to be in the following format
+ *
+ * RSA key data:
+ * |--key metadata--|--public modulus--|--public exponent--|--private exponent--|
+ *
+ * RSA CRT key data:
+ * |--key metadata--|--public modulus--|--public exponent--|--P--|--Q--|--DP--|--DQ--|--Qinv--|
+ *
+ * Where:
+ * P:     secret prime factor
+ * Q:     secret prime factor
+ * DP:    d mod (p-1)
+ * DQ:    d mod (q-1)
+ * Qinv:  q^-1 mod p
+ *
+ * DSA key data:
+ * |-- Key metadata --|--p--|--q--|--g--|--y--|--private key data (x)--|
+ *
+ * Where:
+ * p:     prime (modulus)
+ * q:     sub prime
+ * g:     generator
+ * y:     public y
+ * x:     private x
+ *
+ * ECDSA key data:
+ * |-- Key metadata --|--x--|--y--|--private key data --|
+ *
+ * Where:
+ * x:     affine point x
+ * y:     affine point y
+ *
+ * @param  keyData          [in]  Pointer to key data
+ * @param  keyDataLength    [in]  Key data length
+ * @param  soData           [out] Pointer to wrapped key data
+ * @param  soDataLength     [out] Wrapped key data length
+ */
+teeResult_t TEE_KeyImport(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    uint8_t*        soData,
+    uint32_t*       soDataLength
+){
+    teeResult_t         ret  = TEE_ERR_NONE;
+    tciMessage_ptr      pTci = NULL;
+    mcSessionHandle_t   sessionHandle;
+    mcBulkMap_t         keyMapInfo = {0};
+    mcBulkMap_t         soMapInfo  = {0};
+    mcResult_t          mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)   ||
+        (soData == NULL)    ||
+        (soDataLength == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)soData, *soDataLength, &soMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId = CMD_ID_TEE_KEY_IMPORT;
+        pTci->key_import.key_data      = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->key_import.so_data       = (uint32_t)soMapInfo.sVirtualAddr;
+        pTci->key_import.key_data_len  = keyDataLength;
+        pTci->key_import.so_data_len   = *soDataLength;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_KeyImport(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Update secure object length */
+        *soDataLength =  pTci->key_import.so_data_len;
+
+    } while (false);
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (soMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)soData, &soMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/** * TEE_GetPubKey
+ *
+ * Retrieves public key data from wrapped key data
+ *
+ *
+ * RSA public key data:
+ * |--public key metadata--|--public modulus--|--public exponent--|
+ *
+ * DSA public key data:
+ * |-- public key metadata --|--p--|--q--|--g--|--y--|
+ *
+ * ECDSA public key data:
+ * |-- public key metadata --|--x--|--y--|
+ *
+ * @param  keyData          [in]  Pointer to key data
+ * @param  keyDataLength    [in]  Key data length
+ * @param  pubKeyData       [out] Pointer to public key data
+ * @param  pubKeyDataLength [out] Public key data length
+ */
+teeResult_t TEE_GetPubKey(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    uint8_t*        pubKeyData,
+    uint32_t*       pubKeyDataLength
+){
+    teeResult_t         ret  = TEE_ERR_NONE;
+    tciMessage_ptr      pTci = NULL;
+    mcSessionHandle_t   sessionHandle;
+    mcBulkMap_t         keyMapInfo    = {0};
+    mcBulkMap_t         pubKeyMapInfo = {0};
+    mcResult_t          mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)       ||
+        (pubKeyData == NULL)    ||
+        (pubKeyDataLength == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)pubKeyData, *pubKeyDataLength, &pubKeyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId     = CMD_ID_TEE_GET_PUB_KEY;
+        pTci->get_pub_key.key_data         = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->get_pub_key.pub_key_data     = (uint32_t)pubKeyMapInfo.sVirtualAddr;
+        pTci->get_pub_key.key_data_len     = keyDataLength;
+        pTci->get_pub_key.pub_key_data_len = *pubKeyDataLength;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_GetPubKey(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Update  modulus and exponent lengths */
+        *pubKeyDataLength  =   pTci->get_pub_key.pub_key_data_len;
+
+    } while (false);
+
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (pubKeyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)pubKeyData, &pubKeyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_DSAGenerateKeyPair
+ *
+ * Generates DSA key pair and returns key pair data as wrapped object
+ *
+ * @param  keyData        [in]  Pointer to the key data buffer
+ * @param  keyDataLength  [in]  Key data buffer length
+ * @param  params         [in]  DSA parameters
+ * @param  soLen          [out] Key data secure object length
+ */
+teeResult_t TEE_DSAGenerateKeyPair(
+    uint8_t*            keyData,
+    uint32_t            keyDataLength,
+    teeDsaParams_t      *params,
+    uint32_t*           soLen
+){
+    teeResult_t         ret = TEE_ERR_NONE;
+    tciMessage_ptr      pTci = NULL;
+    mcSessionHandle_t   sessionHandle;
+    mcBulkMap_t         keyDataInfo = {0};
+    mcBulkMap_t         pInfo = {0};
+    mcBulkMap_t         qInfo = {0};
+    mcBulkMap_t         gInfo = {0};
+    mcResult_t          mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)   ||
+        (params == NULL)    ||
+        (params->p == NULL) ||
+        (params->q == NULL) ||
+        (params->g == NULL) ||
+        (params->pLen == 0) ||
+        (params->qLen == 0) ||
+        (params->gLen == 0))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map key data buffer to the secure world */
+        mcRet = mcMap(&sessionHandle, keyData, keyDataLength, &keyDataInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Map p buffer to the secure world */
+        mcRet = mcMap(&sessionHandle, params->p, params->pLen, &pInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Map q buffer to the secure world */
+        mcRet = mcMap(&sessionHandle, params->q, params->qLen, &qInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Map g buffer to the secure world */
+        mcRet = mcMap(&sessionHandle, params->g, params->gLen, &gInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId = CMD_ID_TEE_DSA_GEN_KEY_PAIR;
+        pTci->dsa_gen_key.key_data     = (uint32_t)keyDataInfo.sVirtualAddr;
+        pTci->dsa_gen_key.key_data_len = keyDataLength;
+        pTci->dsa_gen_key.p            = (uint32_t)pInfo.sVirtualAddr;
+        pTci->dsa_gen_key.q            = (uint32_t)qInfo.sVirtualAddr;
+        pTci->dsa_gen_key.g            = (uint32_t)gInfo.sVirtualAddr;
+        pTci->dsa_gen_key.p_len        = params->pLen;
+        pTci->dsa_gen_key.q_len        = params->qLen;
+        pTci->dsa_gen_key.g_len        = params->gLen;
+        pTci->dsa_gen_key.x_len        = params->xLen;
+        pTci->dsa_gen_key.y_len        = params->yLen;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_DSAGenerateKeyPair(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Update secure object length */
+        *soLen = pTci->dsa_gen_key.so_len;
+
+    } while (false);
+
+    /* Unmap key data buffer memory */
+    if (keyDataInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, keyData, &keyDataInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+    /* Unmap p buffer */
+    if (pInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, params->p, &pInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Unmap q buffer */
+    if (qInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, params->q, &qInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Unmap g buffer */
+    if (gInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, params->g, &gInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_DSASign
+ *
+ * Signs given plain data and returns signature data
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Digest data to be signed
+ * @param  digestLength     [in]  Digest data length
+ * @param  signatureData    [out] Pointer to signature data
+ * @param  signatureDataLength  [out] Signature data length
+ */
+teeResult_t TEE_DSASign(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLength,
+    uint8_t*        signatureData,
+    uint32_t*       signatureDataLength
+){
+    teeResult_t        ret = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyMapInfo    = {0};
+    mcBulkMap_t        digestMapInfo = {0};
+    mcBulkMap_t        signatureMapInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)   ||
+        (digest == NULL) ||
+        (signatureData == NULL) ||
+        (signatureDataLength == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)digest, digestLength, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId    = CMD_ID_TEE_DSA_SIGN;
+        pTci->dsa_sign.key_data           = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->dsa_sign.digest_data        = (uint32_t)digestMapInfo.sVirtualAddr;
+        pTci->dsa_sign.signature_data     = (uint32_t)signatureMapInfo.sVirtualAddr;
+        pTci->dsa_sign.key_data_len       = keyDataLength;
+        pTci->dsa_sign.digest_data_len    = digestLength;
+        pTci->dsa_sign.signature_data_len = *signatureDataLength;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_DSASign(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Retrieve signature data length */
+        *signatureDataLength = pTci->dsa_sign.signature_data_len;
+
+    } while (false);
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (digestMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)digest, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (signatureMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_DSAVerify
+ *
+ * Verifies given data with DSA public key and return status
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Pointer to digest data to be verified
+ * @param  digestLen        [in]  Digest data length
+ * @param  signatureData    [in]  Pointer to signed data
+ * @param  signatureData    [in]  Plain  data length
+ * @param  validity         [out] Signature validity
+ */
+teeResult_t TEE_DSAVerify(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLen,
+    const uint8_t*  signatureData,
+    const uint32_t  signatureDataLength,
+    bool*           validity
+){
+    teeResult_t        ret  = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyMapInfo       = {0};
+    mcBulkMap_t        digestMapInfo    = {0};
+    mcBulkMap_t        signatureMapInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)       ||
+        (digest == NULL)        ||
+        (signatureData == NULL) ||
+        (validity == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)digest, digestLen, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId      = CMD_ID_TEE_DSA_VERIFY;
+        pTci->dsa_verify.key_data           = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->dsa_verify.digest_data        = (uint32_t)digestMapInfo.sVirtualAddr;
+        pTci->dsa_verify.signature_data     = (uint32_t)signatureMapInfo.sVirtualAddr;
+        pTci->dsa_verify.key_data_len       = keyDataLength;
+        pTci->dsa_verify.digest_data_len    = digestLen;
+        pTci->dsa_verify.signature_data_len = signatureDataLength;
+        pTci->dsa_verify.validity           = false;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_DSAVerify(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        *validity =  pTci->dsa_verify.validity;
+
+    } while (false);
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (digestMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)digest, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (signatureMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_ECDSAGenerateKeyPair
+ *
+ * Generates ECDSA key pair and returns key pair data as wrapped object
+ *
+ * @param  keyData        [in]  Pointer to the key data buffer
+ * @param  keyDataLength  [in]  Key data buffer length
+ * @param  curveType      [in]  Curve type
+ * @param  soLen          [out] Key data secure object length
+ */
+teeResult_t TEE_ECDSAGenerateKeyPair(
+    uint8_t*            keyData,
+    uint32_t            keyDataLength,
+    teeEccCurveType_t   curveType,
+    uint32_t*           soLen
+){
+    teeResult_t         ret     = TEE_ERR_NONE;
+    tciMessage_ptr      pTci    = NULL;
+    mcSessionHandle_t   sessionHandle;
+    mcBulkMap_t         keyDataInfo = {0};
+    mcResult_t          mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL) || (soLen == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map key data buffer to the secure world */
+        mcRet = mcMap(&sessionHandle, keyData, keyDataLength, &keyDataInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+        /* Update TCI buffer */
+        pTci->command.header.commandId   = CMD_ID_TEE_ECDSA_GEN_KEY_PAIR;
+        pTci->ecdsa_gen_key.key_data     = (uint32_t)keyDataInfo.sVirtualAddr;
+        pTci->ecdsa_gen_key.key_data_len = keyDataLength;
+        pTci->ecdsa_gen_key.curve        = curveType;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_ECDSAGenerateKeyPair(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Update secure object length */
+        *soLen =  pTci->ecdsa_gen_key.so_len;
+
+    } while (false);
+
+    /* Unmap key data buffer */
+    if (keyDataInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, keyData, &keyDataInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+
+}
+
+
+/**
+ * TEE_ECDSASign
+ *
+ * Signs given plain data and returns signature data
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Digest data to be signed
+ * @param  digestLength     [in]  Digest data length
+ * @param  signatureData    [out] Pointer to signature data
+ * @param  signatureDataLength  [out] Signature data length
+ */
+teeResult_t TEE_ECDSASign(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLength,
+    uint8_t*        signatureData,
+    uint32_t*       signatureDataLength
+){
+    teeResult_t        ret  = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyMapInfo       = {0};
+    mcBulkMap_t        digestMapInfo    = {0};
+    mcBulkMap_t        signatureMapInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)       ||
+        (digest == NULL)        ||
+        (signatureData == NULL) ||
+        (signatureDataLength == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)digest, digestLength, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)signatureData, *signatureDataLength, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId      = CMD_ID_TEE_ECDSA_SIGN;
+        pTci->ecdsa_sign.key_data           = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->ecdsa_sign.digest_data        = (uint32_t)digestMapInfo.sVirtualAddr;
+        pTci->ecdsa_sign.signature_data     = (uint32_t)signatureMapInfo.sVirtualAddr;
+        pTci->ecdsa_sign.key_data_len       = keyDataLength;
+        pTci->ecdsa_sign.digest_data_len    = digestLength;
+        pTci->ecdsa_sign.signature_data_len = *signatureDataLength;
+
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_ECDSASign(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        /* Retrieve signature data length */
+        *signatureDataLength = pTci->ecdsa_sign.signature_data_len;
+
+    } while (false);
+
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (digestMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)digest, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (signatureMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_ECDSAVerify
+ *
+ * Verifies given data with ECDSA public key and return status
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Pointer to digest data to be verified
+ * @param  digestLen        [in]  Digest data length
+ * @param  signatureData    [in]  Pointer to signed data
+ * @param  signatureData    [in]  Plain  data length
+ * @param  validity         [out] Signature validity
+ */
+teeResult_t TEE_ECDSAVerify(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLen,
+    const uint8_t*  signatureData,
+    const uint32_t  signatureDataLength,
+    bool*           validity
+){
+    teeResult_t        ret  = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyMapInfo       = {0};
+    mcBulkMap_t        digestMapInfo    = {0};
+    mcBulkMap_t        signatureMapInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyData == NULL)       ||
+        (digest == NULL)        ||
+        (signatureData == NULL) ||
+        (validity == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyData, keyDataLength, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)digest, digestLen, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)signatureData, signatureDataLength, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId        = CMD_ID_TEE_ECDSA_VERIFY;
+        pTci->ecdsa_verify.key_data           = (uint32_t)keyMapInfo.sVirtualAddr;
+        pTci->ecdsa_verify.digest_data        = (uint32_t)digestMapInfo.sVirtualAddr;
+        pTci->ecdsa_verify.signature_data     = (uint32_t)signatureMapInfo.sVirtualAddr;
+        pTci->ecdsa_verify.key_data_len       = keyDataLength;
+        pTci->ecdsa_verify.digest_data_len    = digestLen;
+        pTci->ecdsa_verify.signature_data_len = signatureDataLength;
+        pTci->ecdsa_verify.validity = false;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_ECDSAVerify(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+        *validity =  pTci->ecdsa_verify.validity;
+
+    } while (false);
+
+    /* Unmap memory */
+    if (keyMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyData, &keyMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (digestMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)digest, &digestMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (signatureMapInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)signatureData, &signatureMapInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
+
+
+/**
+ * TEE_GetKeyInfo
+ *
+ * Retrieves key information (type, length,..) from key data blob and populates key metadata
+ * accordingly
+ *
+ * @param  keyBlob          [in]  Pointer to key blob data
+ * @param  keyBlobLength    [in]  Key data buffer length
+ * @param  metadata         [out] Pointer to digest data to be verified
+ */
+teeResult_t TEE_GetKeyInfo(
+    const uint8_t*  keyBlob,
+    const uint32_t  keyBlobLength,
+    teeKeyMeta_t*   metadata)
+{
+    teeResult_t        ret  = TEE_ERR_NONE;
+    tciMessage_ptr     pTci = NULL;
+    mcSessionHandle_t  sessionHandle;
+    mcBulkMap_t        keyBlobInfo = {0};
+    mcBulkMap_t        keyDataInfo = {0};
+    mcResult_t         mcRet;
+
+    /* Validate pointers */
+    if ((keyBlob == NULL) || (metadata == NULL))
+    {
+        return TEE_ERR_INVALID_INPUT;
+    }
+
+    do
+    {
+        /* Open session to the trusted application */
+        pTci = TEE_Open(&sessionHandle);
+        if (pTci == NULL)
+        {
+            ret = TEE_ERR_MEMORY;
+            break;
+        }
+
+        /* Map memory to the secure world */
+        mcRet = mcMap(&sessionHandle, (void*)keyBlob, keyBlobLength, &keyBlobInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        mcRet = mcMap(&sessionHandle, (void*)metadata, sizeof(teeKeyMeta_t), &keyDataInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_MAP;
+            break;
+        }
+
+        /* Update TCI buffer */
+        pTci->command.header.commandId        = CMD_ID_TEE_GET_KEY_INFO;
+        pTci->get_key_info.key_blob           = (uint32_t)keyBlobInfo.sVirtualAddr;
+        pTci->get_key_info.key_metadata       = (uint32_t)keyDataInfo.sVirtualAddr;
+        pTci->get_key_info.key_blob_len       = keyBlobLength;
+
+        /* Notify the trusted application */
+        mcRet = mcNotify(&sessionHandle);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        /* Wait for response from the trusted application */
+        if (MC_DRV_OK != mcWaitNotification(&sessionHandle, MC_INFINITE_TIMEOUT))
+        {
+            ret = TEE_ERR_NOTIFICATION;
+            break;
+        }
+
+        if (RET_OK != pTci->response.header.returnCode)
+        {
+            LOG_E("TEE_GetKeyInfo(): TEE Keymaster trusted application returned: 0x%.8x\n",
+                        pTci->response.header.returnCode);
+            ret = TEE_ERR_FAIL;
+            break;
+        }
+
+    } while (false);
+
+    if (keyBlobInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)keyBlob, &keyBlobInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    if (keyDataInfo.sVirtualAddr != 0)
+    {
+        mcRet = mcUnmap(&sessionHandle, (void*)metadata, &keyDataInfo);
+        if (MC_DRV_OK != mcRet)
+        {
+            ret = TEE_ERR_UNMAP;
+        }
+    }
+
+    /* Close session to the trusted application */
+    TEE_Close(&sessionHandle);
+
+    return ret;
+}
diff --git a/libkeymaster/ver0/tlcTeeKeymaster_if.h b/libkeymaster/ver0/tlcTeeKeymaster_if.h
new file mode 100644 (file)
index 0000000..fea86ea
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLCTEEKEYMASTERIF_H__
+#define __TLCTEEKEYMASTERIF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+/**
+ * Key sizes
+ */
+#define TEE_RSA_KEY_SIZE_512   512
+#define TEE_RSA_KEY_SIZE_1024  1024
+#define TEE_RSA_KEY_SIZE_2048  2048
+#define TEE_RSA_KEY_SIZE_3072  3072
+#define TEE_RSA_KEY_SIZE_4096  4096
+
+
+/* error codes */
+typedef enum
+{
+    TEE_ERR_NONE             = 0,
+    TEE_ERR_FAIL             = 1,
+    TEE_ERR_INVALID_BUFFER   = 2,
+    TEE_ERR_BUFFER_TOO_SMALL = 3,
+    TEE_ERR_NOT_IMPLEMENTED  = 4,
+    TEE_ERR_SESSION          = 5,
+    TEE_ERR_MC_DEVICE        = 6,
+    TEE_ERR_NOTIFICATION     = 7,
+    TEE_ERR_MEMORY           = 8,
+    TEE_ERR_MAP              = 9,
+    TEE_ERR_UNMAP            = 10,
+    TEE_ERR_INVALID_INPUT    = 11
+    /* more can be added as required */
+} teeResult_t;
+
+
+/* Key types */
+typedef enum
+{
+    TEE_KEYTYPE_RSA          = 1,
+    TEE_KEYTYPE_DSA          = 2,
+    TEE_KEYTYPE_ECDSA        = 3,
+    /* more can be added as required */
+} teeKeyType_t;
+
+
+/* RSA key pair types */
+typedef enum {
+    TEE_KEYPAIR_RSA       = 1,   /**< RSA public and RSA private key. */
+    TEE_KEYPAIR_RSACRT    = 2    /**< RSA public and RSA CRT private key. */
+} teeRsaKeyPairType_t;
+
+
+/* Supported RSA signature algorithms */
+typedef enum
+{
+    /* RSA */
+    TEE_RSA_NODIGEST_NOPADDING    = 1, /**< No digest and padding */
+} teeRsaSigAlg_t;
+
+
+typedef enum {
+  TEE_ECC_CURVE_NIST_P192 = 1,
+  TEE_ECC_CURVE_NIST_P224 = 2,
+  TEE_ECC_CURVE_NIST_P256 = 3,
+  TEE_ECC_CURVE_NIST_P384 = 4,
+  TEE_ECC_CURVE_NIST_P521 = 5,
+} teeEccCurveType_t;
+
+
+/**
+ * RSA private key metadata (Private modulus and exponent lengths)
+ */
+typedef struct {
+    uint32_t     lenpriexp;     /**< Private key exponent length */
+} teeRsaPrivKeyMeta_t;
+
+
+/**
+ * RSA CRT private key metadata (Private modulus and exponent lengths)
+ */
+typedef struct {
+    uint32_t     lenp;          /**< Prime p length */
+    uint32_t     lenq;          /**< Prime q length */
+    uint32_t     lendp;         /**< DP length */
+    uint32_t     lendq;         /**< DQ length */
+    uint32_t     lenqinv;       /**< QP length */
+} teeRsaCrtPrivKeyMeta_t;
+
+
+/**
+ * RSA key metadata (public key hash, key size, modulus/exponent lengths, etc..)
+ */
+typedef struct {
+    uint32_t     type;        /**< RSA key type (RSA or RSA CRT) */
+    uint32_t     keysize;       /**< Key size, e.g. 1024, 2048 */
+    uint32_t     lenpubmod;   /**< Public key modulus length */
+    uint32_t     lenpubexp;   /**< Public key exponent length */
+    union {
+        teeRsaPrivKeyMeta_t    rsapriv;       /**< RSA private key */
+        teeRsaCrtPrivKeyMeta_t rsacrtpriv; /**< RSA CRT private key */
+    };
+} teeRsaKeyMeta_t;
+
+
+/**
+ * DSA key metadata (p, q, g, x and y lengths)
+ */
+typedef struct {
+    uint32_t     pLen;        /**< q length */
+    uint32_t     qLen;        /**< q length */
+    uint32_t     gLen;        /**< Generator length */
+    uint32_t     xLen;        /**< x length */
+    uint32_t     yLen;        /**< y length */
+} teeDsaKeyMeta_t;
+
+
+/**
+ * ECDSA key metadata (x, y and private key lengths)
+ */
+typedef struct {
+    uint32_t  curve;       /**< Curve type */
+    uint32_t  curveLen;    /**< Curve length */
+} teeEcdsaKeyMeta_t;
+
+
+/**
+ * Key metadata
+ */
+typedef struct {
+    uint32_t     keytype;       /**< Key type, e.g. RSA */
+    union {
+        teeRsaKeyMeta_t    rsakey;    /**< RSA key */
+        teeDsaKeyMeta_t    dsakey;    /**< DSA key */
+        teeEcdsaKeyMeta_t  ecdsakey;  /**< ECDSA key */
+    };
+} teeKeyMeta_t;
+
+
+/**
+ * RSA public key metadata
+ */
+typedef struct {
+    uint32_t     lenpubmod;   /**< Public key modulus length */
+    uint32_t     lenpubexp;   /**< Public key exponent length */
+} teeRsaPubKeyMeta_t;
+
+
+/**
+ * DSA public key metadata (p, q, g and y lengths)
+ */
+typedef struct {
+    uint32_t     pLen;        /**< q length */
+    uint32_t     qLen;        /**< q length */
+    uint32_t     gLen;        /**< Generator length */
+    uint32_t     yLen;        /**< y length */
+} teeDsaPubKeyMeta_t;
+
+
+/**
+ * ECDSA public key metadata
+ */
+typedef struct {
+    uint32_t  curve;        /**< Curve e.g. P192, P224,..,P521*/
+} teeEcdsaPubKeyMeta_t;
+
+
+/**
+ * Public key metadata
+ */
+typedef struct {
+    uint32_t     keytype;       /**< Key type, e.g. RSA */
+    union {
+        teeRsaPubKeyMeta_t   rsakey;    /**< RSA public key */
+        teeDsaPubKeyMeta_t   dsakey;    /**< DSA public key */
+        teeEcdsaPubKeyMeta_t ecdsakey;  /**< ECDSA public key */
+    };
+} teePubKeyMeta_t;
+
+
+/**
+ * DSA parameters
+ */
+typedef struct {
+    uint8_t*      p;     /**< Prime p */
+    uint8_t*      q;     /**< Prime q */
+    uint8_t*      g;     /**< Generator */
+    uint32_t      pLen;  /**< Prime p length */
+    uint32_t      qLen;  /**< Prime q length */
+    uint32_t      gLen;  /**< Generator length */
+    uint32_t      xLen;  /**< x length */
+    uint32_t      yLen;  /**< y length */
+} teeDsaParams_t;
+
+
+/**
+ * ECDSA public key
+ */
+typedef struct {
+    uint8_t*      x;     /**< Pointer to x coordinate */
+    uint8_t*      y;     /**< Pointer to y coordinate */
+    uint32_t      xLen;  /**< x length */
+    uint32_t      yLen;  /**< y length */
+} teeEcdsaPublicKey_t;
+
+
+/**
+ * ECDSA private key
+ */
+typedef struct {
+    uint8_t*      data;   /**< Pointer to private key */
+    uint32_t      len;    /**< Private key length */
+} teeEcdsaPrivateKey_t;
+
+
+/**
+ * TEE_RSAGenerateKeyPair
+ *
+ * Generates RSA key pair and returns key pair data as wrapped object
+ *
+ * @param  keyType        [in]  Key pair type. RSA or RSACRT
+ * @param  keyData        [in]  Pointer to the key data buffer
+ * @param  keyDataLength  [in]  Key data buffer length
+ * @param  keySize        [in]  Key size
+ * @param  exponent       [in]  Exponent number
+ * @param  soLen          [out] Key data secure object length
+ */
+teeResult_t TEE_RSAGenerateKeyPair(
+    teeRsaKeyPairType_t keyType,
+    uint8_t*            keyData,
+    uint32_t            keyDataLength,
+    uint32_t            keySize,
+    uint32_t            exponent,
+    uint32_t*           soLen);
+
+
+/**
+ * TEE_RSASign
+ *
+ * Signs given plain data and returns signature data
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  plainData        [in]  Pointer to plain data to be signed
+ * @param  plainDataLength  [in]  Plain data length
+ * @param  signatureData    [out] Pointer to signature data
+ * @param  signatureDataLength  [out] Signature data length
+ * @param  algorithm        [in]  RSA signature algorithm
+ */
+teeResult_t TEE_RSASign(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  plainData,
+    const uint32_t  plainDataLength,
+    uint8_t*        signatureData,
+    uint32_t*       signatureDataLength,
+    teeRsaSigAlg_t  algorithm);
+
+
+/**
+ * TEE_RSAVerify
+ *
+ * Verifies given data with RSA public key and return status
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  plainData        [in]  Pointer to plain data to be signed
+ * @param  plainDataLength  [in]  Plain data length
+ * @param  signatureData    [in]  Pointer to signed data
+ * @param  signatureData    [in]  Plain  data length
+ * @param  algorithm        [in]  RSA signature algorithm
+ * @param  validity         [out] Signature validity
+ */
+teeResult_t TEE_RSAVerify(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  plainData,
+    const uint32_t  plainDataLength,
+    const uint8_t*  signatureData,
+    const uint32_t  signatureDataLength,
+    teeRsaSigAlg_t  algorithm,
+    bool            *validity);
+
+
+/**
+ * TEE_KeyImport
+ *
+ * Imports key data and returns key data as secure object
+ *
+ * Key data needs to be in the following format
+ *
+ * RSA key data:
+ * |--key metadata--|--public modulus--|--public exponent--|--private exponent--|
+ *
+ * RSA CRT key data:
+ * |--key metadata--|--public modulus--|--public exponent--|--P--|--Q--|--DP--|--DQ--|--Qinv--|
+ *
+ * Where:
+ * P:     secret prime factor
+ * Q:     secret prime factor
+ * DP:    d mod (p-1)
+ * DQ:    d mod (q-1)
+ * Qinv:  q^-1 mod p
+ *
+ * DSA key data:
+ * |-- Key metadata --|--p--|--q--|--g--|--y--|--private key data (x)--|
+ *
+ * Where:
+ * p:     prime (modulus)
+ * q:     sub prime
+ * g:     generator
+ * y:     public y
+ * x:     private x
+ *
+ * ECDSA key data:
+ * |-- Key metadata --|--x--|--y--|--private key data (d)--|
+ *
+ * Where:
+ * x:     affine coordinate x
+ * y:     affine coordinate y
+ * d:     private key
+ *
+ * @param  keyData          [in]  Pointer to key data
+ * @param  keyDataLength    [in]  Key data length
+ * @param  soData           [out] Pointer to wrapped key data
+ * @param  soDataLength     [out] Wrapped key data length
+ */
+teeResult_t TEE_KeyImport(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    uint8_t*        soData,
+    uint32_t*       soDataLength);
+
+
+/** * TEE_GetPubKey
+ *
+ * Retrieves public key data from wrapped key data
+ *
+ *
+ * RSA public key data:
+ * |--public key metadata--|--public modulus--|--public exponent--|
+ *
+ * DSA public key data:
+ * |-- public key metadata --|--p--|--q--|--g--|--y--|
+ *
+ * ECDSA public key data:
+ * |-- public key metadata --|--x--|--y--|
+ *
+ *
+ * @param  keyData          [in]  Pointer to key data
+ * @param  keyDataLength    [in]  Key data length
+ * @param  pubKeyData       [out] Pointer to public key data
+ * @param  pubKeyDataLength [out] Public key data length
+ */
+teeResult_t TEE_GetPubKey(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    uint8_t*        pubKeyData,
+    uint32_t*       pubKeyDataLength);
+
+
+/**
+ * TEE_DSAGenerateKeyPair
+ *
+ * Generates DSA key pair and returns key pair data as wrapped object
+ *
+ * @param  keyData        [in]  Pointer to the key data buffer
+ * @param  keyDataLength  [in]  Key data buffer length
+ * @param  params         [in]  DSA parameters
+ * @param  soLen          [out] Key data secure object length
+ */
+teeResult_t TEE_DSAGenerateKeyPair(
+    uint8_t*            keyData,
+    uint32_t            keyDataLength,
+    teeDsaParams_t      *params,
+    uint32_t*           soLen);
+
+
+/**
+ * TEE_DSASign
+ *
+ * Signs given plain data and returns signature data
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Digest data to be signed
+ * @param  digestLength     [in]  Digest data length
+ * @param  signatureData    [out] Pointer to signature data
+ * @param  signatureDataLength  [out] Signature data length
+ */
+teeResult_t TEE_DSASign(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLength,
+    uint8_t*        signatureData,
+    uint32_t*       signatureDataLength);
+
+
+/**
+ * TEE_DSAVerify
+ *
+ * Verifies given data with DSA public key and return status
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  plainData        [in]  Pointer to plain data to be signed
+ * @param  plainDataLength  [in]  Plain data length
+ * @param  signatureData    [in]  Pointer to signed data
+ * @param  signatureData    [in]  Plain  data length
+ * @param  validity         [out] Signature validity
+ */
+teeResult_t TEE_DSAVerify(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  plainData,
+    const uint32_t  plainDataLength,
+    const uint8_t*  signatureData,
+    const uint32_t  signatureDataLength,
+    bool            *validity);
+
+
+/**
+ * TEE_ECDSAGenerateKeyPair
+ *
+ * Generates ECDSA key pair and returns key pair data as wrapped object
+ *
+ * @param  keyData        [in]  Pointer to the key data buffer
+ * @param  keyDataLength  [in]  Key data buffer length
+ * @param  curveType      [in]  Curve type
+ * @param  soLen          [out] Key data secure object length
+ */
+teeResult_t TEE_ECDSAGenerateKeyPair(
+    uint8_t*            keyData,
+    uint32_t            keyDataLength,
+    teeEccCurveType_t   curveType,
+    uint32_t*           soLen);
+
+
+/**
+ * TEE_ECDSASign
+ *
+ * Signs given plain data and returns signature data
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Digest data to be signed
+ * @param  digestLength     [in]  Digest data length
+ * @param  signatureData    [out] Pointer to signature data
+ * @param  signatureDataLength  [out] Signature data length
+ */
+teeResult_t TEE_ECDSASign(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLength,
+    uint8_t*        signatureData,
+    uint32_t*       signatureDataLength);
+
+
+/**
+ * TEE_ECDSAVerify
+ *
+ * Verifies given data with ECDSA public key and return status
+ *
+ * @param  keyData          [in]  Pointer to key data buffer
+ * @param  keyDataLength    [in]  Key data buffer length
+ * @param  digest           [in]  Pointer to digest data to be verified
+ * @param  digestLen        [in]  Digest data length
+ * @param  signatureData    [in]  Pointer to signed data
+ * @param  signatureData    [in]  Plain  data length
+ * @param  validity         [out] Signature validity
+ */
+teeResult_t TEE_ECDSAVerify(
+    const uint8_t*  keyData,
+    const uint32_t  keyDataLength,
+    const uint8_t*  digest,
+    const uint32_t  digestLen,
+    const uint8_t*  signatureData,
+    const uint32_t  signatureDataLength,
+    bool            *validity);
+
+
+/**
+ * TEE_GetKeyInfo
+ *
+ * Retrieves key information (type, length,..) from key data blob and populates key metadata
+ * accordingly
+ *
+ * @param  keyBlob          [in]  Pointer to key blob data
+ * @param  keyBlobLength    [in]  Key data buffer length
+ * @param  metadata         [out] Pointer to digest data to be verified
+ */
+teeResult_t TEE_GetKeyInfo(
+    const uint8_t*  keyBlob,
+    const uint32_t  keyBlobLength,
+    teeKeyMeta_t*   metadata);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __TLCTEEKEYMASTERIF_H__
diff --git a/libkeymaster/ver1/NOTICE b/libkeymaster/ver1/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/libkeymaster/ver1/include/km_encodings.h b/libkeymaster/ver1/include/km_encodings.h
new file mode 100644 (file)
index 0000000..563181b
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __KM_ENCODINGS_H__
+#define __KM_ENCODINGS_H__
+
+#include <hardware/keymaster_defs.h>
+
+/**
+ * Decode PKCS8 data into core key data.
+ *
+ * @param[out] core_key_data buffer for metadata + raw data
+ * @param core_key_data_len length of \p core_key_data buffer
+ * @param[in,out] key_size key size in bits if known, otherwise 0 on entry, actual on exit
+ * @param[in,out] rsa_pubexp RSA public exponent if known, otherwise 0 on entry, actual on exit
+ * @param pkcs8_data PKCS8-encoded data
+ *
+ * @return KM_ERROR_OK or error
+ */
+keymaster_error_t decode_pkcs8(
+    uint8_t *core_key_data,
+    uint32_t core_key_data_len,
+    uint32_t *key_size,
+    uint64_t *rsa_pubexp,
+    const keymaster_blob_t *pkcs8_data);
+
+/**
+ * Encode public key data into X509 format.
+ *
+ * @param[out] export_data encoded public key data
+ * @param key_type key type
+ * @param key_size key size in bits
+ * @param core_pub_data core public key data (metadata + raw data)
+ * @param core_pub_data_len length of \p core_pub_data buffer
+ *
+ * @pre \p export_data points to a \p keymaster_blob_t
+ * @post on success, caller assumes ownership of \p export_data->data
+ * @post on error, no memory is allocated
+ *
+ * @return KM_ERROR_OK or error
+ */
+keymaster_error_t encode_x509(
+    keymaster_blob_t *export_data,
+    keymaster_algorithm_t key_type,
+    uint32_t key_size,
+    const uint8_t *core_pub_data,
+    uint32_t core_pub_data_len);
+
+#endif /* __KM_ENCODINGS_H__ */
diff --git a/libkeymaster/ver1/include/km_shared_util.h b/libkeymaster/ver1/include/km_shared_util.h
new file mode 100644 (file)
index 0000000..a5e2d68
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __KM_SHARED_UTIL_H__
+#define __KM_SHARED_UTIL_H__
+
+#include "hardware/keymaster_defs.h"
+
+#define BITS_TO_BYTES(n) (((n)+7)/8)
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/**
+ * Read a serialized little-endian encoding of a uint32_t.
+ *
+ * @param  pos position to read from
+ * @return     value
+ */
+uint32_t get_u32(
+    const uint8_t *pos);
+
+/**
+ * Read a serialized little-endian encoding of a uint64_t.
+ *
+ * @param  pos position to read from
+ * @return     value
+ */
+uint64_t get_u64(
+    const uint8_t *pos);
+
+/**
+ * Write a serialized little-endian encoding of a uint32_t.
+ *
+ * @param pos position to write to
+ * @param val value
+ */
+void set_u32(
+    uint8_t *pos,
+    uint32_t val);
+
+/**
+ * Write a serialized little-endian encoding of a uint64_t.
+ *
+ * @param pos position to write to
+ * @param val value
+ */
+void set_u64(
+    uint8_t *pos,
+    uint64_t val);
+
+/**
+ * Write a serialized little-endian encoding of a uint32_t and increment the
+ * position by 4 bytes.
+ *
+ * @param pos pointer to position to write to
+ * @param val value
+ */
+void set_u32_increment_pos(
+    uint8_t **pos,
+    uint32_t val);
+
+/**
+ * Write a serialized little-endian encoding of a uint64_t and increment the
+ * position by 8 bytes.
+ *
+ * @param pos pointer to position to write to
+ * @param val value
+ */
+void set_u64_increment_pos(
+    uint8_t **pos,
+    uint64_t val);
+
+/**
+ * Write data and increment position by length of data.
+ *
+ * @param pos pointer to position to write to
+ * @param src buffer to write
+ * @param len length of buffer
+ */
+void set_data_increment_pos(
+    uint8_t **pos,
+    const uint8_t *src,
+    uint32_t len);
+
+/**
+ * Set a pointer and increment position.
+ *
+ * @param ptr pointer to pointer to set
+ * @param src pointer to position to set it to
+ * @param len length by which to increment \p *src
+ */
+void set_ptr_increment_src(
+    uint8_t **ptr,
+    uint8_t **src,
+    uint32_t len);
+
+/**
+ * Check consistency of parameters.
+ * @param algorithm key type
+ * @param purpose operation purpose
+ * @return whether \p algorithm and \p purpose are consistent
+ */
+bool check_algorithm_purpose(
+    keymaster_algorithm_t algorithm,
+    keymaster_purpose_t purpose);
+
+/**
+ * Memory needed to store a set of (HW- or SW-enforced) characteristics, n32 of
+ * which are uint32_t (enum, uint, bool) and n64 of which are uint64_t (ulong,
+ * date).
+ */
+#define KM_W_CHARACTERISTICS_SIZE(n32,n64) (4 + (4 + 4)*(n32) + (4 + 8)*(n64))
+
+/* Hardware-enforced characteristics:
+ *   KM_TAG_PURPOSE, // enum, uint32_t, up to 4 of these
+ *   KM_TAG_ALGORITHM, // enum, uint32_t
+ *   KM_TAG_KEY_SIZE, // uint, uint32_t
+ *   KM_TAG_BLOCK_MODE, // enum, uint32_t, up to 4 of these
+ *   KM_TAG_DIGEST, // enum, uint32_t, up to 7 of these
+ *   KM_TAG_PADDING, // enum, uint32_t, up to 5 of these
+ *   KM_TAG_RSA_PUBLIC_EXPONENT, // ulong, uint64_t
+ *   KM_TAG_BLOB_USAGE_REQUIREMENTS, // enum, uint32_t
+ *   KM_TAG_BOOTLOADER_ONLY, // bool, uint32_t
+ *   KM_TAG_ORIGIN, // enum, uint32_t
+ *   KM_TAG_ROLLBACK_RESISTANT, // bool, uint32_t
+ *   KM_TAG_USER_SECURE_ID, // uint64_t, up to ? of these
+ *   KM_TAG_NO_AUTH_REQUIRED, // bool, uint32_t
+ *   KM_TAG_USER_AUTH_TYPE, // enum, uint32_t
+ *   KM_TAG_AUTH_TIMEOUT, // uint, uint32_t
+ *   KM_TAG_CALLER_NONCE, // bool, uint32_t
+ *   KM_TAG_MIN_MAC_LENGTH, // uint, uint32_t
+ */
+#define KM_MAX_N_USER_SECURE_ID 8 // arbitrary
+#define KM_N_HW_32 31
+#define KM_N_HW_64 (1 + KM_MAX_N_USER_SECURE_ID)
+
+/* Software-enforced characteristics: (set and enforced by keystore)
+ *   KM_TAG_ACTIVE_DATETIME, // date, uint64_t
+ *   KM_TAG_CREATION_DATETIME, // date, uint64_t
+ *   KM_TAG_MAX_USES_PER_BOOT, // uint, uint32_t
+ *   KM_TAG_MIN_SECONDS_BETWEEN_OPS, // uint, uint32_t
+ *   KM_TAG_ORIGINATION_EXPIRE_DATETIME, // date, uint64_t
+ *   KM_TAG_USAGE_EXPIRE_DATETIME, // date, uint64_t
+ */
+#define KM_N_SW_32 2
+#define KM_N_SW_64 4
+
+#define KM_N_HW_CHARACTERISTICS (KM_N_HW_32 + KM_N_HW_64)
+#define KM_N_SW_CHARACTERISTICS (KM_N_SW_32 + KM_N_SW_64)
+#define KM_HW_CHARACTERISTICS_SIZE \
+    KM_W_CHARACTERISTICS_SIZE(KM_N_HW_32, KM_N_HW_64)
+#define KM_SW_CHARACTERISTICS_SIZE  \
+    KM_W_CHARACTERISTICS_SIZE(KM_N_SW_32, KM_N_SW_64)
+
+/**
+ * Maximum amount of memory needed for serialized key characteristics.
+ */
+#define KM_CHARACTERISTICS_SIZE \
+    (KM_HW_CHARACTERISTICS_SIZE + KM_SW_CHARACTERISTICS_SIZE)
+
+/* Nuber of parameters added by default on key import or key generation */
+#define OWN_PARAMS_NB 3
+
+/* Size of an array storing default parameters */
+#define OWN_PARAMS_SIZE ( OWN_PARAMS_NB * (4+4) )  // OWN_PARAMS_NB x (tag + (enum or bool))
+
+/**
+ * Size of out_params buffer when required for begin() operation.
+ *
+ * This is enough to hold a 16-byte IV field, serialized
+ * (param_count | tag | blob_length | blob_data).
+ */
+#define TEE_BEGIN_OUT_PARAMS_SIZE (4 + 4 + 4 + 16)
+
+#endif /* __KM_SHARED_UTIL_H__ */
diff --git a/libkeymaster/ver1/include/km_util.h b/libkeymaster/ver1/include/km_util.h
new file mode 100644 (file)
index 0000000..35a19d2
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __KM_UTIL_H__
+#define __KM_UTIL_H__
+
+#include <hardware/keymaster_defs.h>
+
+#define LOG_TAG "TlcTeeKeyMaster"
+#include "log.h"
+
+/**
+ * Set \p ret to the return value of \p expr; if it is not \p KM_ERROR_OK then
+ * log the error and go to \p end,
+ */
+#define CHECK_RESULT_OK(expr) \
+    do { \
+        ret = (expr); \
+        if (ret != KM_ERROR_OK) { \
+            LOG_E("%s:%d: %s == %d", __func__, __LINE__, #expr, ret); \
+            goto end; \
+        } \
+    } while (false)
+
+#define CHECK_TRUE(errcode, expr) \
+    do { \
+        if (!(expr)) { \
+            LOG_E("%s:%d: '%s' is false\n", __func__, __LINE__, #expr); \
+            ret = (errcode); \
+            goto end; \
+        } \
+    } while (false)
+
+#define CHECK_NOT_NULL(expr) \
+    CHECK_TRUE(KM_ERROR_UNEXPECTED_NULL_POINTER, (expr) != NULL)
+
+/**
+ * Get value of enumerated tag from key parameters
+ */
+keymaster_error_t get_enumerated_tag(
+    const keymaster_key_param_set_t *params,
+    keymaster_tag_t tag,
+    uint32_t *value);
+
+/**
+ * Get value of integer tag from key parameters
+ */
+keymaster_error_t get_integer_tag(
+    const keymaster_key_param_set_t *params,
+    keymaster_tag_t tag,
+    uint32_t *value);
+
+/**
+ * Get value of long integer tag from key parameters
+ */
+keymaster_error_t get_long_integer_tag(
+    const keymaster_key_param_set_t *params,
+    keymaster_tag_t tag,
+    uint64_t *value);
+
+#endif /* __KM_UTIL_H__ */
diff --git a/libkeymaster/ver1/include/log.h b/libkeymaster/ver1/include/log.h
new file mode 100644 (file)
index 0000000..34f3e40
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** Log wrapper for Android.
+ * 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.
+ */
+#ifndef TLCWRAPPERANDROIDLOG_H_
+#define TLCWRAPPERANDROIDLOG_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#ifndef WIN32
+#include <errno.h>
+#include <unistd.h>
+#define GETPID getpid
+#else
+#include <process.h>
+#define GETPID _getpid
+#endif
+
+/** LOG_D(fmt, ...)
+ * Debug information logging, only shown in debug version
+ */
+
+/** LOG_I(fmt, ...)
+ * Important information logging
+ */
+
+/** LOG_W(fmt, ...)
+ * Warnings logging
+ */
+
+/** LOG_E(fmt, ...)
+ * Error logging
+ */
+
+/** LOG_D_BUF(szDescriptor, blob, sizeOfBlob)
+ * Binary logging, line-wise output to LOG_D
+ */
+
+#define DUMMY_FUNCTION()    do {} while(0)
+
+#ifdef LOG_ANDROID
+#include <android/log.h>
+// log to adb logcat
+#ifdef NDEBUG // no logging in debug version
+    #define LOG_D(fmt, ...) DUMMY_FUNCTION()
+#else
+    // add LINE
+    #define LOG_D(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt " [%s:%d]", ##__VA_ARGS__, __FILE__, __LINE__)
+#endif
+    #define LOG_I(fmt, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt " [%s:%d]", ##__VA_ARGS__, __FILE__, __LINE__)
+    #define LOG_W(fmt, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, fmt " [%s:%d]", ##__VA_ARGS__, __FILE__, __LINE__)
+    #define _LOG_E(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##__VA_ARGS__)
+#endif // defined(LOG_ANDROID)
+
+
+#ifdef LOG_TIZEN
+#include <dlog.h>
+#ifdef NDEBUG
+    #define LOG_D(...)  DUMMY_FUNCTION()
+#else
+    #define LOG_D(...)  SLOGD(__VA_ARGS__)
+#endif
+    #define LOG_I(...)  SLOGI(__VA_ARGS__)
+    #define LOG_W(...)  SLOGW(__VA_ARGS__)
+    #define _LOG_E(...) SLOGE(__VA_ARGS__)
+#endif // defined(LOG_TIZEN)
+
+
+#if !defined(_LOG_E)
+    // log using fprintf, by default to stdout
+#ifdef LOG_FPRINTF
+    extern FILE* mc_log_file_;
+    #define _LOG_x(_x_,...) \
+        do { \
+            fprintf(mc_log_file_, "%s/%s(%d): ",_x_,LOG_TAG,GETPID()); \
+            fprintf(mc_log_file_, __VA_ARGS__); \
+            fprintf(mc_log_file_, "\n"); \
+        } while(0)
+#else // LOG_FPRINTF
+    #define _LOG_x(_x_,...) \
+        do { \
+            printf("%s/%s(%d): ",_x_,LOG_TAG,GETPID()); \
+            printf(__VA_ARGS__); \
+            printf("\n"); \
+        } while(0)
+#endif // !LOG_FPRINTF
+
+#ifdef NDEBUG // no logging in debug version
+    #define LOG_D(fmt, ...) DUMMY_FUNCTION()
+#else
+    #define LOG_D(...)  _LOG_x("D",__VA_ARGS__)
+#endif
+    #define LOG_I(...)  _LOG_x("I",__VA_ARGS__)
+    #define LOG_W(...)  _LOG_x("W",__VA_ARGS__)
+    #define _LOG_E(...)  _LOG_x("E",__VA_ARGS__)
+#endif // !defined(_LOG_E): neither Android nor Tizen
+
+
+/** LOG_E() needs to be more prominent:
+ * Display "*********** ERROR ***********" before actual error message.
+ */
+#define LOG_E(...) \
+            do { \
+                _LOG_E("  *****************************"); \
+                _LOG_E("  *** ERROR: " __VA_ARGS__); \
+                _LOG_E("  *** Detected in %s:%u()", __FILE__, __LINE__); \
+                _LOG_E("  *****************************"); \
+            } while(0)
+
+#define LOG_ERRNO(MESSAGE) \
+    LOG_E("%s failed with \"%s\"(errno %i)", MESSAGE, strerror(errno), errno);
+
+#ifdef NDEBUG
+    #define LOG_D_BUF(...)      DUMMY_FUNCTION()
+#else
+    #define LOG_D_BUF(f, b, s)  LOG_x_BUF(f, b, s, true)
+#endif
+#define LOG_I_BUF(f, b, s)      LOG_x_BUF(f, b, s, false)
+
+#ifndef WIN32
+__attribute__ ((unused))
+#endif
+static void LOG_x_BUF(
+        const char*     szDescriptor,
+        const void*     blob,
+        size_t          sizeOfBlob,
+        bool            debug
+) {
+
+#define CPL         0x10  // chars per line
+#define OVERHEAD    20
+
+    char buffer[CPL * 4 + OVERHEAD];
+
+    int index = 0;
+
+    uint32_t moreThanOneLine = (sizeOfBlob > CPL);
+    size_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], " (%p, %zu bytes)", blob,sizeOfBlob);
+        LOG_D("%s", buffer);
+        index = 0;
+    }
+    else if (NULL == szDescriptor)
+    {
+        index += sprintf(&buffer[index], "Data at %p: ", blob);
+    }
+
+    if(sizeOfBlob == 0) {
+        LOG_D("%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 unsigned 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
+            if (debug) {
+                LOG_D("%s", buffer);
+            } else {
+                LOG_I("%s", buffer);
+            }
+            index = 0;
+        }
+    }
+}
+
+#endif /** TLCWRAPPERANDROIDLOG_H_ */
diff --git a/libkeymaster/ver1/include/module.h b/libkeymaster/ver1/include/module.h
new file mode 100644 (file)
index 0000000..09b389b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _module_H_
+#define _module_H_
+
+#define KEYMASTER_HARDWARE_MODULE_TEE_NAME "Keymaster TEE HAL"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------------------------------------------------------
+   That's the only function used by module.c. Name of this function must
+   not be mangled when compiled by C++ compiler.
+   -------------------------------------------------------------------------*/
+int kinibi_keymaster_open(const struct hw_module_t* module, const char* id,
+            struct hw_device_t** device);
+
+int kinibi_keymaster_close(hw_device_t *hw);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _tee_gatekeeper_device_ */
diff --git a/libkeymaster/ver1/include/serialization.h b/libkeymaster/ver1/include/serialization.h
new file mode 100644 (file)
index 0000000..5dc9597
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SERIALIZATION_H__
+#define __SERIALIZATION_H__
+
+#include <hardware/keymaster_defs.h>
+#include "km_shared_util.h"
+
+/**
+ * Serialize key parameters.
+ *
+ * The format of the returned buffer is
+ *
+ * n (uint32_t) | param_1 (pbuf) | ... | param_n (pbuf)
+ *
+ * where a 'pbuf' is
+ *
+ * tag (uint32_t <= keymaster_tag_t) | val
+ *
+ * where 'val' is
+ *
+ * int_type OR bool_type OR longint_type OR blob_type
+ *
+ * where
+ *
+ * int_type = uint32_t
+ * bool_type = uint32_t (value 0 or 1)
+ * longint_type = uint64_t
+ * blob_type = K | byte_1 (uint8_t) | ... | byte_K (uint8_t)
+ *
+ * \param[out] buf serialized parameters
+ * \param[out] buflen length of \p buf
+ * \param params set of parameters to serialize
+ * \param add_time if true, add KM_TAG_CREATION_DATETIME parameter
+ * \param key_size if non-zero and KM_TAG_KEY_SIZE not present in params, add it
+ * \param rsa_pubexp if non-zero and KM_TAG_RSA_PUBLIC_EXPONENT not present in params, add it
+ *
+ * \post On error, no memory is allocated and *buf == NULL.
+ *
+ * \return KM_ERROR_OK or error
+ */
+keymaster_error_t km_serialize_params(
+    uint8_t **buf,
+    uint32_t *buflen,
+    const keymaster_key_param_set_t *params,
+    bool add_time,
+    uint32_t key_size,
+    uint64_t rsa_pubexp);
+
+/**
+ * Deserialize a parameter set.
+ *
+ * @param[out] param_set patameter set
+ * @param[in,out] pos pointer to current position in buffer
+ * @param[in,out] remain length of buffer remaining
+ *
+ * @return KM_ERROR_OK or error
+ */
+keymaster_error_t deserialize_param_set(
+    keymaster_key_param_set_t *param_set,
+    uint8_t **pos,
+    uint32_t *remain);
+
+/**
+ * Deserialize key characteristics.
+ *
+ * This function allocates memory in \p characteristics, which the caller should
+ * free using keymaster_free_characteristics().
+ *
+ * The expected format of the serialized characteristics is
+ *
+ * hw_enforced (params) | sw_enforced (params)
+ *
+ * where 'params' is serialized as for \p km_serialize_params().
+ *
+ * \param[out] characteristics deserialized characteristics
+ * \param buffer serialized key characteristics
+ * \param buffer_length length of buffer
+ *
+ * \return KM_ERROR_OK or error
+ */
+keymaster_error_t km_deserialize_characteristics(
+    keymaster_key_characteristics_t *characteristics,
+    const uint8_t *buffer,
+    uint32_t buffer_length);
+
+#endif /* __SERIALIZATION_H__ */
diff --git a/libkeymaster/ver1/include/tci.h b/libkeymaster/ver1/include/tci.h
new file mode 100644 (file)
index 0000000..abeadb4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TCI_H__
+#define __TCI_H__
+
+typedef uint32_t tciCommandId_t;
+typedef uint32_t tciResponseId_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)
+
+/**
+ * TCI command header.
+ */
+typedef struct{
+    tciCommandId_t commandId; /**< Command ID */
+} tciCommandHeader_t;
+
+/**
+ * TCI response header.
+ */
+typedef struct{
+    tciResponseId_t     responseId; /**< Response ID (must be command ID | RSP_ID_MASK )*/
+    uint32_t            returnCode; /**< Return code of command (keymaster_error_t) */
+} tciResponseHeader_t;
+
+#endif // __TCI_H__
diff --git a/libkeymaster/ver1/include/tee_keymaster_device.h b/libkeymaster/ver1/include/tee_keymaster_device.h
new file mode 100644 (file)
index 0000000..d32878d
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEE_KEYMASTER_DEVICE_H_
+#define TEE_KEYMASTER_DEVICE_H_
+
+#include <stdlib.h>
+
+#include <hardware/keymaster1.h>
+
+#include <UniquePtr.h>
+
+
+class TrustonicTeeKeymasterImpl;
+
+
+/**
+ * TEE based Keymaster implementation.
+ *
+ * IMPORTANT MAINTAINER NOTE: Pointers to instances of this class must be castable to hw_device_t
+ * and keymaster_device. This means it must remain a standard layout class (no virtual functions and
+ * no data members which aren't standard layout), and device_ must be the first data member.
+ * Assertions in the constructor validate compliance with those constraints.
+ */
+class TeeKeymasterDevice {
+  public:
+    TeeKeymasterDevice(hw_module_t* module);
+
+    hw_device_t* hw_device();
+    keymaster1_device_t* keymaster_device();
+
+    /*
+     * These static methods are the functions referenced through the function pointers in
+     * keymaster_device.
+     */
+
+    // Version 0.4 APIs.
+    static keymaster_error_t get_supported_algorithms(
+                        const keymaster1_device_t*      dev,
+                        keymaster_algorithm_t**         algorithms,
+                        size_t*                         algorithms_length);
+
+    static keymaster_error_t get_supported_block_modes(
+                        const keymaster1_device_t*      dev,
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_purpose_t             purpose,
+                        keymaster_block_mode_t**        modes,
+                        size_t*                         modes_length);
+
+    static keymaster_error_t get_supported_padding_modes(
+                        const keymaster1_device_t*      dev,
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_purpose_t             purpose,
+                        keymaster_padding_t**           modes,
+                        size_t*                         modes_length);
+
+    static keymaster_error_t get_supported_digests(
+                        const keymaster1_device_t*      dev,
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_purpose_t             purpose,
+                        keymaster_digest_t**            digests,
+                        size_t*                         digests_length);
+
+    static keymaster_error_t get_supported_import_formats(
+                        const keymaster1_device_t*      dev,
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_key_format_t**        formats,
+                        size_t*                         formats_length);
+
+    static keymaster_error_t get_supported_export_formats(
+                        const keymaster1_device_t*      dev,
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_key_format_t**        formats,
+                        size_t*                         formats_length);
+
+    static keymaster_error_t add_rng_entropy(
+                        const keymaster1_device_t*      dev,
+                        const uint8_t*                  data,
+                        size_t                          data_length);
+
+    static keymaster_error_t generate_key(
+                        const keymaster1_device_t*      dev,
+                        const keymaster_key_param_set_t* params,
+                        keymaster_key_blob_t*           key_blob,
+                        keymaster_key_characteristics_t** characteristics);
+
+    static keymaster_error_t get_key_characteristics(
+                        const keymaster1_device_t*      dev,
+                        const keymaster_key_blob_t*     key_blob,
+                        const keymaster_blob_t*         client_id,
+                        const keymaster_blob_t*         app_data,
+                        keymaster_key_characteristics_t** character);
+
+    static keymaster_error_t import_key(
+                        const keymaster1_device_t*      dev,
+                        const keymaster_key_param_set_t* params,
+                        keymaster_key_format_t          key_format,
+                        const keymaster_blob_t*         key_data,
+                        keymaster_key_blob_t*           key_blob,
+                        keymaster_key_characteristics_t** characteristics);
+
+    static keymaster_error_t export_key(
+                        const keymaster1_device_t*      dev,
+                        keymaster_key_format_t          export_format,
+                        const keymaster_key_blob_t*     key_to_export,
+                        const keymaster_blob_t*         client_id,
+                        const keymaster_blob_t*         app_data,
+                        keymaster_blob_t*               export_data);
+
+    static keymaster_error_t begin(
+                        const keymaster1_device_t*      dev,
+                        keymaster_purpose_t             purpose,
+                        const keymaster_key_blob_t*     key,
+                        const keymaster_key_param_set_t* params,
+                        keymaster_key_param_set_t*      out_params,
+                        keymaster_operation_handle_t*   operation_handle);
+
+    static keymaster_error_t update(
+                        const keymaster1_device_t*      dev,
+                        keymaster_operation_handle_t    operation_handle,
+                        const keymaster_key_param_set_t* params,
+                        const keymaster_blob_t*         input,
+                        size_t*                         input_consumed,
+                        keymaster_key_param_set_t*      out_params,
+                        keymaster_blob_t*               output);
+
+    static keymaster_error_t finish(
+                        const keymaster1_device_t*      dev,
+                        keymaster_operation_handle_t    operation_handle,
+                        const keymaster_key_param_set_t* params,
+                        const keymaster_blob_t*         signature,
+                        keymaster_key_param_set_t*      out_params,
+                        keymaster_blob_t*               output);
+
+    static keymaster_error_t abort(
+                        const keymaster1_device_t*      dev,
+                        keymaster_operation_handle_t    operation_handle);
+
+  private:
+
+    // Class is non-copyable and not default-constructible
+    TeeKeymasterDevice();
+    TeeKeymasterDevice(const TeeKeymasterDevice&);
+    TeeKeymasterDevice& operator=(const TeeKeymasterDevice&);
+
+    keymaster1_device_t                   device_;
+    UniquePtr<TrustonicTeeKeymasterImpl>  impl_;
+};
+
+#endif  // TEE_KEYMASTER_DEVICE_H_
diff --git a/libkeymaster/ver1/include/tlTeeKeymaster_Api.h b/libkeymaster/ver1/include/tlTeeKeymaster_Api.h
new file mode 100644 (file)
index 0000000..adcd5fa
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLTEEKEYMASTER_API_H__
+#define __TLTEEKEYMASTER_API_H__
+
+#include "tci.h"
+#include "hardware/keymaster_defs.h"
+
+
+
+/**
+ * Command ID's
+ */
+#define CMD_ID_TEE_ADD_RNG_ENTROPY         0x01
+#define CMD_ID_TEE_GENERATE_KEY            0x02
+#define CMD_ID_TEE_GET_KEY_CHARACTERISTICS 0x03
+#define CMD_ID_TEE_IMPORT_KEY              0x04
+#define CMD_ID_TEE_EXPORT_KEY              0x05
+#define CMD_ID_TEE_BEGIN                   0x06
+#define CMD_ID_TEE_UPDATE                  0x07
+#define CMD_ID_TEE_FINISH                  0x08
+#define CMD_ID_TEE_ABORT                   0x09
+// for internal use:
+#define CMD_ID_TEE_GET_KEY_INFO          0x0101
+#define CMD_ID_TEE_GET_OPERATION_INFO    0x0102
+/* ... add more command ids when needed */
+
+/*
++ KEY FORMATS
+
+We define here the serialized key formats used in the code.
+
+All uint32_t are serialized in little-endian format.
+
+++ Key Blob
+
+This is the 'key_material' part of a keymaster_key_blob_t:
+
+- key_blob = IV (16 bytes) | ciphertext | tag (16 bytes)
+
+where 'ciphertext' is the AES-GCM encryption of the key material (defined next),
+'IV' is the initialization vector and 'tag' is the authentication tag.
+
+++ Key Material
+
+This comprises:
+
+- key_material = params_len (4 bytes) | params | key_data
+
+where 'params_len' is a uint32_t representing the length of 'params', 'params'
+is the serialized representation of the Keymaster key parameters (see
+serialization.h for documentation of this), and 'key_data' is defined next.
+
+++ Key Data
+
+This comprises:
+
+- key_data = key_type | key_size | core_key_data
+
+where 'key_type' is a uint32_t corresponding to a keymaster_algorithm_t,
+'key_size' is a uint32_t representing the key size in bits (the exact meaning
+of 'key size' being key-type-dependent), and 'core_key_data' is defined next.
+
+++ Core Key Data
+
+This comprises:
+
+- core_key_data = key_metadata | raw_key_data
+
+where 'key_metadata' and 'raw_key_data' are defined below.
+
+++ Key Metadata
+
+This is key-type-dependent.
+
+For AES and HMAC keys, it is empty.
+
+For RSA keys, it comprises:
+
+- rsa_metadata = keysize(bits) | n_len | e_len | d_len | p_len | q_len | dp_len | dq_len | qinv_len
+
+where all lengths are uint32_t and (except for keysize) measured in bytes.
+
+For exported RSA public keys, it comprises:
+
+- rsa_pub_metadata = keysize(bits) | n_len | e_len
+
+For EC keys, it comprises:
+
+- ec_metadata = curve | x_len | y_len | d_len
+
+where these are all uint32_t, 'curve' represents curve type and lengths are in
+bytes.
+
+For exported EC public keys, it comprises:
+
+- ec_pub_metadata = curve | x_len | y_len
+
+++ Raw Key Data
+
+This is key-type-dependent.
+
+For AES and HMAC keys, it comprises the key bytes.
+
+For RSA keys, it comprises:
+
+- n | e | d | p | q | dp | dq | qinv
+
+with lengths as specified in the key metadata, and all numbers big-endian.
+
+For exported RSA public keys, it comprises:
+
+- n | e
+
+For EC keys, it comprises:
+
+- x | y | d
+
+with lengths as specified in the key metadata, and all numbers big-endian.
+
+For exported EC public keys, it comprises:
+
+- x | y
+*/
+
+#define KM_RSA_METADATA_SIZE (9*4)
+#define KM_EC_METADATA_SIZE (4*4)
+
+typedef struct {
+    uint32_t data; /**< secure address */
+    uint32_t data_length; /**< data length */
+} data_blob_t;
+
+/**
+ * Command message.
+ *
+ * @param len Length of the data to process.
+ * @param data Data to be processed
+ */
+typedef struct {
+    tciCommandHeader_t header; /**< Command header */
+    uint32_t len; /**< Length of data to process */
+} command_t;
+
+
+/**
+ * Response structure
+ */
+typedef struct {
+    tciResponseHeader_t header; /**< Response header */
+    uint32_t len;
+} response_t;
+
+
+/**
+ * add_rng_entropy data structure
+ */
+typedef struct {
+    data_blob_t rng_data; /**< [in] random data to be mixed in */
+} add_rng_entropy_t;
+
+
+/**
+ * generate_key data structure
+ */
+typedef struct {
+    data_blob_t params; /**< [in] serialized */
+    data_blob_t key_blob; /**< [out] keymaster_key_blob_t */
+    data_blob_t characteristics; /**< [out] serialized */
+} generate_key_t;
+
+
+/**
+ * get_key_characteristics data structure
+ */
+typedef struct {
+    data_blob_t key_blob; /**< [in] keymaster_key_blob_t */
+    data_blob_t client_id; /**< [in] */
+    data_blob_t app_data; /**< [in] */
+    data_blob_t characteristics; /**< [out] serialized */
+} get_key_characteristics_t;
+
+
+/**
+ * import_key data structure
+ */
+typedef struct {
+    data_blob_t params; /**< [in] serialized */
+    data_blob_t key_data; /**< [in] km_key_data */
+    data_blob_t key_blob; /**< [out] keymaster_key_blob_t */
+    data_blob_t characteristics; /**< [out] serialized */
+} import_key_t;
+
+
+/**
+ * export_key data structure
+ */
+typedef struct {
+    data_blob_t key_blob; /**< [in] keymaster_key_blob_t */
+    data_blob_t client_id; /**< [in] */
+    data_blob_t app_data; /**< [in] */
+    data_blob_t key_data; /**< [out] km_key_data */
+} export_key_t;
+
+
+/**
+ * begin data structure
+ */
+typedef struct {
+    keymaster_operation_handle_t handle; /**< [out] */
+    keymaster_purpose_t purpose; /**< [in] */
+    data_blob_t params; /**< [in] serialized */
+    data_blob_t key_blob; /**< [in] keymaster_key_blob_t */
+    data_blob_t out_params; /**< [out] serialized */
+    uint8_t RFU_padding[4];
+} begin_t;
+
+
+/**
+ * update data structure
+ */
+typedef struct {
+    keymaster_operation_handle_t handle; /**< [in] */
+    data_blob_t params; /**< [in] serialized */
+    data_blob_t input; /**< [in] */
+    uint32_t input_consumed; /**< [out] */
+    uint8_t RFU_padding[4];
+    data_blob_t output; /**< [out] */
+} update_t;
+
+
+/**
+ * finish data structure
+ */
+typedef struct {
+    keymaster_operation_handle_t handle; /**< [in] */
+    data_blob_t params; /**< [in] serialized */
+    data_blob_t signature; /**< [in] */
+    data_blob_t output; /**< [out] */
+} finish_t;
+
+
+/**
+ * abort structure
+ */
+typedef struct {
+    keymaster_operation_handle_t handle; /**< [in] */
+} abort_t;
+
+
+/**
+ * get_key_info data structure
+ */
+typedef struct {
+    data_blob_t key_blob; /**< [in] keymaster_key_blob_t */
+    keymaster_algorithm_t key_type; /**< [out] */
+    uint32_t key_size; /**< [out] bits */
+} get_key_info_t;
+
+
+/**
+ * get_operation_info data structure
+ */
+typedef struct {
+    keymaster_operation_handle_t handle; /**< [in] */
+    keymaster_algorithm_t algorithm; /**< [out] key type of operation */
+    uint32_t data_length; /**< [out] upper bound for length in bytes of output from finish() */
+} get_operation_info_t;
+
+
+/**
+ * TCI message data.
+ */
+typedef struct {
+    union {
+        command_t command;
+        response_t response;
+    };
+
+    uint8_t RFU_padding[4];
+    union {
+        add_rng_entropy_t   add_rng_entropy;
+        generate_key_t      generate_key;
+        get_key_characteristics_t get_key_characteristics;
+        import_key_t        import_key;
+        export_key_t        export_key;
+        begin_t             begin;
+        update_t            update;
+        finish_t            finish;
+        abort_t             abort;
+        get_key_info_t      get_key_info;
+        get_operation_info_t get_operation_info;
+    };
+} tciMessage_t, *tciMessage_ptr;
+
+
+/**
+ * Overall TCI structure.
+ */
+typedef struct {
+    tciMessage_t message; /**< TCI message */
+} tci_t;
+
+
+/**
+ * Trustlet UUID
+ */
+#define TEE_KEYMASTER_M_TA_UUID { { 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4D } }
+
+
+#endif // __TLTEEKEYMASTER_API_H__
diff --git a/libkeymaster/ver1/include/tlcTeeKeymasterM_if.h b/libkeymaster/ver1/include/tlcTeeKeymasterM_if.h
new file mode 100644 (file)
index 0000000..ec61383
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLCTEEKEYMASTERM_IF_H__
+#define __TLCTEEKEYMASTERM_IF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef void *TEE_SessionHandle;
+
+/**
+ * Open session to the TEE Keymaster trusted application
+ *
+ * @param  pSessionHandle  [out] Return pointer to the session handle
+ */
+keymaster_error_t TEE_Open(
+    TEE_SessionHandle                 *sessionHandle);
+
+/**
+ * Close session to the TEE Keymaster trusted application
+ *
+ * @param  sessionHandle  [in] Session handle
+ */
+void TEE_Close(
+    TEE_SessionHandle                 sessionHandle);
+
+keymaster_error_t TEE_AddRngEntropy(
+    TEE_SessionHandle                 session_handle,
+    const uint8_t*                    data,
+    uint32_t                          dataLength);
+
+keymaster_error_t TEE_GenerateKey(
+    TEE_SessionHandle                 session_handle,
+    const keymaster_key_param_set_t*  params,
+    keymaster_key_blob_t*             key_blob,
+    keymaster_key_characteristics_t** characteristics);
+
+keymaster_error_t TEE_GetKeyCharacteristics(
+    TEE_SessionHandle                 session_handle,
+    const keymaster_key_blob_t*       key_blob,
+    const keymaster_blob_t*           client_id,
+    const keymaster_blob_t*           app_data,
+    keymaster_key_characteristics_t** characteristics);
+
+keymaster_error_t TEE_ImportKey(
+    TEE_SessionHandle                 session_handle,
+    const keymaster_key_param_set_t*  params,
+    keymaster_key_format_t            key_format,
+    const keymaster_blob_t*           key_data,
+    keymaster_key_blob_t*             key_blob,
+    keymaster_key_characteristics_t** characteristics);
+
+keymaster_error_t TEE_ExportKey(
+    TEE_SessionHandle                 session_handle,
+    keymaster_key_format_t            export_format,
+    const keymaster_key_blob_t*       key_to_export,
+    const keymaster_blob_t*           client_id,
+    const keymaster_blob_t*           app_data,
+    keymaster_blob_t*                 export_data);
+
+keymaster_error_t TEE_Begin(
+    TEE_SessionHandle                 session_handle,
+    keymaster_purpose_t               purpose,
+    const keymaster_key_blob_t*       key,
+    const keymaster_key_param_set_t*  params,
+    keymaster_key_param_set_t*        out_params,
+    keymaster_operation_handle_t*     operation_handle);
+
+keymaster_error_t TEE_Update(
+    TEE_SessionHandle                session_handle,
+    keymaster_operation_handle_t      operation_handle,
+    const keymaster_key_param_set_t*  params,
+    const keymaster_blob_t*           input,
+    size_t*                           input_consumed,
+    keymaster_key_param_set_t*        out_params,
+    keymaster_blob_t*                 output);
+
+keymaster_error_t TEE_Finish(
+    TEE_SessionHandle                 session_handle,
+    keymaster_operation_handle_t      operation_handle,
+    const keymaster_key_param_set_t*  params,
+    const keymaster_blob_t*           signature,
+    keymaster_key_param_set_t*        out_params,
+    keymaster_blob_t*                 output);
+
+keymaster_error_t TEE_Abort(
+    TEE_SessionHandle                 session_handle,
+    keymaster_operation_handle_t      operation_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TLCTEEKEYMASTERM_IF_H__ */
diff --git a/libkeymaster/ver1/include/trustonic_tee_keymaster_impl.h b/libkeymaster/ver1/include/trustonic_tee_keymaster_impl.h
new file mode 100644 (file)
index 0000000..789b715
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TRUSTONIC_TEE_KEYMASTER_IMPL_H_
+#define TRUSTONIC_TEE_KEYMASTER_IMPL_H_
+
+#include "tlcTeeKeymasterM_if.h"
+
+class TrustonicTeeKeymasterImpl {
+  public:
+    TrustonicTeeKeymasterImpl();
+
+    ~TrustonicTeeKeymasterImpl();
+
+    keymaster_error_t get_supported_algorithms(
+                        keymaster_algorithm_t**         algorithms,
+                        size_t*                         algorithms_length);
+
+    keymaster_error_t get_supported_block_modes(
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_purpose_t             purpose,
+                        keymaster_block_mode_t**        modes,
+                        size_t*                         modes_length);
+
+    keymaster_error_t get_supported_padding_modes(
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_purpose_t             purpose,
+                        keymaster_padding_t**           modes,
+                        size_t*                         modes_length);
+
+    keymaster_error_t get_supported_digests(
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_purpose_t             purpose,
+                        keymaster_digest_t**            digests,
+                        size_t*                         digests_length);
+
+    keymaster_error_t get_supported_import_formats(
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_key_format_t**        formats,
+                        size_t*                         formats_length);
+
+    keymaster_error_t get_supported_export_formats(
+                        keymaster_algorithm_t           algorithm,
+                        keymaster_key_format_t**        formats,
+                        size_t*                         formats_length);
+
+    keymaster_error_t add_rng_entropy(
+                        const uint8_t*                  data,
+                        size_t                          data_length);
+
+    keymaster_error_t generate_key(
+                        const keymaster_key_param_set_t* params,
+                        keymaster_key_blob_t*           key_blob,
+                        keymaster_key_characteristics_t** characteristics);
+
+    keymaster_error_t get_key_characteristics(
+                        const keymaster_key_blob_t*     key_blob,
+                        const keymaster_blob_t*         client_id,
+                        const keymaster_blob_t*         app_data,
+                        keymaster_key_characteristics_t** character);
+
+    keymaster_error_t import_key(
+                        const keymaster_key_param_set_t* params,
+                        keymaster_key_format_t          key_format,
+                        const keymaster_blob_t*         key_data,
+                        keymaster_key_blob_t*           key_blob,
+                        keymaster_key_characteristics_t** characteristics);
+
+    keymaster_error_t export_key(
+                        keymaster_key_format_t          export_format,
+                        const keymaster_key_blob_t*     key_to_export,
+                        const keymaster_blob_t*         client_id,
+                        const keymaster_blob_t*         app_data,
+                        keymaster_blob_t*               export_data);
+
+    keymaster_error_t begin(
+                        keymaster_purpose_t             purpose,
+                        const keymaster_key_blob_t*     key,
+                        const keymaster_key_param_set_t* params,
+                        keymaster_key_param_set_t*      out_params,
+                        keymaster_operation_handle_t*   operation_handle);
+
+    keymaster_error_t update(
+                        keymaster_operation_handle_t    operation_handle,
+                        const keymaster_key_param_set_t* params,
+                        const keymaster_blob_t*         input,
+                        size_t*                         input_consumed,
+                        keymaster_key_param_set_t*      out_params,
+                        keymaster_blob_t*               output);
+
+    keymaster_error_t finish(
+                        keymaster_operation_handle_t    operation_handle,
+                        const keymaster_key_param_set_t* params,
+                        const keymaster_blob_t*         signature,
+                        keymaster_key_param_set_t*      out_params,
+                        keymaster_blob_t*               output);
+
+    keymaster_error_t abort(
+                        keymaster_operation_handle_t    operation_handle);
+
+    TEE_SessionHandle session_handle_;
+
+};
+
+
+#endif  //  TRUSTONIC_TEE_KEYMASTER_IMPL_H_
diff --git a/libkeymaster/ver1/src/buildTag.h b/libkeymaster/ver1/src/buildTag.h
new file mode 100644 (file)
index 0000000..dc1eab0
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICORE_COMPONENT_BUILD_TAG
+#define MOBICORE_COMPONENT_BUILD_TAG \
+       "t-base-EXYNOS64-Android-310B-V005-20151221_084810_68"
+#endif
diff --git a/libkeymaster/ver1/src/km_encodings.cpp b/libkeymaster/ver1/src/km_encodings.cpp
new file mode 100644 (file)
index 0000000..e07b431
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hardware/keymaster_defs.h>
+#include <openssl/x509.h>
+#include "km_encodings.h"
+#include "tlTeeKeymaster_Api.h"
+#include "km_shared_util.h"
+#include "km_util.h"
+#include <assert.h>
+
+/**
+ * Supported ECC curve types (from TlApiCrypto.h)
+ */
+#define ECC_CURVE_NIST_P192 1
+#define ECC_CURVE_NIST_P224 2
+#define ECC_CURVE_NIST_P256 3
+#define ECC_CURVE_NIST_P384 4
+#define ECC_CURVE_NIST_P521 5
+
+static keymaster_error_t get_curve(
+    uint32_t *curve,
+    int nid)
+{
+    assert(curve != NULL);
+
+    switch (nid) {
+        case NID_X9_62_prime192v1:
+            *curve = ECC_CURVE_NIST_P192;
+            break;
+        case NID_secp224r1:
+            *curve = ECC_CURVE_NIST_P224;
+            break;
+        case NID_X9_62_prime256v1:
+            *curve = ECC_CURVE_NIST_P256;
+            break;
+        case NID_secp384r1:
+            *curve = ECC_CURVE_NIST_P384;
+            break;
+        case NID_secp521r1:
+            *curve = ECC_CURVE_NIST_P521;
+            break;
+        default:
+            return KM_ERROR_INVALID_KEY_BLOB;
+    }
+
+    return KM_ERROR_OK;
+}
+
+static keymaster_error_t get_nid(
+    int *nid,
+    uint32_t curve)
+{
+    assert(nid != NULL);
+
+    switch (curve) {
+        case ECC_CURVE_NIST_P192:
+            *nid = NID_X9_62_prime192v1;
+            break;
+        case ECC_CURVE_NIST_P224:
+            *nid = NID_secp224r1;
+            break;
+        case ECC_CURVE_NIST_P256:
+            *nid = NID_X9_62_prime256v1;
+            break;
+        case ECC_CURVE_NIST_P384:
+            *nid = NID_secp384r1;
+            break;
+        case ECC_CURVE_NIST_P521:
+            *nid = NID_secp521r1;
+            break;
+        default:
+            return KM_ERROR_INVALID_KEY_BLOB;
+    }
+
+    return KM_ERROR_OK;
+}
+
+static uint32_t get_bitlen(
+    uint32_t curve)
+{
+    switch (curve) {
+        case ECC_CURVE_NIST_P192:
+            return 192;
+        case ECC_CURVE_NIST_P224:
+            return 224;
+        case ECC_CURVE_NIST_P256:
+            return 256;
+        case ECC_CURVE_NIST_P384:
+            return 384;
+        case ECC_CURVE_NIST_P521:
+            return 521;
+        default:
+            return 0;
+    }
+}
+
+/**
+ * Decode a PKCS8-encoded EC key
+ *
+ * @param[out] core_key_data buffer for metadata + raw key data
+ * @param core_key_data_len length of \p core_key_data buffer
+ * @param[in,out] key_size key size in bits if known, otherwise 0 on entry, actual on exit
+ * @param pkey key
+ *
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t decode_pkcs8_ec_key(
+    uint8_t *core_key_data,
+    uint32_t core_key_data_len,
+    uint32_t *key_size,
+    const EVP_PKEY *pkey)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    const EC_POINT *pubkey = NULL;
+    const EC_GROUP *ec_group = NULL;
+    BIGNUM *x_bn = NULL;
+    BIGNUM *y_bn = NULL;
+    const BIGNUM *d_bn;
+    uint32_t x_len, y_len, d_len, curve_len;
+    uint8_t *key_metadata;
+    uint8_t *raw_key_data;
+    uint8_t *pos;
+    uint32_t curve;
+    uint32_t actual_key_size;
+
+    assert(key_size != NULL);
+
+    const EC_KEY *eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY*)pkey);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        eckey != NULL);
+
+    pubkey = EC_KEY_get0_public_key(eckey);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        pubkey != NULL);
+
+    ec_group = EC_KEY_get0_group(eckey);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        ec_group != NULL);
+
+    CHECK_RESULT_OK(get_curve(&curve, EC_GROUP_get_curve_name(ec_group)));
+
+    /* Set key size, and check consistency with import_key() params. */
+    actual_key_size = get_bitlen(curve);
+    if (*key_size == 0) {
+        *key_size = actual_key_size;
+    } else {
+        CHECK_TRUE(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+            *key_size == actual_key_size);
+    }
+
+    curve_len = BITS_TO_BYTES(actual_key_size);
+    CHECK_TRUE(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+        core_key_data_len >= KM_EC_METADATA_SIZE + 3 * curve_len);
+
+    x_bn = BN_new();
+    y_bn = BN_new();
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        (x_bn != NULL) && (y_bn != NULL));
+
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        EC_POINT_get_affine_coordinates_GFp(ec_group, pubkey, x_bn, y_bn, NULL));
+
+    d_bn = EC_KEY_get0_private_key(eckey);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        d_bn != NULL);
+
+    x_len = BN_num_bytes(x_bn);
+    y_len = BN_num_bytes(y_bn);
+    d_len = BN_num_bytes(d_bn);
+
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        (x_len <= curve_len) && (y_len <= curve_len) && (d_len <= curve_len));
+
+    key_metadata = core_key_data;
+    raw_key_data = key_metadata + KM_EC_METADATA_SIZE;
+
+    /* Some versions of Kinibi require all lengths to match the curve length.
+     * Arrange for it to be so by zero-padding.
+     */
+
+    pos = key_metadata;
+    set_u32_increment_pos(&pos, curve);
+    set_u32_increment_pos(&pos, curve_len);
+    set_u32_increment_pos(&pos, curve_len);
+    set_u32_increment_pos(&pos, curve_len);
+
+    memset(raw_key_data, 0, curve_len - x_len);
+    BN_bn2bin(x_bn, raw_key_data + curve_len - x_len);
+    memset(raw_key_data + curve_len, 0, curve_len - y_len);
+    BN_bn2bin(y_bn, raw_key_data + 2 * curve_len - y_len);
+    memset(raw_key_data + 2 * curve_len, 0, curve_len - d_len);
+    BN_bn2bin(d_bn, raw_key_data + 3 * curve_len - d_len);
+
+end:
+    BN_free(x_bn);
+    BN_free(y_bn);
+    EC_KEY_free((EC_KEY*)eckey);
+
+    return ret;
+}
+
+/**
+ * Decode a PKCS8-encoded RSA key.
+ *
+ * @param[out] core_key_data buffer for metadata + raw key data
+ * @param core_key_data_len length of \p core_key_data buffer
+ * @param[in,out] key_size key size in bits if known, otherwise 0 on entry, actual on exit
+ * @param[in,out] rsa_pubexp RSA public exponent if known, otherwise 0 on entry, actual on exit
+ * @param pkey key
+ *
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t decode_pkcs8_rsa_key(
+    uint8_t *core_key_data,
+    uint32_t core_key_data_len,
+    uint32_t *key_size,
+    uint64_t *rsa_pubexp,
+    const EVP_PKEY *pkey)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    RSA *rsa = NULL;
+    uint32_t n_len, e_len, d_len, p_len, q_len, dp_len, dq_len, qinv_len;
+    size_t offset;
+    uint8_t *key_metadata;
+    uint8_t *raw_key_data;
+    uint8_t *pos;
+    uint32_t actual_key_size;
+    uint64_t actual_rsa_pubexp;
+
+    CHECK_NOT_NULL(key_size);
+    CHECK_NOT_NULL(rsa_pubexp);
+
+    rsa = EVP_PKEY_get1_RSA((EVP_PKEY*)pkey);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        rsa != NULL);
+
+    n_len = BN_num_bytes(rsa->n);
+    e_len = BN_num_bytes(rsa->e);
+    d_len = BN_num_bytes(rsa->d);
+    p_len = BN_num_bytes(rsa->p);
+    q_len = BN_num_bytes(rsa->q);
+    dp_len = BN_num_bytes(rsa->dmp1);
+    dq_len = BN_num_bytes(rsa->dmq1);
+    qinv_len = BN_num_bytes(rsa->iqmp);
+
+    CHECK_TRUE(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+        core_key_data_len >= KM_RSA_METADATA_SIZE
+            + n_len + e_len + d_len + p_len + q_len + dp_len + dq_len + qinv_len);
+
+    key_metadata = core_key_data;
+    raw_key_data = key_metadata + KM_RSA_METADATA_SIZE;
+
+    pos = key_metadata + 4; // leave space for key size
+    set_u32_increment_pos(&pos, n_len);
+    set_u32_increment_pos(&pos, e_len);
+    set_u32_increment_pos(&pos, d_len);
+    set_u32_increment_pos(&pos, p_len);
+    set_u32_increment_pos(&pos, q_len);
+    set_u32_increment_pos(&pos, dp_len);
+    set_u32_increment_pos(&pos, dq_len);
+    set_u32_increment_pos(&pos, qinv_len);
+
+    offset = 0;
+    BN_bn2bin(rsa->n, raw_key_data + offset); offset += n_len;
+    BN_bn2bin(rsa->e, raw_key_data + offset); offset += e_len;
+    BN_bn2bin(rsa->d, raw_key_data + offset); offset += d_len;
+    BN_bn2bin(rsa->p, raw_key_data + offset); offset += p_len;
+    BN_bn2bin(rsa->q, raw_key_data + offset); offset += q_len;
+    BN_bn2bin(rsa->dmp1, raw_key_data + offset); offset += dp_len;
+    BN_bn2bin(rsa->dmq1, raw_key_data + offset); offset += dq_len;
+    BN_bn2bin(rsa->iqmp, raw_key_data + offset); // offset += qinv_len;
+
+    actual_key_size = 8 * n_len;
+    set_u32(key_metadata, actual_key_size);
+    CHECK_TRUE(KM_ERROR_INVALID_ARGUMENT,
+        e_len <= 4); // TODO Allow import of RSA keys with 2^32 < e < 2^64
+    actual_rsa_pubexp = BN_get_word(rsa->e);
+
+    /* Set key size, or check consistency with import_key() params. */
+    if (*key_size == 0) {
+        *key_size = actual_key_size;
+    } else {
+        CHECK_TRUE(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+            *key_size == actual_key_size);
+    }
+
+    /* Set RSA public exponent, or check consistency with import_key() params. */
+    if (*rsa_pubexp == 0) {
+        *rsa_pubexp = actual_rsa_pubexp;
+    } else {
+        CHECK_TRUE(KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+            *rsa_pubexp == actual_rsa_pubexp);
+    }
+
+end:
+    RSA_free(rsa);
+
+    return ret;
+}
+
+keymaster_error_t decode_pkcs8(
+    uint8_t *core_key_data,
+    uint32_t core_key_data_len,
+    uint32_t *key_size,
+    uint64_t *rsa_pubexp,
+    const keymaster_blob_t *pkcs8_data)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+    EVP_PKEY *pkey = NULL;
+
+    CHECK_NOT_NULL(key_size);
+
+    /* Parse key data */
+    p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL,
+        (const unsigned char**)&pkcs8_data->data, pkcs8_data->data_length);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        p8inf != NULL);
+    pkey = EVP_PKCS82PKEY(p8inf);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        pkey != NULL);
+
+    switch (EVP_PKEY_type(pkey->type)) {
+        case EVP_PKEY_EC:
+            ret = decode_pkcs8_ec_key(
+                core_key_data, core_key_data_len, key_size, pkey);
+            break;
+        case EVP_PKEY_RSA:
+            ret = decode_pkcs8_rsa_key(
+                core_key_data, core_key_data_len, key_size, rsa_pubexp, pkey);
+            break;
+        default:
+            ret = KM_ERROR_INVALID_KEY_BLOB;
+    }
+
+end:
+    PKCS8_PRIV_KEY_INFO_free(p8inf);
+    EVP_PKEY_free(pkey);
+
+    return ret;
+}
+
+static keymaster_error_t encode_x509_rsa_pub(
+    keymaster_blob_t *export_data,
+    uint32_t key_size,
+    const uint8_t *core_pub_data,
+    uint32_t core_pub_data_len)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    EVP_PKEY *pkey = NULL;
+    RSA *rsa = NULL;
+    uint32_t n_len, e_len;
+    int encoded_len;
+    unsigned char *pos = NULL;
+
+    rsa = RSA_new();
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        rsa != NULL);
+
+    /* Read metadata */
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        core_pub_data_len >= 12);
+
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        key_size == get_u32(core_pub_data));
+    n_len = get_u32(core_pub_data + 4);
+    e_len = get_u32(core_pub_data + 8);
+
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        (n_len <= BITS_TO_BYTES(key_size)) &&
+        (e_len <= BITS_TO_BYTES(key_size)));
+
+    /* Read bignums and populate key */
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        core_pub_data_len >= 12 + n_len + e_len);
+
+    rsa->n = BN_bin2bn(core_pub_data + 12, n_len, NULL);
+    rsa->e = BN_bin2bn(core_pub_data + 12 + n_len, e_len, NULL);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        (rsa->n != NULL) && (rsa->e != NULL));
+
+    /* Set the EVP_PKEY */
+    pkey = EVP_PKEY_new();
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        pkey != NULL);
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        EVP_PKEY_set1_RSA(pkey, rsa));
+
+    /* Allocate and populate export_data */
+    encoded_len = i2d_PUBKEY(pkey, NULL);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        encoded_len > 0);
+    export_data->data = (uint8_t*)malloc(encoded_len);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        export_data->data != NULL);
+    pos = (unsigned char*)export_data->data;
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        i2d_PUBKEY(pkey, &pos) == encoded_len);
+    export_data->data_length = encoded_len;
+
+end:
+    EVP_PKEY_free(pkey);
+    RSA_free(rsa);
+    if (ret != KM_ERROR_OK) {
+        free((void*)export_data->data);
+        export_data->data = NULL;
+        export_data->data_length = 0;
+    }
+
+    return ret;
+}
+
+static keymaster_error_t encode_x509_ec_pub(
+    keymaster_blob_t *export_data,
+    uint32_t key_size,
+    const uint8_t *core_pub_data,
+    uint32_t core_pub_data_len)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    EVP_PKEY *pkey = NULL;
+    EC_GROUP *ecgroup = NULL;
+    EC_KEY *eckey = NULL;
+    EC_POINT *ecpoint = NULL;
+    BIGNUM *x = NULL;
+    BIGNUM *y = NULL;
+    uint32_t curve, x_len, y_len;
+    int encoded_len;
+    int nid;
+    unsigned char *pos = NULL;
+
+    /* Read metadata */
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        core_pub_data_len >= 12);
+    curve = get_u32(core_pub_data);
+    x_len = get_u32(core_pub_data + 4);
+    y_len = get_u32(core_pub_data + 8);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        (x_len <= BITS_TO_BYTES(key_size)) &&
+        (y_len <= BITS_TO_BYTES(key_size)));
+
+    /* Construct EC group and key */
+    CHECK_RESULT_OK(get_nid(&nid, curve));
+    ecgroup = EC_GROUP_new_by_curve_name(nid);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        ecgroup != NULL);
+    eckey = EC_KEY_new_by_curve_name(nid);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        eckey != NULL);
+
+    /* Read bignums */
+    x = BN_bin2bn(core_pub_data + 12, x_len, NULL);
+    y = BN_bin2bn(core_pub_data + 12 + x_len, y_len, NULL);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        (x != NULL) && y != NULL);
+
+    /* Set ecpoint */
+    ecpoint = EC_POINT_new(ecgroup);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        ecpoint != NULL);
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        EC_POINT_set_affine_coordinates_GFp(ecgroup, ecpoint, x, y, NULL));
+
+    /* Set eckey */
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        EC_KEY_set_public_key(eckey, ecpoint));
+
+    /* Set the EVP_PKEY */
+    pkey = EVP_PKEY_new();
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        pkey != NULL);
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        EVP_PKEY_set1_EC_KEY(pkey, eckey));
+
+    /* Allocate and populate export_data */
+    encoded_len = i2d_PUBKEY(pkey, NULL);
+    CHECK_TRUE(KM_ERROR_INVALID_KEY_BLOB,
+        encoded_len > 0);
+    export_data->data = (uint8_t*)malloc(encoded_len);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        export_data->data != NULL);
+    pos = (unsigned char*)export_data->data;
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        i2d_PUBKEY(pkey, &pos) == encoded_len);
+    export_data->data_length = encoded_len;
+
+end:
+    EVP_PKEY_free(pkey);
+    EC_POINT_free(ecpoint);
+    BN_free(x);
+    BN_free(y);
+    EC_KEY_free(eckey);
+    EC_GROUP_free(ecgroup);
+    if (ret != KM_ERROR_OK) {
+        free((void*)export_data->data);
+        export_data->data = NULL;
+        export_data->data_length = 0;
+    }
+
+    return ret;
+}
+
+keymaster_error_t encode_x509(
+    keymaster_blob_t *export_data,
+    keymaster_algorithm_t key_type,
+    uint32_t key_size,
+    const uint8_t *core_pub_data,
+    uint32_t core_pub_data_len)
+{
+    switch (key_type) {
+        case KM_ALGORITHM_RSA:
+            return encode_x509_rsa_pub(export_data, key_size,
+                core_pub_data, core_pub_data_len);
+        case KM_ALGORITHM_EC:
+            return encode_x509_ec_pub(export_data, key_size,
+                core_pub_data, core_pub_data_len);
+        default:
+            return KM_ERROR_INCOMPATIBLE_ALGORITHM;
+    }
+}
diff --git a/libkeymaster/ver1/src/km_shared_util.cpp b/libkeymaster/ver1/src/km_shared_util.cpp
new file mode 100644 (file)
index 0000000..39e55d6
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "hardware/keymaster_defs.h"
+#include "km_shared_util.h"
+
+uint32_t get_u32(const uint8_t *pos) {
+    uint32_t a = 0;
+    for (int i = 0; i < 4; i++) {
+        a |= ((uint32_t)pos[i] << (8*i));
+    }
+    return a;
+}
+uint64_t get_u64(const uint8_t *pos) {
+    uint64_t a = 0;
+    for (int i = 0; i < 8; i++) {
+        a |= ((uint64_t)pos[i] << (8*i));
+    }
+    return a;
+}
+void set_u32(uint8_t *pos, uint32_t val) {
+    for (int i = 0; i < 4; i++) {
+        pos[i] = (val >> (8*i)) & 0xFF;
+    }
+}
+void set_u64(uint8_t *pos, uint64_t val) {
+    for (int i = 0; i < 8; i++) {
+        pos[i] = (val >> (8*i)) & 0xFF;
+    }
+}
+void set_u32_increment_pos(uint8_t **pos, uint32_t val) {
+    set_u32(*pos, val);
+    *pos += 4;
+}
+void set_u64_increment_pos(uint8_t **pos, uint64_t val) {
+    set_u64(*pos, val);
+    *pos += 8;
+}
+void set_data_increment_pos(uint8_t **pos, const uint8_t *src, uint32_t len) {
+    memcpy(*pos, src, len);
+    *pos += len;
+}
+void set_ptr_increment_src(uint8_t **ptr, uint8_t **src, uint32_t len) {
+    *ptr = *src;
+    *src += len;
+}
+
+bool check_algorithm_purpose(
+    keymaster_algorithm_t algorithm,
+    keymaster_purpose_t purpose)
+{
+    switch (algorithm) {
+        case KM_ALGORITHM_AES:
+            return ((purpose == KM_PURPOSE_ENCRYPT) ||
+                    (purpose == KM_PURPOSE_DECRYPT));
+        case KM_ALGORITHM_HMAC:
+        case KM_ALGORITHM_EC:
+            return ((purpose == KM_PURPOSE_SIGN) ||
+                    (purpose == KM_PURPOSE_VERIFY));
+        case KM_ALGORITHM_RSA:
+            return ((purpose == KM_PURPOSE_ENCRYPT) ||
+                    (purpose == KM_PURPOSE_DECRYPT) ||
+                    (purpose == KM_PURPOSE_SIGN) ||
+                    (purpose == KM_PURPOSE_VERIFY));
+        default:
+            return false;
+    }
+}
diff --git a/libkeymaster/ver1/src/km_util.cpp b/libkeymaster/ver1/src/km_util.cpp
new file mode 100644 (file)
index 0000000..d81f3f2
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <hardware/keymaster_defs.h>
+#include "km_util.h"
+
+keymaster_error_t get_enumerated_tag(
+    const keymaster_key_param_set_t *params,
+    keymaster_tag_t tag,
+    uint32_t *value)
+{
+    if ((params == NULL) || (value == NULL)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    for (size_t i = 0; i < params->length; i++) {
+        if (params->params[i].tag == tag) {
+            *value = params->params[i].enumerated;
+            return KM_ERROR_OK;
+        }
+    }
+    return KM_ERROR_INVALID_TAG;
+}
+
+keymaster_error_t get_integer_tag(
+    const keymaster_key_param_set_t *params,
+    keymaster_tag_t tag,
+    uint32_t *value)
+{
+    if ((params == NULL) || (value == NULL)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    for (size_t i = 0; i < params->length; i++) {
+        if (params->params[i].tag == tag) {
+            *value = params->params[i].integer;
+            return KM_ERROR_OK;
+        }
+    }
+    return KM_ERROR_INVALID_TAG;
+}
+
+keymaster_error_t get_long_integer_tag(
+    const keymaster_key_param_set_t *params,
+    keymaster_tag_t tag,
+    uint64_t *value)
+{
+    if ((params == NULL) || (value == NULL)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    for (size_t i = 0; i < params->length; i++) {
+        if (params->params[i].tag == tag) {
+            *value = params->params[i].long_integer;
+            return KM_ERROR_OK;
+        }
+    }
+    return KM_ERROR_INVALID_TAG;
+}
diff --git a/libkeymaster/ver1/src/module.c b/libkeymaster/ver1/src/module.c
new file mode 100644 (file)
index 0000000..2544d68
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdbool.h> // needed by keymaster1.h below
+#include <hardware/hardware.h>
+#include <hardware/keymaster1.h>
+#include "module.h"
+
+/* -------------------------------------------------------------------------
+   Module definitions needed for integrtion with Android HAL framework.
+   -------------------------------------------------------------------------*/
+
+static struct hw_module_methods_t kinibi_keymaster_module_methods = {
+    .open = kinibi_keymaster_open,
+};
+
+__attribute__((visibility("default")))
+struct keystore_module HAL_MODULE_INFO_SYM = {
+    .common =
+        {
+            .tag = HARDWARE_MODULE_TAG,
+            .module_api_version = KEYMASTER_MODULE_API_VERSION_1_0,
+            .hal_api_version = HARDWARE_HAL_API_VERSION,
+            .id = KEYSTORE_HARDWARE_MODULE_ID,
+            .name = KEYMASTER_HARDWARE_MODULE_TEE_NAME,
+            .author = "Trustonic",
+            .methods = &kinibi_keymaster_module_methods,
+            .dso = 0,
+            .reserved = {},
+        },
+};
diff --git a/libkeymaster/ver1/src/serialization.cpp b/libkeymaster/ver1/src/serialization.cpp
new file mode 100644 (file)
index 0000000..c02e71e
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <time.h>
+#include <hardware/keymaster_defs.h>
+#include "serialization.h"
+#include "km_util.h"
+
+#define MAX_DYNAMIC_PARAM_BUFFERS 20
+
+keymaster_error_t km_serialize_params(
+    uint8_t **buf,
+    uint32_t *buflen,
+    const keymaster_key_param_set_t *params,
+    bool add_time,
+    uint32_t key_size,
+    uint64_t rsa_pubexp)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint8_t* pos = NULL;
+    uint32_t size;
+    uint32_t n_params;
+    bool key_size_present = false;
+    bool rsa_pubexp_present = false;
+    bool add_key_size = false;
+    bool add_rsa_pubexp = false;
+    keymaster_tag_t tag;
+
+    CHECK_NOT_NULL(buf);
+    CHECK_NOT_NULL(buflen);
+
+    n_params = (params != NULL) ? params->length : 0;
+    *buf = NULL;
+    size = 4; // uint32_t (number of parameters)
+
+   /* First calculate the required buffer size */
+    for (size_t i = 0; i < n_params; i++) {
+        tag = params->params[i].tag;
+
+        if (tag == KM_TAG_KEY_SIZE) {
+            key_size_present = true;
+        } else if (tag == KM_TAG_RSA_PUBLIC_EXPONENT) {
+            rsa_pubexp_present = true;
+        }
+
+        /* length of tag */
+        size += 4; // uint32_t <= keymaster_tag_t
+
+        /* length of value */
+        switch (keymaster_tag_get_type(tag)) {
+            case KM_ENUM:
+            case KM_ENUM_REP:
+            case KM_UINT:
+            case KM_UINT_REP:
+            case KM_BOOL:
+                size += 4; // uint32_t
+                break;
+            case KM_ULONG:
+            case KM_DATE:
+            case KM_ULONG_REP:
+                size += 8; // uint64_t
+                break;
+            case KM_BIGNUM:
+            case KM_BYTES:
+                size += 4; // uint32_t
+                size += params->params[i].blob.data_length;
+                break;
+            default: // bad tag
+                ret = KM_ERROR_INVALID_TAG;
+                goto end;
+        }
+    }
+
+    add_key_size = (key_size != 0) && !key_size_present;
+    add_rsa_pubexp = (rsa_pubexp != 0) && !rsa_pubexp_present;
+
+    if (add_time) {
+        size += 4 + 8;
+    }
+    if (add_key_size) {
+        size += 4 + 4;
+    }
+    if (add_rsa_pubexp) {
+        size += 4 + 8;
+    }
+
+    /* Allocate memory for the buffer */
+    *buf = (uint8_t*)malloc(size);
+    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+        *buf != NULL);
+
+    /* Position to the beginning of the buffer */
+    pos = *buf;
+
+    /* Copy parameter count */
+    set_u32_increment_pos(&pos, n_params + (add_time       ? 1 : 0)
+                                         + (add_key_size   ? 1 : 0)
+                                         + (add_rsa_pubexp ? 1 : 0));
+
+    /* Copy data */
+    for (size_t i = 0; i < n_params; i++) {
+        keymaster_tag_t tag = params->params[i].tag;
+
+        set_u32_increment_pos(&pos, tag);
+
+        switch (keymaster_tag_get_type(tag)) {
+            case KM_ENUM:
+            case KM_ENUM_REP:
+                set_u32_increment_pos(&pos, params->params[i].enumerated);
+                break;
+            case KM_UINT:
+            case KM_UINT_REP:
+                set_u32_increment_pos(&pos, params->params[i].integer);
+                break;
+            case KM_BOOL:
+                set_u32_increment_pos(&pos, params->params[i].boolean ? 1 : 0);
+                break;
+            case KM_ULONG:
+            case KM_ULONG_REP:
+                set_u64_increment_pos(&pos, params->params[i].long_integer);
+                break;
+            case KM_DATE:
+                set_u64_increment_pos(&pos, params->params[i].date_time);
+                break;
+            case KM_BIGNUM:
+            case KM_BYTES:
+                set_u32_increment_pos(&pos, params->params[i].blob.data_length);
+                set_data_increment_pos(&pos, params->params[i].blob.data, params->params[i].blob.data_length);
+                break;
+            default: // bad tag
+                ret = KM_ERROR_INVALID_TAG;
+                goto end;
+        }
+    }
+    if (add_time) {
+        struct timeval tv;
+        gettimeofday(&tv, NULL);
+        set_u32_increment_pos(&pos, KM_TAG_CREATION_DATETIME);
+        set_u64_increment_pos(&pos, (uint64_t)tv.tv_usec + 1000000ull*(uint64_t)tv.tv_sec);
+    }
+    if (add_key_size) {
+        set_u32_increment_pos(&pos, KM_TAG_KEY_SIZE);
+        set_u32_increment_pos(&pos, key_size);
+    }
+    if (add_rsa_pubexp) {
+        set_u32_increment_pos(&pos, KM_TAG_RSA_PUBLIC_EXPONENT);
+        set_u64_increment_pos(&pos, rsa_pubexp);
+    }
+
+end:
+    if (ret != KM_ERROR_OK) {
+        if (buf != NULL) {
+            free(*buf);
+            *buf = NULL;
+        }
+        if (buflen != NULL) {
+            *buflen = 0;
+        }
+    } else {
+        *buflen = size;
+    }
+    return ret;
+}
+
+keymaster_error_t deserialize_param_set(
+    keymaster_key_param_set_t *param_set,
+    uint8_t **pos,
+    uint32_t *remain)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint32_t n;
+    uint32_t data_length;
+
+    CHECK_NOT_NULL(param_set);
+    CHECK_NOT_NULL(pos);
+    CHECK_NOT_NULL(remain);
+
+    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+        *remain >= 4);
+    n = get_u32(*pos);
+    *pos += 4; *remain -= 4;
+    param_set->length = n;
+
+    if (n == 0) {
+        param_set->params = NULL;
+    } else {
+        param_set->params = (keymaster_key_param_t*)calloc(sizeof(keymaster_key_param_t), n);
+        CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+            param_set->params != NULL);
+        memset(param_set->params, 0, n * sizeof(keymaster_key_param_t));
+
+        for (uint32_t i = 0; i < n; i++) {
+            keymaster_key_param_t *param = param_set->params + i;
+
+            // read tag
+            CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                *remain >= 4);
+            param->tag = (keymaster_tag_t)get_u32(*pos);
+            *pos += 4; *remain -= 4;
+
+            // read value
+            switch (keymaster_tag_get_type(param->tag)) {
+                case KM_ENUM:
+                case KM_ENUM_REP:
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= 4);
+                    param->enumerated = get_u32(*pos);
+                    *pos += 4; *remain -= 4;
+                    break;
+                case KM_UINT:
+                case KM_UINT_REP:
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= 4);
+                    param->integer = get_u32(*pos);
+                    *pos += 4; *remain -= 4;
+                    break;
+                case KM_BOOL:
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= 4);
+                    param->boolean = (get_u32(*pos) != 0);
+                    *pos += 4; *remain -= 4;
+                    break;
+                case KM_ULONG:
+                case KM_ULONG_REP:
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= 8);
+                    param->long_integer = get_u64(*pos);
+                    *pos += 8; *remain -= 8;
+                    break;
+                case KM_DATE:
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= 8);
+                    param->date_time = get_u64(*pos);
+                    *pos += 8; *remain -= 8;
+                    break;
+                case KM_BIGNUM:
+                case KM_BYTES:
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= 4);
+                    data_length = get_u32(*pos);
+                    *pos += 4; *remain -= 4;
+                    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+                        *remain >= data_length);
+                    param->blob.data = (const uint8_t*)malloc(data_length);
+                    CHECK_TRUE(KM_ERROR_MEMORY_ALLOCATION_FAILED,
+                        param->blob.data != NULL);
+                    memcpy((void*)param->blob.data, *pos, data_length);
+                    param->blob.data_length = data_length;
+                    *pos += data_length; *remain -= data_length;
+                    break;
+                default:
+                    ret = KM_ERROR_INVALID_TAG;
+                    goto end;
+            }
+        }
+    }
+
+end:
+    return ret;
+}
+
+keymaster_error_t km_deserialize_characteristics(
+    keymaster_key_characteristics_t *characteristics,
+    const uint8_t *buffer,
+    uint32_t buffer_length)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint8_t *pos = (uint8_t*)buffer;
+    uint32_t remain = buffer_length;
+
+    CHECK_NOT_NULL(characteristics);
+    CHECK_NOT_NULL(buffer);
+
+    memset(characteristics, 0, sizeof(keymaster_key_characteristics_t));
+
+    CHECK_RESULT_OK(deserialize_param_set(&characteristics->hw_enforced, &pos, &remain));
+    CHECK_RESULT_OK(deserialize_param_set(&characteristics->sw_enforced, &pos, &remain));
+
+end:
+    if (ret != KM_ERROR_OK) {
+        keymaster_free_characteristics(characteristics);
+    }
+    return ret;
+}
diff --git a/libkeymaster/ver1/src/tee_keymaster_device.cpp b/libkeymaster/ver1/src/tee_keymaster_device.cpp
new file mode 100644 (file)
index 0000000..70a7314
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hardware/keymaster_common.h>
+#include <tee_keymaster_device.h>
+#include <trustonic_tee_keymaster_impl.h>
+#include <module.h>
+#include "buildTag.h"
+#include "km_util.h"
+
+extern "C" {
+
+extern struct keystore_module HAL_MODULE_INFO_SYM;
+
+/******************************************************************************/
+__attribute__((visibility("default")))
+int kinibi_keymaster_open( const struct hw_module_t* module, const char* id,
+                            struct hw_device_t** device)
+{
+    int ret = 0;
+    LOG_I(MOBICORE_COMPONENT_BUILD_TAG);
+
+    if( id == NULL )
+        return -EINVAL;
+
+    if( memcmp(id, KEYSTORE_KEYMASTER, strlen(KEYSTORE_KEYMASTER)) != 0)
+        return -EINVAL;
+
+    // Make sure we initialize only with known module
+    if( (module->tag != HAL_MODULE_INFO_SYM.common.tag) ||
+        (module->module_api_version != HAL_MODULE_INFO_SYM.common.module_api_version) ||
+        (module->hal_api_version != HAL_MODULE_INFO_SYM.common.hal_api_version) ||
+        (0!=memcmp(module->name, HAL_MODULE_INFO_SYM.common.name, sizeof(KEYMASTER_HARDWARE_MODULE_TEE_NAME)-1)) )
+    {
+        return -EINVAL;
+    }
+
+    TeeKeymasterDevice* keymaster = new TeeKeymasterDevice(&HAL_MODULE_INFO_SYM.common);
+    if (0 == keymaster)
+    {
+        // Heap exhausted
+        return -ENOMEM;
+    }
+
+    *device = reinterpret_cast<hw_device_t*>(keymaster);
+    return ret;
+}
+
+/******************************************************************************/
+__attribute__((visibility("default")))
+int kinibi_keymaster_close(hw_device_t *hw)
+{
+    if(hw != NULL)
+    {
+        TeeKeymasterDevice* gk = reinterpret_cast<TeeKeymasterDevice*>(hw);
+        delete gk;
+    }
+    return 0;
+}
+} // extern "C"
+
+/******************************************************************************/
+
+TeeKeymasterDevice::TeeKeymasterDevice(hw_module_t* module) :
+        impl_(new TrustonicTeeKeymasterImpl())
+{
+    memset(&device_, 0, sizeof(device_));
+
+    device_.common.tag = HARDWARE_DEVICE_TAG;
+    device_.common.version = 1;
+    device_.common.module = module;
+    device_.common.close = &kinibi_keymaster_close;
+
+    device_.flags = KEYMASTER_BLOBS_ARE_STANDALONE | KEYMASTER_SUPPORTS_EC;
+
+    // The following functions are in the keymaster1_device_t definition but
+    // should not be implemented.
+    device_.generate_keypair    = NULL;
+    device_.import_keypair      = NULL;
+    device_.get_keypair_public  = NULL;
+    device_.delete_keypair      = NULL;
+    device_.delete_all          = NULL;
+    device_.sign_data           = NULL;
+    device_.verify_data         = NULL;
+
+    // keymaster1 API
+    device_.get_supported_algorithms = get_supported_algorithms;
+    device_.get_supported_block_modes = get_supported_block_modes;
+    device_.get_supported_padding_modes = get_supported_padding_modes;
+    device_.get_supported_digests = get_supported_digests;
+    device_.get_supported_import_formats = get_supported_import_formats;
+    device_.get_supported_export_formats = get_supported_export_formats;
+    device_.add_rng_entropy = add_rng_entropy;
+    device_.generate_key = generate_key;
+    device_.get_key_characteristics = get_key_characteristics;
+    device_.import_key = import_key;
+    device_.export_key = export_key;
+    device_.delete_key = NULL;
+    device_.delete_all_keys = NULL;
+    device_.begin = begin;
+    device_.update = update;
+    device_.finish = finish;
+    device_.abort = abort;
+
+    device_.context = NULL;
+}
+
+
+hw_device_t* TeeKeymasterDevice::hw_device() {
+    return &device_.common;
+}
+
+
+keymaster1_device_t* TeeKeymasterDevice::keymaster_device() {
+    return &device_;
+}
+
+/* static */
+static inline TeeKeymasterDevice* convert_device(const keymaster1_device_t* dev) {
+    return reinterpret_cast<TeeKeymasterDevice*>(const_cast<keymaster1_device_t*>(dev));
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_supported_algorithms(
+    const keymaster1_device_t*      dev,
+    keymaster_algorithm_t**         algorithms,
+    size_t*                         algorithms_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+    return convert_device(dev)->impl_->get_supported_algorithms(
+        algorithms, algorithms_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_supported_block_modes(
+    const struct keymaster1_device* dev,
+    keymaster_algorithm_t           algorithm,
+    keymaster_purpose_t             purpose,
+    keymaster_block_mode_t**        modes,
+    size_t*                         modes_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->get_supported_block_modes(
+        algorithm, purpose, modes, modes_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_supported_padding_modes(
+    const keymaster1_device_t*      dev,
+    keymaster_algorithm_t           algorithm,
+    keymaster_purpose_t             purpose,
+    keymaster_padding_t**           modes,
+    size_t*                         modes_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->get_supported_padding_modes(
+        algorithm, purpose, modes, modes_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_supported_digests(
+    const keymaster1_device_t*      dev,
+    keymaster_algorithm_t           algorithm,
+    keymaster_purpose_t             purpose,
+    keymaster_digest_t**            digests,
+    size_t*                         digests_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->get_supported_digests(
+        algorithm, purpose, digests, digests_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_supported_import_formats(
+    const keymaster1_device_t*      dev,
+    keymaster_algorithm_t           algorithm,
+    keymaster_key_format_t**        formats,
+    size_t*                         formats_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->get_supported_import_formats(
+        algorithm, formats, formats_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_supported_export_formats(
+    const keymaster1_device_t*       dev,
+    keymaster_algorithm_t            algorithm,
+    keymaster_key_format_t**         formats,
+    size_t*                          formats_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->get_supported_export_formats(
+        algorithm, formats, formats_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::add_rng_entropy(
+    const keymaster1_device_t*      dev,
+    const uint8_t*                  data,
+    size_t                          data_length)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->add_rng_entropy(
+        data, data_length);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::generate_key(
+    const struct keymaster1_device*     dev,
+    const keymaster_key_param_set_t*    params,
+    keymaster_key_blob_t*               key_blob,
+    keymaster_key_characteristics_t**   characteristics)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->generate_key(
+        params, key_blob, characteristics);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::get_key_characteristics(
+    const keymaster1_device_t*      dev,
+    const keymaster_key_blob_t*     key_blob,
+    const keymaster_blob_t*         client_id,
+    const keymaster_blob_t*         app_data,
+    keymaster_key_characteristics_t** characteristics)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->get_key_characteristics(
+        key_blob, client_id, app_data, characteristics);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::import_key(
+    const keymaster1_device_t*      dev,
+    const keymaster_key_param_set_t* params,
+    keymaster_key_format_t          key_format,
+    const keymaster_blob_t*         key_data,
+    keymaster_key_blob_t*           key_blob,
+    keymaster_key_characteristics_t** characteristics)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->import_key(
+        params, key_format, key_data, key_blob, characteristics);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::export_key(
+    const keymaster1_device_t*      dev,
+    keymaster_key_format_t          export_format,
+    const keymaster_key_blob_t*     key_to_export,
+    const keymaster_blob_t*         client_id,
+    const keymaster_blob_t*         app_data,
+    keymaster_blob_t*               export_data)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->export_key(
+        export_format, key_to_export, client_id, app_data, export_data);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::begin(
+    const keymaster1_device_t*      dev,
+    keymaster_purpose_t             purpose,
+    const keymaster_key_blob_t*     key,
+    const keymaster_key_param_set_t* params,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_operation_handle_t*   operation_handle)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->begin(
+        purpose, key, params, out_params, operation_handle);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::update(
+    const keymaster1_device_t*      dev,
+    keymaster_operation_handle_t    operation_handle,
+    const keymaster_key_param_set_t* params,
+    const keymaster_blob_t*         input,
+    size_t*                         input_consumed,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_blob_t*               output)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->update(
+        operation_handle, params, input, input_consumed, out_params, output);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::finish(
+    const keymaster1_device_t*      dev,
+    keymaster_operation_handle_t    operation_handle,
+    const keymaster_key_param_set_t* params,
+    const keymaster_blob_t*         signature,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_blob_t*               output)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->finish(
+        operation_handle, params, signature, out_params, output);
+}
+
+
+/* Static */
+keymaster_error_t TeeKeymasterDevice::abort(
+    const keymaster1_device_t*      dev,
+    keymaster_operation_handle_t    operation_handle)
+{
+    if (dev == NULL)
+    {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    return convert_device(dev)->impl_->abort(
+        operation_handle);
+}
+
diff --git a/libkeymaster/ver1/src/tlcTeeKeymaster_if.cpp b/libkeymaster/ver1/src/tlcTeeKeymaster_if.cpp
new file mode 100644 (file)
index 0000000..9d10318
--- /dev/null
@@ -0,0 +1,1755 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <hardware/keymaster_defs.h>
+#include "cutils/properties.h"
+#include "tlcTeeKeymasterM_if.h"
+#include "buildTag.h"
+#include "MobiCoreDriverApi.h"
+#include "tlTeeKeymaster_Api.h"
+#include "km_util.h"
+#include "serialization.h"
+#include "km_encodings.h"
+
+#define RSA_MAX_KEY_SIZE 4096
+#define EC_MAX_KEY_SIZE 521
+#define AES_MAX_KEY_SIZE 256
+#define HMAC_MAX_KEY_SIZE 1024
+
+#ifdef NDEBUG
+/* In Release mode these macros are void. */
+#define PRINT_BUFFER(data, data_length)
+#define PRINT_BLOB(blob)
+#define PRINT_BLOB_HEX(blob, length)
+#define PRINT_PARAM_SET(params)
+
+#else
+#include <sstream>
+
+#define SBUF_SIZE 1024
+static char sbuf[SBUF_SIZE]; // for formatting debug output prior to LOG_I
+
+static int snprint_buffer(
+    char *s, size_t n,
+    const uint8_t *data,
+    size_t data_length)
+{
+    if (data == NULL) {
+        return snprintf(s, n, "<NULL>\n");
+    } else {
+        return snprintf(s, n, "<data of length %zu>\n", data_length);
+    }
+}
+
+static int snprint_uint64(
+    char *s, size_t n,
+    uint64_t x)
+{
+    return snprintf(s, n, "0x%08x%08x\n", (uint32_t)(x >> 32), (uint32_t)(x & 0xFFFFFFFF));
+}
+
+static int snprint_bool(
+    char *s, size_t n,
+    bool x)
+{
+    return snprintf(s, n, x ? "true\n" : "false\n");
+}
+
+static int snprint_blob(
+    char *s, size_t n,
+    const keymaster_blob_t *blob)
+{
+    if (blob == NULL) {
+        return snprintf(s, n, "<NULL>\n");
+    } else {
+        return snprint_buffer(s, n, blob->data, blob->data_length);
+    }
+}
+
+static int snprint_param_set(
+    char *s, size_t n,
+    const keymaster_key_param_set_t *param_set)
+{
+    if (param_set == NULL) {
+        return snprintf(s, n, "<NULL>\n");
+    }
+    else {
+        int r;
+        size_t i = 0, l = 0;
+        while ((i < param_set->length) && (l < SBUF_SIZE)) {
+            const keymaster_key_param_t param = param_set->params[i];
+            switch (param.tag) {
+#define PRINT_ENUM snprintf(s + l, SBUF_SIZE - l, "0x%08x\n", param.enumerated)
+#define PRINT_UINT snprintf(s + l, SBUF_SIZE - l, "%u\n", param.integer)
+#define PRINT_ULONG snprint_uint64(s + l, SBUF_SIZE - l, param.long_integer)
+#define PRINT_DATE snprint_uint64(s + l, SBUF_SIZE - l, param.date_time)
+#define PRINT_BOOL snprint_bool(s + l, SBUF_SIZE - l, param.boolean)
+// #define PRINT_BIGNUM
+#define PRINT_BYTES snprint_blob(s + l, SBUF_SIZE - l, &param.blob)
+#define PARAM_CASE(tag, printval) \
+    case tag: \
+        r = snprintf(s + l, SBUF_SIZE - l, "%s: ", #tag); \
+        if (r < 0) return r; \
+        l += r; \
+        if (l < SBUF_SIZE) { \
+            r = printval; \
+            if (r < 0) return r; \
+            l += r; \
+        } \
+        break;
+#define PARAM_CASE_ENUM(tag) PARAM_CASE(tag, PRINT_ENUM)
+#define PARAM_CASE_UINT(tag) PARAM_CASE(tag, PRINT_UINT)
+#define PARAM_CASE_ULONG(tag) PARAM_CASE(tag, PRINT_ULONG)
+#define PARAM_CASE_DATE(tag) PARAM_CASE(tag, PRINT_DATE)
+#define PARAM_CASE_BOOL(tag) PARAM_CASE(tag, PRINT_BOOL)
+// #define PARAM_CASE_BIGNUM
+#define PARAM_CASE_BYTES(tag) PARAM_CASE(tag, PRINT_BYTES)
+                PARAM_CASE_DATE(KM_TAG_ACTIVE_DATETIME)
+                PARAM_CASE_ENUM(KM_TAG_ALGORITHM)
+                PARAM_CASE_BOOL(KM_TAG_ALL_APPLICATIONS)
+                PARAM_CASE_BOOL(KM_TAG_ALL_USERS)
+                PARAM_CASE_BYTES(KM_TAG_APPLICATION_DATA)
+                PARAM_CASE_BYTES(KM_TAG_APPLICATION_ID)
+                PARAM_CASE_BYTES(KM_TAG_ASSOCIATED_DATA)
+                PARAM_CASE_UINT(KM_TAG_AUTH_TIMEOUT)
+                PARAM_CASE_BYTES(KM_TAG_AUTH_TOKEN)
+                PARAM_CASE_ENUM(KM_TAG_BLOB_USAGE_REQUIREMENTS)
+                PARAM_CASE_ENUM(KM_TAG_BLOCK_MODE)
+                PARAM_CASE_BOOL(KM_TAG_BOOTLOADER_ONLY)
+                PARAM_CASE_BOOL(KM_TAG_CALLER_NONCE)
+                PARAM_CASE_DATE(KM_TAG_CREATION_DATETIME)
+                PARAM_CASE_ENUM(KM_TAG_DIGEST)
+                PARAM_CASE_UINT(KM_TAG_KEY_SIZE)
+                PARAM_CASE_UINT(KM_TAG_MAC_LENGTH)
+                PARAM_CASE_UINT(KM_TAG_MAX_USES_PER_BOOT)
+                PARAM_CASE_UINT(KM_TAG_MIN_MAC_LENGTH)
+                PARAM_CASE_UINT(KM_TAG_MIN_SECONDS_BETWEEN_OPS)
+                PARAM_CASE_BOOL(KM_TAG_NO_AUTH_REQUIRED)
+                PARAM_CASE_BYTES(KM_TAG_NONCE)
+                PARAM_CASE_ENUM(KM_TAG_ORIGIN)
+                PARAM_CASE_DATE(KM_TAG_ORIGINATION_EXPIRE_DATETIME)
+                PARAM_CASE_ENUM(KM_TAG_PADDING)
+                PARAM_CASE_ENUM(KM_TAG_PURPOSE)
+                PARAM_CASE_BOOL(KM_TAG_ROLLBACK_RESISTANT)
+                PARAM_CASE_BYTES(KM_TAG_ROOT_OF_TRUST)
+                PARAM_CASE_ULONG(KM_TAG_RSA_PUBLIC_EXPONENT)
+                PARAM_CASE_DATE(KM_TAG_USAGE_EXPIRE_DATETIME)
+                PARAM_CASE_ENUM(KM_TAG_USER_AUTH_TYPE)
+                PARAM_CASE_UINT(KM_TAG_USER_ID)
+                PARAM_CASE_ULONG(KM_TAG_USER_SECURE_ID)
+                default:
+                    r = snprintf(s + l, SBUF_SIZE - l, "<unknown tag 0x%08x>\n", param.tag);
+                    if (r < 0) return r;
+                    l += r;
+            }
+            i++;
+        }
+        return l;
+    }
+}
+
+#define PRINT_BUFFER(data, data_length) \
+    do { \
+        if (snprint_buffer(sbuf, SBUF_SIZE, data, data_length) >= 0) { \
+            LOG_D("%s = %s", #data, sbuf); \
+        } \
+    } while (0)
+#define PRINT_BLOB(blob) \
+    do { \
+        if (snprint_blob(sbuf, SBUF_SIZE, blob) >= 0) { \
+            LOG_D("%s = %s", #blob, sbuf); \
+        } \
+    } while (0)
+#define PRINT_PARAM_SET(params) \
+    do { \
+        if (snprint_param_set(sbuf, SBUF_SIZE, params) >= 0) { \
+            LOG_D("%s =\n%s", #params, sbuf); \
+        } \
+    } while (0)
+
+#define PRINT_BLOB_HEX(blob, len)                           \
+    do {                                                    \
+        std::ostringstream buf;                             \
+        for(size_t i=0; i<len; ++i) {                       \
+            buf << std::hex << (unsigned) blob[i] << " ";   \
+        }                                                   \
+        LOG_D("%s = %s\n", #blob, buf.str().c_str());       \
+    }                                                       \
+    while (0)
+
+#endif
+
+/* Global definitions */
+static const __attribute__((used)) char* buildtag = MOBICORE_COMPONENT_BUILD_TAG;
+static const uint32_t gDeviceId = MC_DEVICE_ID_DEFAULT;
+static const mcUuid_t gUuid = TEE_KEYMASTER_M_TA_UUID;
+
+extern inline void keymaster_free_param_values(keymaster_key_param_t* param, size_t param_count);
+extern inline void keymaster_free_param_set(keymaster_key_param_set_t* set);
+extern inline void keymaster_free_characteristics(keymaster_key_characteristics_t* characteristics);
+
+struct TEE_Session {
+    tciMessage_ptr      pTci;
+    mcSessionHandle_t   sessionHandle;
+};
+
+#define SECURE_OS_TIMEOUT      10000
+
+/* Acceptable params for all commands */
+#define AUTH_TAGS \
+    KM_TAG_ALL_USERS, \
+    KM_TAG_USER_ID, \
+    KM_TAG_USER_SECURE_ID, \
+    KM_TAG_NO_AUTH_REQUIRED, \
+    KM_TAG_USER_AUTH_TYPE, \
+    KM_TAG_AUTH_TIMEOUT, \
+    KM_TAG_ALL_APPLICATIONS, \
+    KM_TAG_APPLICATION_ID, \
+    KM_TAG_APPLICATION_DATA
+
+/* Acceptable params for generate_key() and import_key() */
+static const keymaster_tag_t key_creation_allowed_params[] = {
+    AUTH_TAGS,
+    KM_TAG_PURPOSE,
+    KM_TAG_ALGORITHM,
+    KM_TAG_KEY_SIZE,
+    KM_TAG_BLOCK_MODE,
+    KM_TAG_DIGEST,
+    KM_TAG_PADDING,
+    KM_TAG_CALLER_NONCE,
+    KM_TAG_MIN_MAC_LENGTH,
+    KM_TAG_RSA_PUBLIC_EXPONENT,
+    KM_TAG_ACTIVE_DATETIME,
+    KM_TAG_ORIGINATION_EXPIRE_DATETIME,
+    KM_TAG_USAGE_EXPIRE_DATETIME,
+    KM_TAG_MIN_SECONDS_BETWEEN_OPS,
+    KM_TAG_MAX_USES_PER_BOOT,
+    KM_TAG_ROOT_OF_TRUST,
+    KM_TAG_BOOTLOADER_ONLY,
+    KM_TAG_BLOB_USAGE_REQUIREMENTS
+};
+
+/* Acceptable params for begin() */
+static const keymaster_tag_t op_begin_allowed_params[] = {
+    AUTH_TAGS,
+    KM_TAG_ALGORITHM,
+    KM_TAG_BLOCK_MODE,
+    KM_TAG_DIGEST,
+    KM_TAG_PADDING,
+    KM_TAG_ASSOCIATED_DATA,
+    KM_TAG_NONCE,
+    KM_TAG_AUTH_TOKEN,
+    KM_TAG_MAC_LENGTH,
+    KM_TAG_PURPOSE
+};
+
+/* Acceptable params for update() and finish() */
+static const keymaster_tag_t op_allowed_params[] = {
+    AUTH_TAGS,
+    KM_TAG_ASSOCIATED_DATA,
+    KM_TAG_AUTH_TOKEN
+};
+
+static int secure_os_init(void)
+{
+    char state[PROPERTY_VALUE_MAX];
+    int i;
+
+    for (i = 0; i < SECURE_OS_TIMEOUT; i++) {
+       property_get("secure_os.init", state, 0);
+       if (!strncmp(state, "done", strlen("done") + 1))
+               break;
+       else
+               usleep(500);
+    }
+
+    if (i == SECURE_OS_TIMEOUT) {
+       LOG_E("%s: secure os init timed out!", __func__);
+       return -1;
+    } else {
+       LOG_D("%s: secure os init is done", __func__);
+       return 0;
+    }
+}
+
+/**
+ * Check that all tags in \p params occur in the given list.
+ */
+static keymaster_error_t check_params(
+    const keymaster_key_param_set_t *params,
+    const keymaster_tag_t *tags,
+    size_t tag_count)
+{
+    if ((tags == NULL) && (tag_count != 0)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    if ((params != NULL) && (params->length != 0)) {
+        if (params->params == NULL) {
+            return KM_ERROR_UNEXPECTED_NULL_POINTER;
+        }
+        for (uint32_t i = 0; i < params->length; i++) {
+            keymaster_tag_t tag = params->params[i].tag;
+            bool ok = false;
+            size_t j = 0;
+            while (!ok && (j < tag_count)) {
+                ok = (tags[j] == tag);
+                j++;
+            }
+            if (!ok) {
+                LOG_E("%s: Invalid tag 0x%08x", __func__, tag);
+                return KM_ERROR_INVALID_TAG;
+            }
+        }
+    }
+
+    return KM_ERROR_OK;
+}
+
+/**
+ * Maximum supported key size in bits.
+ *
+ * @param algorithm key type
+ * @return maximum supported size in bits
+ */
+static uint32_t km_max_key_size(
+    keymaster_algorithm_t algorithm)
+{
+    switch (algorithm) {
+        case KM_ALGORITHM_RSA:
+            return RSA_MAX_KEY_SIZE;
+        case KM_ALGORITHM_EC:
+            return EC_MAX_KEY_SIZE;
+        case KM_ALGORITHM_AES:
+            return AES_MAX_KEY_SIZE;
+        case KM_ALGORITHM_HMAC:
+            return HMAC_MAX_KEY_SIZE;
+        default:
+            return 0;
+    }
+}
+
+/**
+ * Upper bound km_key_data in plain form.
+ *
+ * @param algorithm key type
+ * @param key_size_in_bits key size in bits if known; if zero, assume worst case
+ * @return upper bound for km_key_data size
+ */
+static uint32_t km_key_data_max_size(
+    keymaster_algorithm_t algorithm,
+    uint32_t  key_size_in_bits)
+{
+    uint32_t keylen = BITS_TO_BYTES(
+        (key_size_in_bits > 0) ? key_size_in_bits : km_max_key_size(algorithm));
+    uint32_t prelim_size = 4 + 4; // key type and key size, both uint32_t
+    switch(algorithm)
+    {
+        case KM_ALGORITHM_RSA:
+            /* n + e + d + p + q + dp + dq + qinv */
+            return prelim_size + KM_RSA_METADATA_SIZE + 8 * keylen;
+        case KM_ALGORITHM_EC:
+            /* k + x + y */
+            return prelim_size + KM_EC_METADATA_SIZE + 3 * keylen;
+        case KM_ALGORITHM_AES:
+        case KM_ALGORITHM_HMAC:
+            /* no metadata */
+            return prelim_size + keylen;
+        default:
+            /* Unsupported algorithm */
+            return 0;
+    }
+}
+
+/**
+ * Calculate upper bound on length of exported key data.
+ *
+ * @return upper bound on length of exported data, or 0 on error
+ */
+static uint32_t export_data_length(
+    keymaster_algorithm_t key_type,
+    uint32_t key_size) // bits
+{
+    switch (key_type) {
+        case KM_ALGORITHM_AES:
+        case KM_ALGORITHM_HMAC:
+            // export not supported for symmetric keys
+            return 0;
+        case KM_ALGORITHM_RSA:
+            // type | size | size | n_len | e_len | n | e
+            return 5*4 + 2*BITS_TO_BYTES(key_size);
+        case KM_ALGORITHM_EC:
+            // type | size | curve | x_len | y_len | x | y
+            return 5*4 + 2*BITS_TO_BYTES(key_size);;
+        default:
+            return 0;
+    }
+}
+
+/**
+ * Calculate upper bound for size in bytes of material in encrypted key blob.
+ *
+ * \param key_size_in_bits Key size in bits if known. If zero assume worst case.
+ */
+static uint32_t key_blob_max_size(
+    keymaster_algorithm_t algorithm,
+    uint32_t key_size_in_bits,
+    uint32_t params_size_in_bytes)
+{
+    /* params_len (uint32_t) + caller-supplied params */
+    uint32_t plain_material_size = 4 + params_size_in_bytes;
+
+    /* characteristics set by us */
+    plain_material_size += OWN_PARAMS_SIZE;
+
+    /* raw key data */
+    plain_material_size += km_key_data_max_size(algorithm, key_size_in_bits);
+
+    /* 16-byte nonce | encrypted data | 16-byte tag */
+    return plain_material_size + 32;
+}
+
+/**
+ * Map a buffer.
+ */
+static keymaster_error_t map_buffer(
+    mcSessionHandle_t* session_handle,
+    const uint8_t *buf, uint32_t buflen,
+    mcBulkMap_t *bufinfo)
+{
+    if ((buf != NULL) && (buflen != 0)) {
+        mcResult_t mcRet = mcMap(session_handle, (void*)buf, buflen, bufinfo);
+        if (mcRet != MC_DRV_OK) {
+            LOG_E("%s: mcMap() returned 0x%08x", __func__, mcRet);
+            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+        }
+    }
+    return KM_ERROR_OK;
+}
+
+/**
+ * Unmap a buffer.
+ */
+static void unmap_buffer(
+    mcSessionHandle_t* session_handle,
+    const uint8_t *buf,
+    mcBulkMap_t *bufinfo)
+{
+    if (bufinfo->sVirtualAddr != 0) {
+        mcResult_t mcRet = mcUnmap(session_handle, (void*)buf, bufinfo);
+        if (mcRet != MC_DRV_OK) {
+            LOG_E("%s: mcUnmap() returned 0x%08x", __func__, mcRet);
+        }
+    }
+}
+
+/**
+ * Allocate memory and zero it.
+ *
+ * @param a pointer to address to allocate
+ * @param l number of bytes
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t km_alloc(
+    uint8_t **a,
+    uint32_t l)
+{
+    *a = (uint8_t*)malloc(l);
+    if (*a == NULL) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+    memset(*a, 0, l);
+    return KM_ERROR_OK;
+}
+
+/**
+ * Notify the trusted application and wait for response.
+ */
+static keymaster_error_t transact(
+    mcSessionHandle_t* session_handle,
+    tciMessage_ptr tci)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    mcResult_t mcRet;
+
+    mcRet = mcNotify(session_handle);
+    if (mcRet != MC_DRV_OK) {
+        LOG_E("%s: mcNotify() returned 0x%08x", __func__, mcRet);
+        ret = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+        goto end;
+    }
+
+    mcRet = mcWaitNotification(session_handle, MC_INFINITE_TIMEOUT);
+    if (mcRet != MC_DRV_OK) {
+        LOG_E("%s: mcWaitNotification() returned 0x%08x", __func__, mcRet);
+        ret = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+        goto end;
+    }
+
+    CHECK_RESULT_OK( (keymaster_error_t)tci->response.header.returnCode );
+
+end:
+    return ret;
+}
+
+keymaster_error_t TEE_Open(TEE_SessionHandle *pSessionHandle)
+{
+    struct TEE_Session *session;
+    mcResult_t     mcRet;
+    keymaster_error_t kmret = KM_ERROR_OK;
+
+    /* Validate session handle */
+    if (pSessionHandle == NULL) {
+        LOG_E("%s: Invalid session handle", __func__);
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    /* Check if secureOS is loaded or not */
+    if (secure_os_init()) {
+        LOG_E("%s: Failed to init secureOS", __func__);
+        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+    }
+
+    session = (struct TEE_Session *)malloc(sizeof(*session));
+    if (session == NULL) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+
+    /* Initialize session handle data */
+    memset(session, 0, sizeof(*session));
+
+    /* Open MobiCore device */
+    mcRet = mcOpenDevice(gDeviceId);
+    if ((MC_DRV_OK != mcRet) &&
+        (MC_DRV_ERR_DEVICE_ALREADY_OPEN != mcRet))
+    {
+        LOG_E("%s: mcOpenDevice() returned %d", __func__, mcRet);
+        kmret = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+        goto end_session;
+    }
+
+    /* Allocating WSM for TCI */
+    mcRet = mcMallocWsm(gDeviceId, 0, sizeof(*session->pTci), (uint8_t **) &session->pTci, 0);
+    if (MC_DRV_OK != mcRet) {
+        LOG_E("%s: mcMallocWsm() returned %d", __func__, mcRet);
+        kmret = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        goto end_device;
+    }
+
+    /* Open session the TEE Keymaster trusted application */
+    session->sessionHandle.deviceId = gDeviceId;
+    mcRet = mcOpenSession(&session->sessionHandle,
+                          &gUuid,
+                          (uint8_t *) session->pTci,
+                          (uint32_t) sizeof(tciMessage_t));
+    if (MC_DRV_OK != mcRet) {
+        LOG_E("%s: mcOpenSession() returned %d", __func__, mcRet);
+        mcFreeWsm(gDeviceId, (uint8_t*)session->pTci);
+        kmret = KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
+        goto end_device;
+    }
+    *pSessionHandle = (TEE_SessionHandle)session;
+    goto end;
+
+end_device:
+    mcRet = mcCloseDevice(gDeviceId);
+    if (MC_DRV_OK != mcRet) {
+        LOG_E("%s: mcCloseDevice() returned: %d", __func__, mcRet);
+    }
+end_session:
+    free(session);
+end:
+    return kmret;
+}
+
+void TEE_Close(TEE_SessionHandle sessionHandle)
+{
+    mcResult_t    mcRet;
+
+    /* Validate session handle */
+    if (sessionHandle == NULL) {
+        LOG_E("%s: Invalid session handle", __func__);
+        return;
+    }
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+
+    /* Close session */
+    mcRet = mcCloseSession(&session->sessionHandle);
+    if (MC_DRV_OK != mcRet) {
+        LOG_E("%s: mcCloseSession() returned %d", __func__, mcRet);
+    }
+
+    mcFreeWsm(gDeviceId, (uint8_t*)session->pTci);
+    if (MC_DRV_OK != mcRet) {
+        LOG_E("%s: mcFreeWsm() returned %d", __func__, mcRet);
+    }
+
+    /* Close MobiCore device */
+    mcRet = mcCloseDevice(gDeviceId);
+    if (MC_DRV_OK != mcRet) {
+        LOG_E("%s: mcCloseDevice() returned %d", __func__, mcRet);
+    }
+    free(session);
+}
+
+
+keymaster_error_t TEE_AddRngEntropy(
+    TEE_SessionHandle sessionHandle,
+    const uint8_t *data,
+    uint32_t dataLength)
+{
+    LOG_D("TEE_AddRngEntropy");
+    PRINT_BUFFER(data, dataLength);
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    mcBulkMap_t dataInfo = {0, 0};
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t* session_handle = &session->sessionHandle;
+    uint8_t *data1 = NULL;
+
+    CHECK_NOT_NULL(data);
+    CHECK_TRUE(KM_ERROR_INVALID_ARGUMENT,
+        dataLength != 0);
+
+    /* Hack to ensure that non-writable memory can be mapped. */
+    CHECK_RESULT_OK(km_alloc(&data1, dataLength));
+    memcpy(data1, data, dataLength);
+
+    /* Map data */
+    CHECK_RESULT_OK( map_buffer(session_handle, data1, dataLength, &dataInfo) );
+
+    /* Update TCI buffer */
+    tci->command.header.commandId = CMD_ID_TEE_ADD_RNG_ENTROPY;
+    tci->add_rng_entropy.rng_data.data = (uint32_t)dataInfo.sVirtualAddr;
+    tci->add_rng_entropy.rng_data.data_length = dataLength;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+end:
+    unmap_buffer(session_handle, data1, &dataInfo);
+    if (data1 != NULL) {
+        memset(data1, 0, dataLength);
+    }
+    free(data1);
+
+    LOG_D("TEE_AddRngEntropy exiting with %d", ret);
+    return ret;
+}
+
+
+keymaster_error_t TEE_GenerateKey(
+    TEE_SessionHandle                   sessionHandle,
+    const keymaster_key_param_set_t*    params,
+    keymaster_key_blob_t*               key_blob,
+    keymaster_key_characteristics_t**   characteristics)
+{
+    LOG_D("TEE_GenerateKey");
+    PRINT_PARAM_SET(params);
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    mcBulkMap_t paramsInfo = {0, 0};
+    mcBulkMap_t keyBlobInfo = {0, 0};
+    mcBulkMap_t characteristicsInfo = {0, 0};
+    uint32_t serializedDataLen = 0;
+    uint32_t keySizeInBits = 0;
+    uint64_t rsa_pubexp = 0;
+    keymaster_algorithm_t algorithm;
+    uint8_t *pSerializedData = NULL;
+    uint8_t *key_chars = NULL;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t* session_handle = &session->sessionHandle;
+
+    if (characteristics != NULL) {
+        CHECK_RESULT_OK(km_alloc((uint8_t**)characteristics, sizeof(keymaster_key_characteristics_t)));
+    }
+
+    CHECK_NOT_NULL(params);
+    CHECK_NOT_NULL(key_blob);
+
+    key_blob->key_material = NULL;
+
+    /* Check parameters are valid for generate_key */
+    CHECK_RESULT_OK( check_params(params, key_creation_allowed_params,
+        sizeof(key_creation_allowed_params) / sizeof(keymaster_tag_t)) );
+
+    /* Find algorithm, key size and RSA public exponent */
+    CHECK_RESULT_OK( get_enumerated_tag(params,
+        KM_TAG_ALGORITHM, (uint32_t*)&algorithm) );
+    CHECK_TRUE(KM_ERROR_UNSUPPORTED_KEY_SIZE,
+        KM_ERROR_OK == get_integer_tag(params,
+            KM_TAG_KEY_SIZE, &keySizeInBits));
+    if (algorithm == KM_ALGORITHM_RSA) {
+        if (KM_ERROR_OK == get_long_integer_tag(params,
+            KM_TAG_RSA_PUBLIC_EXPONENT, &rsa_pubexp))
+        {
+            CHECK_TRUE(KM_ERROR_INVALID_ARGUMENT,
+                (rsa_pubexp % 2 == 1) && (rsa_pubexp != 1));
+        } else {
+            rsa_pubexp = 65537; // default
+        }
+    }
+
+    /* Serialize key parameters */
+    CHECK_RESULT_OK(km_serialize_params(
+        &pSerializedData, &serializedDataLen, params, true, 0, rsa_pubexp));
+
+    /* Map key generation parameters */
+    CHECK_RESULT_OK( map_buffer(session_handle, pSerializedData, serializedDataLen, &paramsInfo) );
+
+    /* Allocate memory for key material */
+    key_blob->key_material_size = key_blob_max_size(
+        algorithm, keySizeInBits, serializedDataLen);
+    CHECK_RESULT_OK(km_alloc((uint8_t**)&key_blob->key_material, key_blob->key_material_size));
+
+    /* Map key blob buffer */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        key_blob->key_material, key_blob->key_material_size, &keyBlobInfo) );
+
+    if (characteristics != NULL) {
+        /* Allocate memory for the key characteristics. */
+        CHECK_RESULT_OK(km_alloc(&key_chars, KM_CHARACTERISTICS_SIZE));
+        /* Map buffer for key characteristics. */
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            key_chars, KM_CHARACTERISTICS_SIZE, &characteristicsInfo) );
+    }
+
+    /* Update TCI buffer */
+    tci->command.header.commandId = CMD_ID_TEE_GENERATE_KEY;
+    tci->generate_key.params.data = (uint32_t)paramsInfo.sVirtualAddr;
+    tci->generate_key.params.data_length = serializedDataLen;
+    tci->generate_key.key_blob.data = (uint32_t)keyBlobInfo.sVirtualAddr;
+    tci->generate_key.key_blob.data_length = key_blob->key_material_size;
+    tci->generate_key.characteristics.data = (uint32_t)characteristicsInfo.sVirtualAddr;
+    tci->generate_key.characteristics.data_length =
+        (characteristics != NULL) ? KM_CHARACTERISTICS_SIZE : 0;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    /* Update key blob length */
+    key_blob->key_material_size = tci->generate_key.key_blob.data_length;
+
+    if (characteristics != NULL) { // Give characteristics to caller.
+        CHECK_RESULT_OK(km_deserialize_characteristics(
+            *characteristics, key_chars, KM_CHARACTERISTICS_SIZE));
+    }
+end:
+    unmap_buffer(session_handle, pSerializedData, &paramsInfo);
+    if (key_blob != NULL) {
+        unmap_buffer(session_handle, key_blob->key_material, &keyBlobInfo);
+    }
+    if (characteristics != NULL) {
+        unmap_buffer(session_handle, key_chars, &characteristicsInfo);
+    }
+
+    free(pSerializedData);
+    free(key_chars);
+
+    if (ret != KM_ERROR_OK) {
+        if (key_blob != NULL) {
+            free((void*)key_blob->key_material);
+            key_blob->key_material = NULL;
+            key_blob->key_material_size = 0;
+        }
+        if (characteristics != NULL) {
+            keymaster_free_characteristics(*characteristics);
+            free(*characteristics);
+            *characteristics = NULL;
+        }
+    }
+
+    LOG_D("TEE_GenerateKey exiting with %d", ret);
+    return ret;
+}
+
+keymaster_error_t TEE_GetKeyCharacteristics(
+    TEE_SessionHandle                 sessionHandle,
+    const keymaster_key_blob_t*       key_blob,
+    const keymaster_blob_t*           client_id,
+    const keymaster_blob_t*           app_data,
+    keymaster_key_characteristics_t** characteristics)
+{
+    LOG_D("TEE_GetKeyCharacteristics");
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint8_t *key_chars = NULL;
+    mcBulkMap_t keyBlobInfo = {0, 0};
+    mcBulkMap_t clientIdInfo = {0, 0};
+    mcBulkMap_t appDataInfo = {0, 0};
+    mcBulkMap_t characteristicsInfo = {0, 0};
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t* session_handle = &session->sessionHandle;
+    uint8_t *client_id1 = NULL;
+    uint8_t *app_data1 = NULL;
+
+    CHECK_NOT_NULL(tci);
+    CHECK_NOT_NULL(key_blob);
+    CHECK_NOT_NULL(characteristics);
+
+    CHECK_RESULT_OK(km_alloc((uint8_t**)characteristics, sizeof(keymaster_key_characteristics_t)));
+
+    /* Map input buffers */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        key_blob->key_material, key_blob->key_material_size, &keyBlobInfo) );
+    if (client_id != NULL) {
+        /* Hack to ensure that non-writable memory can be mapped. */
+        CHECK_RESULT_OK(km_alloc(&client_id1, client_id->data_length));
+        memcpy(client_id1, client_id->data, client_id->data_length);
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            client_id1, client_id->data_length, &clientIdInfo) );
+    }
+    if (app_data != NULL) {
+        /* Hack to ensure that non-writable memory can be mapped. */
+        CHECK_RESULT_OK(km_alloc(&app_data1, app_data->data_length));
+        memcpy(app_data1, app_data->data, app_data->data_length);
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            app_data1, app_data->data_length, &appDataInfo) );
+    }
+
+    /* Allocate memory for characteristics */
+    CHECK_RESULT_OK(km_alloc(&key_chars, KM_CHARACTERISTICS_SIZE));
+
+    /* Map buffer for serialized key characteristics */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        key_chars, KM_CHARACTERISTICS_SIZE, &characteristicsInfo) );
+
+    /* Now the get_key_characteristics command */
+    tci->command.header.commandId = CMD_ID_TEE_GET_KEY_CHARACTERISTICS;
+    tci->get_key_characteristics.key_blob.data = (uint32_t)keyBlobInfo.sVirtualAddr;
+    tci->get_key_characteristics.key_blob.data_length = key_blob->key_material_size;
+    tci->get_key_characteristics.client_id.data = (uint32_t)clientIdInfo.sVirtualAddr;
+    tci->get_key_characteristics.client_id.data_length =
+        (client_id != NULL) ? client_id->data_length : 0;
+    tci->get_key_characteristics.app_data.data = (uint32_t)appDataInfo.sVirtualAddr;
+    tci->get_key_characteristics.app_data.data_length =
+        (app_data != NULL) ? app_data->data_length : 0;
+    tci->get_key_characteristics.characteristics.data = (uint32_t)characteristicsInfo.sVirtualAddr;
+    tci->get_key_characteristics.characteristics.data_length = KM_CHARACTERISTICS_SIZE;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    /* Deserialize */
+    CHECK_RESULT_OK(km_deserialize_characteristics(
+        *characteristics, key_chars, KM_CHARACTERISTICS_SIZE));
+
+end:
+    if (key_blob != NULL) {
+        unmap_buffer(session_handle, key_blob->key_material, &keyBlobInfo);
+    }
+    if (client_id != NULL) {
+        unmap_buffer(session_handle, client_id1, &clientIdInfo);
+    }
+    if (app_data != NULL) {
+        unmap_buffer(session_handle, app_data1, &appDataInfo);
+    }
+    unmap_buffer(session_handle, key_chars, &characteristicsInfo);
+
+    if (ret != KM_ERROR_OK) {
+        if (characteristics != NULL) {
+            keymaster_free_characteristics(*characteristics);
+            free(*characteristics);
+            *characteristics = NULL;
+        }
+    }
+    free(client_id1);
+    free(app_data1);
+
+    LOG_D("TEE_GetKeyCharacteristics exiting with %d", ret);
+    return ret;
+}
+
+/**
+ * Check if a format is supported for key import
+ * @param format data format
+ * @param algorithm key type
+ * @return whether import is supported
+ */
+static bool import_format_supported(
+    keymaster_key_format_t format,
+    keymaster_algorithm_t algorithm)
+{
+    switch (format) {
+        case KM_KEY_FORMAT_PKCS8:
+            return ((algorithm == KM_ALGORITHM_RSA) ||
+                    (algorithm == KM_ALGORITHM_EC));
+        case KM_KEY_FORMAT_RAW:
+            return ((algorithm == KM_ALGORITHM_AES) ||
+                    (algorithm == KM_ALGORITHM_HMAC));
+        default:
+            return false;
+    }
+}
+
+/**
+ * Check if we can import a key of a given size
+ * @param algorithm key type
+ * @param keysize key size in bits
+ * @return whether key size is supported
+ */
+static bool key_size_supported(
+    keymaster_algorithm_t algorithm,
+    uint32_t keysize)
+{
+    switch (algorithm) {
+        case KM_ALGORITHM_RSA:
+            return ((keysize >= 256) &&
+                    (keysize <= RSA_MAX_KEY_SIZE) &&
+                    (keysize % 64 == 0));
+        case KM_ALGORITHM_EC:
+            return ((keysize == 192) ||
+                    (keysize == 224) ||
+                    (keysize == 256) ||
+                    (keysize == 384) ||
+                    (keysize == EC_MAX_KEY_SIZE));
+        case KM_ALGORITHM_AES:
+            return ((keysize == 128) ||
+                    (keysize == 192) ||
+                    (keysize == AES_MAX_KEY_SIZE));
+        case KM_ALGORITHM_HMAC:
+            return ((keysize >= 64) &&
+                    (keysize <= HMAC_MAX_KEY_SIZE) &&
+                    (keysize % 8 == 0));
+        default:
+            return false;
+    }
+}
+
+/**
+ * Allocate and populate a buffer with km_key_data for passing to the TA.
+ *
+ * @param format format of \p key_encoding
+ * @param algorithm key type
+ * @param[in,out] keySizeInBits key size if known, otherwise 0 on entry, actual on exit
+ * @param[in,out] rsa_pubexp RSA public exponent if knowm, otherwise 0 on entry, actual on exit
+ * @param key_encoding data for decoding/encoding
+ * @param[out] key_data pointer to allocated buffer, or NULL on error
+ * @param[out] key_data_len length of allocated buffer
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t decode_key(
+    keymaster_key_format_t format,
+    keymaster_algorithm_t algorithm,
+    uint32_t *keySizeInBits,
+    uint64_t *rsa_pubexp,
+    const keymaster_blob_t *key_encoding,
+    uint8_t **key_data,
+    uint32_t *key_data_len)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint8_t *pos;
+    uint32_t core_key_data_len;
+
+    assert(keySizeInBits != NULL);
+    assert((rsa_pubexp != NULL) || (algorithm != KM_ALGORITHM_RSA));
+    assert(key_data != NULL);
+    assert(key_data_len != NULL);
+
+    *key_data_len = km_key_data_max_size(algorithm, *keySizeInBits); // upper bound
+    CHECK_RESULT_OK(km_alloc(key_data, *key_data_len));
+
+    /* First the key type and size */
+    CHECK_TRUE(KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+        *key_data_len >= 8);
+    core_key_data_len = *key_data_len - 8;
+
+    pos = *key_data;
+    set_u32_increment_pos(&pos, algorithm);
+    pos += 4; // leave space at *key_data + 4 to put the key size when we know it
+
+    // now pos points to buffer for core key data
+    switch (format) {
+        case KM_KEY_FORMAT_PKCS8:
+            CHECK_RESULT_OK(decode_pkcs8(
+                pos, core_key_data_len, keySizeInBits, rsa_pubexp, key_encoding));
+            break;
+        case KM_KEY_FORMAT_RAW:
+            /* Just copy the bytes. */
+            CHECK_TRUE(KM_ERROR_INVALID_ARGUMENT,
+                core_key_data_len >= key_encoding->data_length);
+            memcpy(pos, key_encoding->data, key_encoding->data_length);
+            if (*keySizeInBits > 0) {
+                CHECK_TRUE(KM_ERROR_INVALID_ARGUMENT,
+                    key_encoding->data_length == BITS_TO_BYTES(*keySizeInBits));
+            } else {
+                *keySizeInBits = 8 * key_encoding->data_length;
+            }
+            break;
+        default:
+            ret = KM_ERROR_UNSUPPORTED_KEY_FORMAT;
+            goto end;
+    }
+
+    CHECK_TRUE(KM_ERROR_INVALID_ARGUMENT,
+        key_size_supported(algorithm, *keySizeInBits));
+
+    // Now we can compute the real key_data_len
+    *key_data_len = km_key_data_max_size(algorithm, *keySizeInBits);
+    *key_data = (uint8_t*)realloc(*key_data, *key_data_len);
+    CHECK_NOT_NULL(*key_data);
+
+    /* Now set the actual key size. */
+    set_u32(*key_data + 4, *keySizeInBits);
+
+end:
+    if (ret != KM_ERROR_OK) {
+        free(*key_data);
+        *key_data = NULL;
+        *key_data_len = 0;
+    }
+
+    return ret;
+}
+
+/**
+ * Allocate and populate a buffer with encoded key data.
+ *
+ * @param format desired export format
+ * @param key_type key type
+ * @param key_size key size in bits
+ * @param core_pub_data public key data
+ * @param core_pub_data_len length of \p core_pub_data
+ * @param[out] export_data encoded key data
+ *
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t encode_key(
+    keymaster_key_format_t format,
+    keymaster_algorithm_t key_type,
+    uint32_t key_size,
+    const uint8_t *core_pub_data,
+    uint32_t core_pub_data_len,
+    keymaster_blob_t *export_data)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+
+    assert(export_data != NULL);
+
+    export_data->data = NULL;
+    export_data->data_length = 0;
+
+    CHECK_TRUE(KM_ERROR_UNSUPPORTED_KEY_FORMAT,
+        format == KM_KEY_FORMAT_X509);
+
+    CHECK_RESULT_OK(encode_x509(export_data, key_type, key_size,
+        core_pub_data, core_pub_data_len));
+    // no need to free export_data on error
+
+end:
+    return ret;
+}
+
+keymaster_error_t TEE_ImportKey(
+    TEE_SessionHandle                   sessionHandle,
+    const keymaster_key_param_set_t*    params,
+    keymaster_key_format_t              key_format,
+    const keymaster_blob_t*             key_data, // encoded
+    keymaster_key_blob_t*               key_blob,
+    keymaster_key_characteristics_t**   characteristics)
+{
+    LOG_D("TEE_ImportKey");
+    PRINT_PARAM_SET(params);
+    LOG_D("key_format = 0x%08x", key_format);
+    PRINT_BLOB(key_data);
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint8_t *pSerializedData = NULL;
+    uint32_t serializedDataLen = 0;
+    mcBulkMap_t paramsInfo = {0, 0};
+    mcBulkMap_t keyDataInfo = {0, 0};
+    mcBulkMap_t keyBlobInfo = {0, 0};
+    mcBulkMap_t characteristicsInfo = {0, 0};
+    uint32_t keySizeInBits = 0;
+    uint64_t rsa_pubexp = 0;
+    keymaster_algorithm_t algorithm;
+    keymaster_error_t ret1;
+    uint8_t *key_chars = NULL;
+    uint8_t *km_key_data = NULL; // to hold km_key_data passed to TA
+    uint32_t km_key_data_len = 0;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t *session_handle = &session->sessionHandle;
+
+    if (characteristics != NULL) {
+        CHECK_RESULT_OK(km_alloc((uint8_t**)characteristics, sizeof(keymaster_key_characteristics_t)));
+    }
+
+    CHECK_NOT_NULL(tci);
+    CHECK_NOT_NULL(key_blob);
+
+    key_blob->key_material = NULL;
+
+    /* Check parameters are valid for import_key */
+    CHECK_RESULT_OK( check_params(params, key_creation_allowed_params,
+        sizeof(key_creation_allowed_params) / sizeof(keymaster_tag_t)) );
+
+    /* Extract algorithm and (if present) key size and RSA public exponent from
+     * the key parameters */
+    CHECK_RESULT_OK( get_enumerated_tag(params, KM_TAG_ALGORITHM, (uint32_t*)&algorithm) );
+    ret1 = get_integer_tag(params, KM_TAG_KEY_SIZE, &keySizeInBits);
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        (ret1 == KM_ERROR_OK) || (ret1 == KM_ERROR_INVALID_TAG));
+    ret1 = get_long_integer_tag(params, KM_TAG_RSA_PUBLIC_EXPONENT, &rsa_pubexp);
+    CHECK_TRUE(KM_ERROR_UNKNOWN_ERROR,
+        (ret1 == KM_ERROR_OK) || (ret1 == KM_ERROR_INVALID_TAG));
+    /* If we got KM_ERROR_INVALID_TAG, the tag was not present; then
+     * the value will still be 0 at this point. */
+
+    /* Check consistency of format and algorithm */
+    CHECK_TRUE(KM_ERROR_INCOMPATIBLE_KEY_FORMAT,
+        import_format_supported(key_format, algorithm));
+
+    /* Allocate and fill buffer for decoded key data for passing to TA */
+    CHECK_RESULT_OK(decode_key(key_format, algorithm,
+        &keySizeInBits, &rsa_pubexp, key_data, &km_key_data, &km_key_data_len));
+
+    /* Serialize key parameters */
+    CHECK_RESULT_OK(km_serialize_params(
+        &pSerializedData, &serializedDataLen, params, true, keySizeInBits, rsa_pubexp));
+
+    /* Map key parameters */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        pSerializedData, serializedDataLen, &paramsInfo) );
+
+    /* Allocate memory for key blob */
+    key_blob->key_material_size = key_blob_max_size(
+        algorithm, keySizeInBits, serializedDataLen);
+    CHECK_RESULT_OK(km_alloc((uint8_t**)&key_blob->key_material, key_blob->key_material_size));
+
+    /* Map key data */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        km_key_data, km_key_data_len, &keyDataInfo) );
+
+    /* Map key blob buffer */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        key_blob->key_material, key_blob->key_material_size, &keyBlobInfo) );
+
+    if (characteristics != NULL) {
+        /* Allocate memory for the serialized key characteristics.*/
+        CHECK_RESULT_OK(km_alloc(&key_chars, KM_CHARACTERISTICS_SIZE));
+         /* Map buffer for key characteristics. */
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            key_chars, KM_CHARACTERISTICS_SIZE, &characteristicsInfo) );
+    }
+
+    /* Update TCI buffer */
+    tci->command.header.commandId = CMD_ID_TEE_IMPORT_KEY;
+    tci->import_key.params.data = (uint32_t)paramsInfo.sVirtualAddr;
+    tci->import_key.params.data_length = serializedDataLen;
+    tci->import_key.key_data.data = (uint32_t)keyDataInfo.sVirtualAddr;
+    tci->import_key.key_data.data_length = km_key_data_len;
+    tci->import_key.key_blob.data = (uint32_t)keyBlobInfo.sVirtualAddr;
+    tci->import_key.key_blob.data_length = key_blob->key_material_size;
+    tci->import_key.characteristics.data = (uint32_t)characteristicsInfo.sVirtualAddr;
+    tci->import_key.characteristics.data_length =
+        (characteristics != NULL) ? KM_CHARACTERISTICS_SIZE : 0;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    /* Update key blob length */
+    key_blob->key_material_size = tci->import_key.key_blob.data_length;
+
+    if (characteristics != NULL) { // Give characteristics to caller.
+        CHECK_RESULT_OK(km_deserialize_characteristics(
+            *characteristics, key_chars, KM_CHARACTERISTICS_SIZE));
+    }
+
+end:
+    unmap_buffer(session_handle, pSerializedData, &paramsInfo);
+    unmap_buffer(session_handle, km_key_data, &keyDataInfo);
+    if (key_blob != NULL) {
+        unmap_buffer(session_handle, (uint8_t*)key_blob->key_material, &keyBlobInfo);
+    }
+    if (characteristics != NULL) {
+        unmap_buffer(session_handle, key_chars, &characteristicsInfo);
+    }
+
+    free(pSerializedData);
+    free(km_key_data);
+    free(key_chars);
+
+    if (ret != KM_ERROR_OK) {
+        if (key_blob != NULL) {
+            free((void*)key_blob->key_material);
+            key_blob->key_material = NULL;
+            key_blob->key_material_size = 0;
+        }
+        if (characteristics != NULL) {
+            keymaster_free_characteristics(*characteristics);
+            free(*characteristics);
+            *characteristics = NULL;
+        }
+    }
+
+    LOG_D("TEE_ImportKey exiting with %d", ret);
+    return ret;
+}
+
+keymaster_error_t TEE_ExportKey(
+    TEE_SessionHandle                   sessionHandle,
+    keymaster_key_format_t              export_format,
+    const keymaster_key_blob_t*         key_to_export,
+    const keymaster_blob_t*             client_id,
+    const keymaster_blob_t*             app_data,
+    keymaster_blob_t*                   export_data)
+{
+    LOG_D("TEE_ExportKey");
+    LOG_D("export_format = 0x%08x", export_format);
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    mcBulkMap_t keyBlobInfo = {0, 0};
+    mcBulkMap_t clientIdInfo = {0, 0};
+    mcBulkMap_t appDataInfo = {0, 0};
+    mcBulkMap_t keyDataInfo = {0, 0};
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr     tci = session->pTci;
+    mcSessionHandle_t* session_handle = &session->sessionHandle;
+    uint8_t *core_pub_data = NULL;
+    uint32_t core_pub_data_len = 0;
+    keymaster_algorithm_t key_type;
+    uint32_t key_size;
+    uint8_t *client_id1 = NULL;
+    uint8_t *app_data1 = NULL;
+
+    CHECK_NOT_NULL(tci);
+    CHECK_NOT_NULL(key_to_export);
+    CHECK_NOT_NULL(export_data);
+
+    export_data->data = NULL;
+
+    /* Map input buffers */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        key_to_export->key_material, key_to_export->key_material_size, &keyBlobInfo) );
+    if (client_id != NULL) {
+        /* Hack to ensure that non-writable memory can be mapped. */
+        CHECK_RESULT_OK(km_alloc(&client_id1, client_id->data_length));
+        memcpy(client_id1, client_id->data, client_id->data_length);
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            client_id1, client_id->data_length, &clientIdInfo) );
+    }
+    if (app_data != NULL) {
+        /* Hack to ensure that non-writable memory can be mapped. */
+        CHECK_RESULT_OK(km_alloc(&app_data1, app_data->data_length));
+        memcpy(app_data1, app_data->data, app_data->data_length);
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            app_data1, app_data->data_length, &appDataInfo) );
+    }
+
+    /* First need to determine required length of key data. */
+    tci->command.header.commandId = CMD_ID_TEE_GET_KEY_INFO;
+    tci->get_key_info.key_blob.data = (uint32_t)keyBlobInfo.sVirtualAddr;
+    tci->get_key_info.key_blob.data_length = key_to_export->key_material_size;
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+    key_type = tci->get_key_info.key_type;
+    key_size = tci->get_key_info.key_size;
+    core_pub_data_len = export_data_length(key_type, key_size);
+    CHECK_TRUE(KM_ERROR_UNSUPPORTED_KEY_FORMAT,
+        core_pub_data_len > 0);
+
+    /* Allocate memory for exported public key data */
+    CHECK_RESULT_OK(km_alloc(&core_pub_data, core_pub_data_len));
+
+    /* Map buffer */
+    CHECK_RESULT_OK( map_buffer(session_handle, core_pub_data, core_pub_data_len, &keyDataInfo) );
+
+    /* Now the export_key command */
+    tci->command.header.commandId = CMD_ID_TEE_EXPORT_KEY;
+    tci->export_key.key_blob.data = (uint32_t)keyBlobInfo.sVirtualAddr;
+    tci->export_key.key_blob.data_length = key_to_export->key_material_size;
+    tci->export_key.client_id.data = (uint32_t)clientIdInfo.sVirtualAddr;
+    tci->export_key.client_id.data_length =
+        (client_id != NULL) ? client_id->data_length : 0;
+    tci->export_key.app_data.data = (uint32_t)appDataInfo.sVirtualAddr;
+    tci->export_key.app_data.data_length =
+        (app_data != NULL) ? app_data->data_length : 0;
+    tci->export_key.key_data.data = (uint32_t)keyDataInfo.sVirtualAddr;
+    tci->export_key.key_data.data_length = core_pub_data_len;
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    /* Allocate and fill buffer for encoded key data for passing to caller */
+    CHECK_RESULT_OK(encode_key(export_format, key_type, key_size,
+        core_pub_data, core_pub_data_len, export_data));
+
+end:
+    if (key_to_export != NULL)
+    {
+        unmap_buffer(session_handle, (uint8_t*)key_to_export->key_material, &keyBlobInfo);
+    }
+    if (client_id != NULL) {
+        unmap_buffer(session_handle, client_id1, &clientIdInfo);
+    }
+    if (app_data != NULL) {
+        unmap_buffer(session_handle, app_data1, &appDataInfo);
+    }
+    unmap_buffer(session_handle, (uint8_t*)core_pub_data, &keyDataInfo);
+
+    if (ret != KM_ERROR_OK) {
+        if (export_data != NULL) {
+            free((void*)export_data->data);
+            export_data->data = NULL;
+            export_data->data_length = 0;
+        }
+    }
+
+    free(core_pub_data);
+    free(client_id1);
+    free(app_data1);
+
+    LOG_D("TEE_ExportKey exiting with %d", ret);
+    return ret;
+}
+
+keymaster_error_t TEE_Begin(
+    TEE_SessionHandle               sessionHandle,
+    keymaster_purpose_t             purpose,
+    const keymaster_key_blob_t*     key,
+    const keymaster_key_param_set_t* params,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_operation_handle_t*   operation_handle)
+{
+    LOG_D("TEE_Begin");
+    LOG_D("purpose = 0x%08x", purpose);
+    PRINT_PARAM_SET(params);
+
+    keymaster_error_t  ret = KM_ERROR_OK;
+    mcBulkMap_t        paramsInfo = {0, 0};
+    mcBulkMap_t        keyBlobInfo = {0, 0};
+    mcBulkMap_t        outParamsInfo = {0, 0};
+    uint32_t           serializedDataLen = 0;
+    uint8_t*           pSerializedData = NULL;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr     tci = session->pTci;
+    mcSessionHandle_t* session_handle = &session->sessionHandle;
+    uint8_t            serialized_out_params[TEE_BEGIN_OUT_PARAMS_SIZE];
+
+    /* Make valgrind happy. */
+    memset(serialized_out_params, 0, TEE_BEGIN_OUT_PARAMS_SIZE);
+
+    if (out_params != NULL) {
+        out_params->params = NULL;
+        out_params->length = 0;
+    }
+
+    CHECK_NOT_NULL(tci);
+    CHECK_NOT_NULL(key);
+    CHECK_NOT_NULL(operation_handle);
+
+    /* Check parameters are valid for begin */
+    CHECK_RESULT_OK( check_params(params, op_begin_allowed_params,
+        sizeof(op_begin_allowed_params) / sizeof(keymaster_tag_t)) );
+
+    /* Serialize params */
+    CHECK_RESULT_OK(km_serialize_params(
+        &pSerializedData, &serializedDataLen, params, false, 0, 0));
+
+    /* Map params */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        pSerializedData, serializedDataLen, &paramsInfo) );
+
+    /* Map key blob buffer */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        key->key_material, key->key_material_size, &keyBlobInfo) );
+
+    /* Map serialized_out_params */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        serialized_out_params, TEE_BEGIN_OUT_PARAMS_SIZE, &outParamsInfo) );
+
+    /* Update TCI buffer */
+    tci->command.header.commandId = CMD_ID_TEE_BEGIN;
+    tci->begin.purpose = purpose;
+    tci->begin.params.data = (uint32_t)paramsInfo.sVirtualAddr;
+    tci->begin.params.data_length = serializedDataLen;
+    tci->begin.key_blob.data = (uint32_t)keyBlobInfo.sVirtualAddr;
+    tci->begin.key_blob.data_length = key->key_material_size;
+    if (out_params != NULL) {
+        tci->begin.out_params.data = (uint32_t)outParamsInfo.sVirtualAddr;
+        tci->begin.out_params.data_length = TEE_BEGIN_OUT_PARAMS_SIZE;
+    } else {
+        tci->begin.out_params.data = 0;
+        tci->begin.out_params.data_length = 0;
+    }
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    /* Deserialize out_params */
+    if (out_params != NULL) {
+        uint8_t *pos = serialized_out_params;
+        uint32_t remain = tci->begin.out_params.data_length;
+        if (remain > 0) {
+            CHECK_RESULT_OK(deserialize_param_set(out_params, &pos, &remain));
+        } else {
+            out_params->params = NULL;
+            out_params->length = 0;
+        }
+    }
+
+    /* Update operation handle */
+    *operation_handle = tci->begin.handle;
+
+end:
+    if (ret != KM_ERROR_OK) {
+        if (out_params != NULL) {
+            keymaster_free_param_set(out_params);
+            out_params->length = 0;
+        }
+    }
+    unmap_buffer(session_handle, pSerializedData, &paramsInfo);
+    if (key != NULL) {
+        unmap_buffer(session_handle, key->key_material, &keyBlobInfo);
+    }
+    unmap_buffer(session_handle, serialized_out_params, &outParamsInfo);
+
+    free(pSerializedData);
+
+    LOG_D("TEE_Begin exiting with %d", ret);
+    return ret;
+}
+
+/**
+ * Maximum size of buffer to process internally in an update() operation.
+ *
+ * Longer messages are split up into chunks this size.
+ */
+#define INPUT_CHUNK_SIZE 4096*4
+
+/**
+ * Process a chunk of input to an operation.
+ *
+ * @param sessionHandle TEE session handle
+ * @param operation_handle operation handle
+ * @param paramsInfo serialized parameters, mapped
+ * @param data input data (not NULL)
+ * @param data_length length of \p data
+ * @param[out] output output if required (pre-allocated), or NULL
+ * @param[in,out] input_consumed input consumed (incremented)
+ *
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t update_chunk(
+    TEE_SessionHandle sessionHandle,
+    keymaster_operation_handle_t operation_handle,
+    const mcBulkMap_t *paramsInfo,
+    const uint8_t *data,
+    size_t data_length,
+    keymaster_blob_t *output,
+    size_t *input_consumed)
+{
+    keymaster_error_t ret = KM_ERROR_OK;
+    uint8_t *data1 = NULL;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t *session_handle = &session->sessionHandle;
+    mcBulkMap_t inputInfo = {0, 0};
+    mcBulkMap_t outputInfo = {0, 0};
+
+    /* If we're just updating AAD in an AEAD operation, data may be NULL. */
+    if (data != NULL) {
+        /* Copy input data to local memory so that it can be mapped */
+        CHECK_RESULT_OK(km_alloc(&data1, data_length));
+        memcpy(data1, data, data_length);
+        /* Map input buffer */
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            data1, data_length, &inputInfo) );
+    }
+
+    /* Map output buffer if required */
+    if (output != NULL) {
+        CHECK_RESULT_OK( map_buffer(session_handle,
+            (uint8_t*)output->data, output->data_length, &outputInfo) );
+    }
+
+    /* Update TCI buffer */
+    tci->command.header.commandId = CMD_ID_TEE_UPDATE;
+    tci->update.handle = operation_handle;
+    tci->update.params.data = (uint32_t)paramsInfo->sVirtualAddr;
+    tci->update.params.data_length = paramsInfo->sVirtualLen;
+    tci->update.input.data = (uint32_t)inputInfo.sVirtualAddr;
+    tci->update.input.data_length = inputInfo.sVirtualLen;
+    tci->update.output.data = (uint32_t)outputInfo.sVirtualAddr;
+    tci->update.output.data_length = outputInfo.sVirtualLen;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    if (input_consumed != NULL) {
+        *input_consumed += tci->update.input_consumed;
+    }
+
+end:
+    if (data != NULL) {
+        unmap_buffer(session_handle, data1, &inputInfo);
+        free(data1);
+    }
+    if (output != NULL) {
+        unmap_buffer(session_handle, (uint8_t*)output->data, &outputInfo);
+        output->data_length = tci->update.output.data_length;
+    }
+
+    return ret;
+}
+
+keymaster_error_t TEE_Update(
+    TEE_SessionHandle               sessionHandle,
+    keymaster_operation_handle_t    operation_handle,
+    const keymaster_key_param_set_t* params,
+    const keymaster_blob_t*         input,
+    size_t*                         input_consumed,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_blob_t*               output)
+{
+    LOG_D("TEE_Update");
+    PRINT_PARAM_SET(params);
+    PRINT_BLOB(input);
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    mcBulkMap_t paramsInfo = {0, 0};
+    uint32_t serializedDataLen = 0;
+    uint8_t *pSerializedData = NULL;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t *session_handle = &session->sessionHandle;
+    keymaster_algorithm_t algorithm;
+    bool split_input = true;
+    const uint8_t *data = NULL;
+    size_t data_length = 0;
+
+    /* No output parameters */
+    if (out_params != NULL) {
+        out_params->params = NULL;
+        out_params->length = 0;
+    }
+
+    CHECK_NOT_NULL(input_consumed);
+    *input_consumed = 0;
+
+    /* Check parameters are valid for update */
+    CHECK_RESULT_OK( check_params(params, op_allowed_params,
+        sizeof(op_allowed_params) / sizeof(keymaster_tag_t)) );
+
+    /* Serialize params */
+    CHECK_RESULT_OK(km_serialize_params(
+        &pSerializedData, &serializedDataLen, params, false, 0, 0));
+
+    /* Map params */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        pSerializedData, serializedDataLen, &paramsInfo) );
+
+    /* Find out what type of operation we are. */
+    tci->command.header.commandId = CMD_ID_TEE_GET_OPERATION_INFO;
+    tci->get_operation_info.handle = operation_handle;
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+    algorithm = tci->get_operation_info.algorithm;
+
+    if (input != NULL) {
+        data = input->data; // else NULL
+        data_length = input->data_length; // else 0
+    }
+
+    /* Allocate output if required. */
+    if (output != NULL) {
+        if (algorithm == KM_ALGORITHM_AES) {
+            /* Allocate the output buffer. */
+            output->data_length = data_length + 16; // up to one more block
+            CHECK_RESULT_OK(km_alloc((uint8_t**)&output->data, output->data_length));
+            split_input = false;
+        } else {
+            /* No output. */
+            output->data = NULL;
+            output->data_length = 0;
+        }
+    }
+
+    if (split_input) {
+        /* No output. But we have to handle input buffers that are too large to
+         * allocate or share. So we split the message into chunks.
+         */
+        for (size_t offset = 0; offset < data_length; offset += INPUT_CHUNK_SIZE) {
+            size_t chunk_length = (offset + INPUT_CHUNK_SIZE <= data_length)
+                                ? INPUT_CHUNK_SIZE : data_length - offset;
+            CHECK_RESULT_OK(update_chunk(
+                sessionHandle, operation_handle, &paramsInfo,
+                data + offset, chunk_length, NULL, input_consumed));
+        }
+    } else {
+        CHECK_RESULT_OK(update_chunk(
+            sessionHandle, operation_handle, &paramsInfo,
+            data, data_length, output, input_consumed));
+    }
+
+end:
+    unmap_buffer(session_handle, pSerializedData, &paramsInfo);
+    free(pSerializedData);
+
+    LOG_D("TEE_Update exiting with %d", ret);
+    return ret;
+}
+
+keymaster_error_t TEE_Finish(
+    TEE_SessionHandle               sessionHandle,
+    keymaster_operation_handle_t    operation_handle,
+    const keymaster_key_param_set_t* params,
+    const keymaster_blob_t*         signature,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_blob_t*               output)
+{
+    LOG_D("TEE_Finish");
+    PRINT_PARAM_SET(params);
+    PRINT_BLOB(signature);
+
+    keymaster_error_t ret = KM_ERROR_OK;
+    mcBulkMap_t paramsInfo = {0, 0};
+    mcBulkMap_t signatureInfo = {0, 0};
+    mcBulkMap_t outputInfo = {0, 0};
+    uint32_t serializedDataLen = 0;
+    uint8_t *pSerializedData = NULL;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr tci = session->pTci;
+    mcSessionHandle_t *session_handle = &session->sessionHandle;
+    uint8_t *signature1 = NULL;
+
+    if (signature != NULL) {
+        /* Hack to ensure that non-writable memory can be mapped. */
+        CHECK_RESULT_OK(km_alloc(&signature1, signature->data_length));
+        memcpy(signature1, signature->data, signature->data_length);
+    }
+
+    if (output != NULL) {
+        output->data = NULL;
+        output->data_length = 0;
+    }
+
+    /* No output parameters */
+    if (out_params != NULL) {
+        out_params->params = NULL;
+        out_params->length = 0;
+    }
+
+    /* Check parameters are valid for finish */
+    CHECK_RESULT_OK( check_params(params, op_allowed_params,
+        sizeof(op_allowed_params) / sizeof(keymaster_tag_t)) );
+
+    /* Serialize params */
+    CHECK_RESULT_OK(km_serialize_params(
+        &pSerializedData, &serializedDataLen, params, false, 0, 0));
+
+    /* Map params */
+    CHECK_RESULT_OK( map_buffer(session_handle,
+        pSerializedData, serializedDataLen, &paramsInfo) );
+
+    /* Map signature buffer */
+    if (signature != NULL) {
+        CHECK_RESULT_OK( map_buffer(session_handle, signature1, signature->data_length, &signatureInfo) );
+    }
+
+    if (output != NULL) {
+        /* The output buffer is used for RSA-encrypt, RSA-decrypt, RSA-sign,
+         * AES-GCM-encrypt, AES with PKCS7 padding, HMAC-sign, and ECDSA-sign.
+         * We can't infer its length from the finish() parameters, so we use the
+         * get_operation_info() command.
+         */
+        tci->command.header.commandId = CMD_ID_TEE_GET_OPERATION_INFO;
+        tci->get_operation_info.handle = operation_handle;
+        CHECK_RESULT_OK( transact(session_handle, tci) );
+
+        /* Allocate and map the output buffer. The caller must free this. */
+        output->data_length = tci->get_operation_info.data_length;
+
+        if (output->data_length != 0) {
+            CHECK_RESULT_OK(km_alloc((uint8_t**)&output->data, output->data_length));
+            CHECK_RESULT_OK( map_buffer(session_handle,
+                (uint8_t*)output->data, output->data_length, &outputInfo) );
+        }
+    }
+
+    /* Update TCI buffer */
+    tci->command.header.commandId     = CMD_ID_TEE_FINISH;
+    tci->finish.handle                = operation_handle;
+    tci->finish.params.data           = (uint32_t)paramsInfo.sVirtualAddr;
+    tci->finish.params.data_length    = serializedDataLen;
+    tci->finish.signature.data        = (uint32_t)signatureInfo.sVirtualAddr;
+    tci->finish.signature.data_length = signatureInfo.sVirtualLen;
+    tci->finish.output.data           = (uint32_t)outputInfo.sVirtualAddr;
+    tci->finish.output.data_length    = outputInfo.sVirtualLen;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+    /* Update output length */
+    if (output != NULL) {
+        output->data_length = tci->finish.output.data_length;
+    }
+
+end:
+    unmap_buffer(session_handle, pSerializedData, &paramsInfo);
+    if (signature != NULL) {
+        unmap_buffer(session_handle, signature1, &signatureInfo);
+        free(signature1);
+    }
+    if (output != NULL) {
+        unmap_buffer(session_handle, (uint8_t*)output->data, &outputInfo);
+    }
+
+    free(pSerializedData);
+
+    if (ret != KM_ERROR_OK) {
+        if (output != NULL) {
+            free((void*)output->data);
+            output->data = NULL;
+            output->data_length = 0;
+        }
+    }
+
+    LOG_D("TEE_Finish exiting with %d", ret);
+    return ret;
+}
+
+keymaster_error_t TEE_Abort(
+    TEE_SessionHandle               sessionHandle,
+    keymaster_operation_handle_t    operation_handle)
+{
+    LOG_D("TEE_Abort");
+
+    keymaster_error_t  ret  = KM_ERROR_OK;
+    struct TEE_Session *session = (struct TEE_Session *)sessionHandle;
+    tciMessage_ptr     tci = session->pTci;
+    mcSessionHandle_t* session_handle = &session->sessionHandle;
+
+    /* Update TCI buffer */
+    tci->command.header.commandId = CMD_ID_TEE_ABORT;
+    tci->abort.handle = operation_handle;
+
+    CHECK_RESULT_OK( transact(session_handle, tci) );
+
+end:
+    LOG_D("TEE_Abort exiting with %d", ret);
+    return ret;
+}
diff --git a/libkeymaster/ver1/src/trustonic_tee_keymaster_impl.cpp b/libkeymaster/ver1/src/trustonic_tee_keymaster_impl.cpp
new file mode 100644 (file)
index 0000000..c5ddca8
--- /dev/null
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hardware/keymaster_common.h>
+#include <tee_keymaster_device.h>
+#include <trustonic_tee_keymaster_impl.h>
+#include <tlcTeeKeymasterM_if.h>
+#include "km_shared_util.h"
+
+#undef  LOG_TAG
+#define LOG_TAG "TrustonicTeeKeymasterImpl"
+#include "log.h"
+
+// Supported algorithms
+static const keymaster_algorithm_t supported_algorithms[]   = {
+    KM_ALGORITHM_RSA,
+    KM_ALGORITHM_EC,
+    KM_ALGORITHM_AES,
+    KM_ALGORITHM_HMAC
+};
+
+// Supported block modes
+static const keymaster_block_mode_t supported_block_modes[] = {
+    KM_MODE_ECB,
+    KM_MODE_CBC,
+    KM_MODE_CTR,
+    KM_MODE_GCM
+};
+
+// Supported padding modes
+static const keymaster_padding_t supported_aes_padding_modes[] = {
+    KM_PAD_NONE,
+    KM_PAD_PKCS7
+};
+static const keymaster_padding_t supported_rsa_sig_padding[] = {
+    KM_PAD_NONE,
+    KM_PAD_RSA_PKCS1_1_5_SIGN,
+    KM_PAD_RSA_PSS
+};
+static const keymaster_padding_t supported_rsa_crypt_padding[] = {
+    KM_PAD_NONE,
+    KM_PAD_RSA_OAEP,
+    KM_PAD_RSA_PKCS1_1_5_ENCRYPT
+};
+
+// Supported digests
+static const keymaster_digest_t supported_hmac_digests[] = {
+    KM_DIGEST_SHA1,
+    KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256,
+    KM_DIGEST_SHA_2_384,
+    KM_DIGEST_SHA_2_512
+};
+static const keymaster_digest_t supported_rsa_sig_digests[] = {
+    KM_DIGEST_NONE,
+    KM_DIGEST_MD5,
+    KM_DIGEST_SHA1,
+    KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256,
+    KM_DIGEST_SHA_2_384,
+    KM_DIGEST_SHA_2_512
+};
+static const keymaster_digest_t supported_rsa_crypt_digests[] = {
+    KM_DIGEST_NONE,
+    KM_DIGEST_MD5,
+    KM_DIGEST_SHA1,
+    KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256,
+    KM_DIGEST_SHA_2_384,
+    KM_DIGEST_SHA_2_512
+};
+static const keymaster_digest_t supported_ec_digests[] = {
+    KM_DIGEST_NONE,
+    KM_DIGEST_SHA1,
+    KM_DIGEST_SHA_2_224,
+    KM_DIGEST_SHA_2_256,
+    KM_DIGEST_SHA_2_384,
+    KM_DIGEST_SHA_2_512
+};
+
+// Key formats
+static const keymaster_key_format_t public_key_export_formats[]     = { KM_KEY_FORMAT_X509 };
+static const keymaster_key_format_t asymmetric_key_import_formats[] = { KM_KEY_FORMAT_PKCS8 };
+static const keymaster_key_format_t symmetric_key_import_formats[]  = { KM_KEY_FORMAT_RAW };
+
+/**
+ * Constructor
+ */
+TrustonicTeeKeymasterImpl::TrustonicTeeKeymasterImpl() : session_handle_(NULL)
+{
+    keymaster_error_t err = TEE_Open(&session_handle_);
+    if (err != KM_ERROR_OK) {
+        LOG_E("Failed to open session to Keymaster TA.");
+        session_handle_ = NULL;
+    }
+}
+
+
+/**
+ * Destructor
+ */
+TrustonicTeeKeymasterImpl::~TrustonicTeeKeymasterImpl()
+{
+    TEE_Close(session_handle_);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_supported_algorithms(
+    keymaster_algorithm_t**         algorithms,
+    size_t*                         algorithms_length)
+{
+    if ((algorithms == NULL) || (algorithms_length == NULL)) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+    *algorithms = reinterpret_cast<keymaster_algorithm_t*>(malloc(sizeof(supported_algorithms)));
+    if (*algorithms == NULL) {
+        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+    }
+    memcpy(*algorithms, &supported_algorithms[0], sizeof(supported_algorithms));
+    *algorithms_length = sizeof(supported_algorithms) / sizeof(keymaster_algorithm_t);
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_supported_block_modes(
+    keymaster_algorithm_t           algorithm,
+    keymaster_purpose_t             purpose,
+    keymaster_block_mode_t**        modes,
+    size_t*                         modes_length)
+{
+    if ((modes == NULL) || (modes_length == NULL)) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    if (!check_algorithm_purpose(algorithm, purpose)) {
+        return KM_ERROR_UNSUPPORTED_PURPOSE;
+    }
+
+    *modes = NULL;
+    *modes_length = 0;
+    if (algorithm == KM_ALGORITHM_AES) {
+        *modes = reinterpret_cast<keymaster_block_mode_t*>(malloc(sizeof(supported_block_modes)));
+        if (*modes == NULL) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+        memcpy(*modes, &supported_block_modes[0], sizeof(supported_block_modes));
+        *modes_length = sizeof(supported_block_modes) / sizeof(keymaster_block_mode_t);
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_supported_padding_modes(
+    keymaster_algorithm_t           algorithm,
+    keymaster_purpose_t             purpose,
+    keymaster_padding_t**           modes,
+    size_t*                         modes_length)
+{
+    const keymaster_padding_t* supported_padding_modes = NULL;
+    size_t               supported_padding_modes_length = 0;
+
+    if ((modes == NULL) || (modes_length == NULL)) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    if (!check_algorithm_purpose(algorithm, purpose)) {
+        return KM_ERROR_UNSUPPORTED_PURPOSE;
+    }
+
+    switch (purpose) {
+        case KM_PURPOSE_SIGN:
+        case KM_PURPOSE_VERIFY:
+            if (algorithm == KM_ALGORITHM_RSA) {
+                supported_padding_modes = &supported_rsa_sig_padding[0];
+                supported_padding_modes_length = sizeof(supported_rsa_sig_padding);
+            }
+            break;
+        case KM_PURPOSE_ENCRYPT:
+        case KM_PURPOSE_DECRYPT:
+            if (algorithm == KM_ALGORITHM_RSA) {
+                    supported_padding_modes = &supported_rsa_crypt_padding[0];
+                    supported_padding_modes_length = sizeof(supported_rsa_crypt_padding);
+            } else if (algorithm == KM_ALGORITHM_AES) {
+                    supported_padding_modes = &supported_aes_padding_modes[0];
+                    supported_padding_modes_length = sizeof(supported_aes_padding_modes);
+            }
+            break;
+        default: /* shouldn't get here */
+            break;
+    }
+
+    *modes = NULL;
+    *modes_length = 0;
+    if (supported_padding_modes != NULL) {
+        *modes = reinterpret_cast<keymaster_padding_t*>(malloc(supported_padding_modes_length));
+        if (*modes == NULL) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+
+        memcpy(*modes, supported_padding_modes, supported_padding_modes_length);
+        *modes_length = supported_padding_modes_length / sizeof(keymaster_padding_t);
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_supported_digests(
+    keymaster_algorithm_t           algorithm,
+    keymaster_purpose_t             purpose,
+    keymaster_digest_t**            digests,
+    size_t*                         digests_length)
+{
+    const keymaster_digest_t *supported_digests = NULL;
+    size_t supported_digests_length = 0;
+
+    if ((digests == NULL) || (digests_length == NULL)) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    if (!check_algorithm_purpose(algorithm, purpose)) {
+        return KM_ERROR_UNSUPPORTED_PURPOSE;
+    }
+
+    switch (algorithm) {
+        case KM_ALGORITHM_RSA:
+            if ((purpose == KM_PURPOSE_SIGN) ||
+                (purpose == KM_PURPOSE_VERIFY))
+            {
+                supported_digests = &supported_rsa_sig_digests[0];
+                supported_digests_length = sizeof(supported_rsa_sig_digests);
+            } else if ((purpose == KM_PURPOSE_ENCRYPT) ||
+                       (purpose == KM_PURPOSE_DECRYPT))
+            {
+                supported_digests = &supported_rsa_crypt_digests[0];
+                supported_digests_length = sizeof(supported_rsa_crypt_digests);
+            }
+            break;
+        case KM_ALGORITHM_EC:
+            if ((purpose == KM_PURPOSE_SIGN) ||
+                (purpose == KM_PURPOSE_VERIFY))
+            {
+                supported_digests = &supported_ec_digests[0];
+                supported_digests_length = sizeof(supported_ec_digests);
+            }
+            break;
+        case KM_ALGORITHM_HMAC:
+            if ((purpose == KM_PURPOSE_SIGN) ||
+                (purpose == KM_PURPOSE_VERIFY))
+            {
+                supported_digests = &supported_hmac_digests[0];
+                supported_digests_length = sizeof(supported_hmac_digests);
+            }
+            break;
+        default: /* shouldn't get here */
+            break;
+    }
+
+    *digests = NULL;
+    *digests_length = 0;
+
+    if (supported_digests != NULL) {
+        *digests = reinterpret_cast<keymaster_digest_t*>(malloc(supported_digests_length));
+        if (*digests == NULL) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+
+        memcpy(*digests, supported_digests, supported_digests_length);
+        *digests_length = supported_digests_length / sizeof(keymaster_digest_t);
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_supported_import_formats(
+    keymaster_algorithm_t           algorithm,
+    keymaster_key_format_t**        formats,
+    size_t*                         formats_length)
+{
+    const keymaster_key_format_t* supported_key_formats = NULL;
+    size_t                 supported_key_formats_length = 0;
+
+    if ((formats == NULL) || (formats_length == NULL)) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    switch (algorithm) {
+        case KM_ALGORITHM_RSA:
+        case KM_ALGORITHM_EC:
+            supported_key_formats = &asymmetric_key_import_formats[0];
+            supported_key_formats_length = sizeof(asymmetric_key_import_formats);
+            break;
+        case KM_ALGORITHM_AES:
+        case KM_ALGORITHM_HMAC:
+            supported_key_formats = &symmetric_key_import_formats[0];
+            supported_key_formats_length = sizeof(symmetric_key_import_formats);
+            break;
+        default:
+            break;
+    }
+
+    *formats = NULL;
+    *formats_length = 0;
+    if (supported_key_formats != NULL) {
+        *formats = reinterpret_cast<keymaster_key_format_t*>(malloc(supported_key_formats_length));
+        if (*formats == NULL) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+        memcpy(*formats, supported_key_formats, supported_key_formats_length);
+        *formats_length = supported_key_formats_length / sizeof(keymaster_key_format_t);
+    }
+
+    return KM_ERROR_OK;
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_supported_export_formats(
+    keymaster_algorithm_t            algorithm,
+    keymaster_key_format_t**         formats,
+    size_t*                          formats_length)
+{
+    const keymaster_key_format_t* supported_key_formats = NULL;
+    size_t                 supported_key_formats_length = 0;
+
+    if ((formats == NULL) || (formats_length == NULL)) {
+        return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    }
+
+    switch (algorithm)
+    {
+        case KM_ALGORITHM_RSA:
+        case KM_ALGORITHM_EC:
+            supported_key_formats = &public_key_export_formats[0];
+            supported_key_formats_length = sizeof(public_key_export_formats);
+            break;
+        default:
+            break;
+    }
+
+    *formats = NULL;
+    *formats_length = 0;
+    if (supported_key_formats != NULL) {
+        *formats = reinterpret_cast<keymaster_key_format_t*>(malloc(supported_key_formats_length));
+        if (*formats == NULL) {
+            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        }
+        memcpy(*formats, supported_key_formats, supported_key_formats_length);
+        *formats_length = supported_key_formats_length / sizeof(keymaster_key_format_t);
+    }
+
+    return KM_ERROR_OK;
+}
+
+#define CHECK_SESSION(handle) \
+        if (handle == NULL) { \
+            LOG_E("%s: Invalid session handle", __func__); \
+            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED; \
+        }\
+
+keymaster_error_t TrustonicTeeKeymasterImpl::add_rng_entropy(
+    const uint8_t*                  data,
+    size_t                          data_length)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_AddRngEntropy(session_handle_, data, data_length);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::generate_key(
+    const keymaster_key_param_set_t*    params,
+    keymaster_key_blob_t*               key_blob,
+    keymaster_key_characteristics_t**   characteristics)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_GenerateKey(session_handle_,
+        params, key_blob, characteristics);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::get_key_characteristics(
+    const keymaster_key_blob_t*     key_blob,
+    const keymaster_blob_t*         client_id,
+    const keymaster_blob_t*         app_data,
+    keymaster_key_characteristics_t** characteristics)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_GetKeyCharacteristics(session_handle_,
+        key_blob, client_id, app_data, characteristics);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::import_key(
+    const keymaster_key_param_set_t* params,
+    keymaster_key_format_t          key_format,
+    const keymaster_blob_t*         key_data,
+    keymaster_key_blob_t*           key_blob,
+    keymaster_key_characteristics_t** characteristics)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_ImportKey(session_handle_,
+        params, key_format, key_data, key_blob, characteristics);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::export_key(
+    keymaster_key_format_t          export_format,
+    const keymaster_key_blob_t*     key_to_export,
+    const keymaster_blob_t*         client_id,
+    const keymaster_blob_t*         app_data,
+    keymaster_blob_t*               export_data)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_ExportKey(session_handle_,
+        export_format, key_to_export, client_id, app_data, export_data);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::begin(
+    keymaster_purpose_t             purpose,
+    const keymaster_key_blob_t*     key,
+    const keymaster_key_param_set_t* params,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_operation_handle_t*   operation_handle)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_Begin(session_handle_,
+        purpose, key, params, out_params, operation_handle);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::update(
+    keymaster_operation_handle_t    operation_handle,
+    const keymaster_key_param_set_t* params,
+    const keymaster_blob_t*         input,
+    size_t*                         input_consumed,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_blob_t*               output)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_Update(session_handle_,
+        operation_handle, params, input, input_consumed, out_params, output);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::finish(
+    keymaster_operation_handle_t    operation_handle,
+    const keymaster_key_param_set_t* params,
+    const keymaster_blob_t*         signature,
+    keymaster_key_param_set_t*      out_params,
+    keymaster_blob_t*               output)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_Finish(session_handle_,
+        operation_handle, params, signature, out_params, output);
+}
+
+keymaster_error_t TrustonicTeeKeymasterImpl::abort(
+    keymaster_operation_handle_t    operation_handle)
+{
+    CHECK_SESSION(session_handle_);
+    return TEE_Abort(session_handle_, operation_handle);
+}
diff --git a/libkeymaster/ver1/test/testTeeKeymaster.cpp b/libkeymaster/ver1/test/testTeeKeymaster.cpp
new file mode 100644 (file)
index 0000000..6bc9a03
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include "tee_keymaster_device.h"
+#include "test_km_aes.h"
+#include "test_km_hmac.h"
+#include "test_km_rsa.h"
+#include "test_km_ec.h"
+#include "test_km_restrictions.h"
+#include "test_km_util.h"
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+extern bool am_big_endian;
+extern struct keystore_module HAL_MODULE_INFO_SYM;
+
+static keymaster_error_t isAlgorithmSupported(
+        keymaster_algorithm_t*  algorithms,
+        size_t                  len,
+        keymaster_algorithm_t   algorithm)
+{
+    if ((algorithms == NULL) || (len == 0)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    for (size_t i = 0; i < len; i++) {
+        if (algorithms[i] == algorithm) {
+            return KM_ERROR_OK;
+        }
+    }
+
+    return KM_ERROR_UNSUPPORTED_ALGORITHM;
+}
+
+
+static keymaster_error_t isBlockModeSupported(
+        keymaster_block_mode_t*  modes,
+        size_t                   len,
+        keymaster_block_mode_t   mode)
+{
+    if ((modes == NULL) || (len == 0)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    for (size_t i = 0; i < len; i++) {
+        if (modes[i] == mode) {
+            return KM_ERROR_OK;
+        }
+    }
+
+    return KM_ERROR_UNSUPPORTED_BLOCK_MODE;
+}
+
+
+static keymaster_error_t isPaddingSupported(
+        keymaster_padding_t*    paddings,
+        size_t                  len,
+        keymaster_padding_t     padding)
+{
+    if ((paddings == NULL) || (len == 0)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    for (size_t i = 0; i < len; i++) {
+        if (paddings[i] == padding) {
+            return KM_ERROR_OK;
+        }
+    }
+
+    return KM_ERROR_UNSUPPORTED_PADDING_MODE;
+}
+
+
+static keymaster_error_t isDigestSupported(
+        keymaster_digest_t*     digests,
+        size_t                  len,
+        keymaster_digest_t      digest)
+{
+    if ((digests == NULL) || (len == 0)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    for (size_t i = 0; i < len; i++) {
+        if (digests[i] == digest) {
+            return KM_ERROR_OK;
+        }
+    }
+
+    return KM_ERROR_UNSUPPORTED_DIGEST;
+}
+
+
+static keymaster_error_t isKeyFormatSupported(
+        keymaster_key_format_t*  key_formats,
+        size_t                   len,
+        keymaster_key_format_t   key_format)
+{
+    if ((key_formats == NULL) || (len == 0)) {
+        return KM_ERROR_UNEXPECTED_NULL_POINTER;
+    }
+
+    for (size_t i = 0; i < len; i++) {
+        if (key_formats[i] == key_format) {
+            return KM_ERROR_OK;
+        }
+    }
+
+    return KM_ERROR_UNSUPPORTED_KEY_FORMAT;
+}
+
+/**
+ * Smoke test
+ *
+ * @param device device
+ *
+ * @return KM_ERROR_OK or error
+ */
+static keymaster_error_t test_api(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_algorithm_t *algorithms = NULL;
+    keymaster_block_mode_t *block_modes = NULL;
+    keymaster_padding_t *paddings = NULL;
+    keymaster_digest_t *digests = NULL;
+    keymaster_key_format_t *key_formats = NULL;
+    size_t len;
+    keymaster_key_param_t key_params[7];
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_operation_handle_t operation_handle;
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+    uint8_t test_entropy[] = { 0x65, 0x6e, 0x74, 0x72, 0x6f, 0x70, 0x79 };
+    uint8_t rsa_input_data[] = {0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61};
+    uint8_t *ptr_rsa_output_data = NULL;;
+    size_t rsa_input_data_len = sizeof(rsa_input_data);
+    size_t input_consumed;
+    keymaster_key_param_set_t paramset = {key_params, 0};
+    keymaster_blob_t rsa_input_data_blob = {rsa_input_data, rsa_input_data_len};
+    keymaster_blob_t rsa_output_data_blob = {ptr_rsa_output_data, 0};
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing get_supported_algorithms API...");
+    CHECK_RESULT_OK(device->get_supported_algorithms(device, &algorithms, &len));
+    CHECK_RESULT_OK(isAlgorithmSupported(algorithms, len, KM_ALGORITHM_RSA));
+    CHECK_RESULT_OK(isAlgorithmSupported(algorithms, len, KM_ALGORITHM_EC));
+    CHECK_RESULT_OK(isAlgorithmSupported(algorithms, len, KM_ALGORITHM_AES));
+    CHECK_RESULT_OK(isAlgorithmSupported(algorithms, len, KM_ALGORITHM_HMAC));
+    FREE(algorithms);
+    CHECK_RESULT(KM_ERROR_OUTPUT_PARAMETER_NULL,
+        device->get_supported_algorithms(device, NULL, NULL));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing get_supported_block_modes API...");
+    CHECK_RESULT_OK(device->get_supported_block_modes(device,
+        KM_ALGORITHM_AES, KM_PURPOSE_ENCRYPT, &block_modes, &len));
+    CHECK_RESULT_OK(isBlockModeSupported(block_modes, len, KM_MODE_ECB));
+    CHECK_RESULT_OK(isBlockModeSupported(block_modes, len, KM_MODE_CBC));
+    CHECK_RESULT_OK(isBlockModeSupported(block_modes, len, KM_MODE_CTR));
+    FREE(block_modes);
+    CHECK_RESULT_OK(device->get_supported_block_modes(device,
+        KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT, &block_modes, &len));
+    CHECK_RESULT_OK(isBlockModeSupported(block_modes, len, KM_MODE_ECB));
+    CHECK_RESULT_OK(isBlockModeSupported(block_modes, len, KM_MODE_CBC));
+    CHECK_RESULT_OK(isBlockModeSupported(block_modes, len, KM_MODE_CTR));
+    FREE(block_modes);
+    CHECK_RESULT_OK(device->get_supported_block_modes(device,
+        KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, &block_modes, &len));
+    CHECK_TRUE(len == 0);
+    FREE(block_modes);
+    CHECK_RESULT_OK(device->get_supported_block_modes(device,
+        KM_ALGORITHM_EC, KM_PURPOSE_SIGN, &block_modes, &len));
+    CHECK_TRUE(len == 0);
+    FREE(block_modes);
+    CHECK_RESULT_OK(device->get_supported_block_modes(device,
+        KM_ALGORITHM_HMAC, KM_PURPOSE_SIGN, &block_modes, &len));
+    CHECK_TRUE(len == 0);
+    FREE(block_modes);
+    CHECK_RESULT(KM_ERROR_OUTPUT_PARAMETER_NULL,
+        device->get_supported_block_modes(device, KM_ALGORITHM_HMAC, KM_PURPOSE_SIGN, NULL, NULL));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing get_supported_padding_modes API...");
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_AES, KM_PURPOSE_ENCRYPT, &paddings, &len));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_NONE));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_PKCS7));
+    FREE(paddings);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT, &paddings, &len));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_NONE));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_PKCS7));
+    FREE(paddings);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, &paddings, &len));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_PKCS1_1_5_SIGN));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_PSS));
+    FREE(paddings);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_RSA, KM_PURPOSE_VERIFY, &paddings, &len));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_PKCS1_1_5_SIGN));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_PSS));
+    FREE(paddings);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_RSA, KM_PURPOSE_ENCRYPT, &paddings, &len));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_NONE));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_OAEP));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+    FREE(paddings);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_RSA, KM_PURPOSE_DECRYPT, &paddings, &len));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_NONE));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_OAEP));
+    CHECK_RESULT_OK(isPaddingSupported(paddings, len, KM_PAD_RSA_PKCS1_1_5_ENCRYPT));
+    FREE(paddings);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_EC, KM_PURPOSE_SIGN, &paddings, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_EC, KM_PURPOSE_VERIFY, &paddings, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_HMAC, KM_PURPOSE_SIGN, &paddings, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT_OK(device->get_supported_padding_modes(device,
+        KM_ALGORITHM_HMAC, KM_PURPOSE_VERIFY, &paddings, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT(KM_ERROR_OUTPUT_PARAMETER_NULL,
+        device->get_supported_padding_modes(device, KM_ALGORITHM_HMAC, KM_PURPOSE_VERIFY, NULL, NULL));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing get_supported_digests API...");
+    CHECK_RESULT_OK(device->get_supported_digests(device,
+        KM_ALGORITHM_RSA, KM_PURPOSE_SIGN, &digests, &len));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA_2_256));
+    FREE(digests);
+    CHECK_RESULT_OK(device->get_supported_digests(device,
+        KM_ALGORITHM_HMAC, KM_PURPOSE_SIGN, &digests, &len));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA1));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA_2_224));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA_2_256));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA_2_384));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA_2_512));
+    CHECK_RESULT(KM_ERROR_UNSUPPORTED_DIGEST,
+        isDigestSupported(digests, len, KM_DIGEST_NONE));
+    FREE(digests);
+    CHECK_RESULT_OK(device->get_supported_digests(device,
+        KM_ALGORITHM_EC, KM_PURPOSE_SIGN, &digests, &len));
+    CHECK_RESULT_OK(isDigestSupported(digests, len, KM_DIGEST_SHA1));
+    FREE(digests);
+    CHECK_RESULT_OK(device->get_supported_digests(device,
+        KM_ALGORITHM_AES, KM_PURPOSE_ENCRYPT, &digests, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT_OK(device->get_supported_digests(device,
+        KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT, &digests, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT(KM_ERROR_OUTPUT_PARAMETER_NULL,
+        device->get_supported_digests(device, KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT, NULL, NULL));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing get_supported_import_formats API...");
+    CHECK_RESULT_OK(device->get_supported_import_formats(device,
+        KM_ALGORITHM_RSA, &key_formats, &len));
+    CHECK_RESULT_OK(isKeyFormatSupported(key_formats, len, KM_KEY_FORMAT_PKCS8));
+    FREE(key_formats);
+    CHECK_RESULT_OK(device->get_supported_import_formats(device,
+        KM_ALGORITHM_EC, &key_formats, &len));
+    CHECK_RESULT_OK(isKeyFormatSupported(key_formats, len, KM_KEY_FORMAT_PKCS8));
+    FREE(key_formats);
+    CHECK_RESULT_OK(device->get_supported_import_formats(device,
+        KM_ALGORITHM_AES, &key_formats, &len));
+    CHECK_RESULT_OK(isKeyFormatSupported(key_formats, len, KM_KEY_FORMAT_RAW));
+    FREE(key_formats);
+    CHECK_RESULT_OK(device->get_supported_import_formats(device,
+        KM_ALGORITHM_HMAC, &key_formats, &len));
+    CHECK_RESULT_OK(isKeyFormatSupported(key_formats, len, KM_KEY_FORMAT_RAW));
+    FREE(key_formats);
+    CHECK_RESULT(KM_ERROR_OUTPUT_PARAMETER_NULL,
+        device->get_supported_import_formats(device, KM_ALGORITHM_RSA, NULL, NULL));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing get_supported_export_formats API...");
+    CHECK_RESULT_OK(device->get_supported_export_formats(device,
+        KM_ALGORITHM_RSA, &key_formats, &len));
+    CHECK_RESULT_OK(isKeyFormatSupported(key_formats, len, KM_KEY_FORMAT_X509));
+    FREE(key_formats);
+    CHECK_RESULT_OK(device->get_supported_export_formats(device,
+        KM_ALGORITHM_EC, &key_formats, &len));
+    CHECK_RESULT_OK(isKeyFormatSupported(key_formats, len, KM_KEY_FORMAT_X509));
+    FREE(key_formats);
+    CHECK_RESULT_OK(device->get_supported_export_formats(device,
+        KM_ALGORITHM_AES, &key_formats, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT_OK(device->get_supported_export_formats(device,
+        KM_ALGORITHM_HMAC, &key_formats, &len));
+    CHECK_TRUE(len == 0);
+    CHECK_RESULT(KM_ERROR_OUTPUT_PARAMETER_NULL,
+        device->get_supported_export_formats(device, KM_ALGORITHM_RSA, NULL, NULL));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing add_rng_entropy API...");
+    CHECK_RESULT_OK(device->add_rng_entropy(device,
+        &test_entropy[0], sizeof(test_entropy)));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing generate_key API...");
+    key_params[0].tag = KM_TAG_ALGORITHM;
+    key_params[0].enumerated = KM_ALGORITHM_RSA;
+    key_params[1].tag = KM_TAG_KEY_SIZE;
+    key_params[1].integer = 1024;
+    key_params[2].tag = KM_TAG_RSA_PUBLIC_EXPONENT;
+    key_params[2].long_integer = 65537;
+    key_params[3].tag = KM_TAG_PURPOSE;
+    key_params[3].enumerated = KM_PURPOSE_SIGN;
+    key_params[4].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_params[4].boolean = true;
+    key_params[5].tag = KM_TAG_PADDING;
+    key_params[5].enumerated = KM_PAD_RSA_PSS;
+    key_params[6].tag = KM_TAG_DIGEST;
+    key_params[6].enumerated = KM_DIGEST_SHA1;
+    paramset.length = 7;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &paramset, &key_blob, &pkey_characteristics));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing begin API...");
+    key_params[0].tag = KM_TAG_ALGORITHM;
+    key_params[0].enumerated = KM_ALGORITHM_RSA;
+    key_params[1].tag = KM_TAG_PADDING;
+    key_params[1].enumerated = KM_PAD_RSA_PSS;
+    key_params[2].tag = KM_TAG_DIGEST;
+    key_params[2].enumerated = KM_DIGEST_SHA1;
+    key_params[3].tag = KM_TAG_PURPOSE;
+    key_params[3].enumerated = KM_PURPOSE_SIGN;
+    paramset.length = 4;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, &key_blob, &paramset, NULL, &operation_handle));
+
+    LOG_I("Testing update API...");
+    CHECK_RESULT_OK(device->update(device,
+        operation_handle, NULL, &rsa_input_data_blob, &input_consumed, NULL, NULL));
+
+    LOG_I("Testing finish API...");
+    CHECK_RESULT_OK(device->finish(device,
+        operation_handle, NULL, NULL, NULL, &rsa_output_data_blob));
+    LOG_I("Data length: %zu", rsa_output_data_blob.data_length);
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
+
+int main(void)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    TeeKeymasterDevice *device = new TeeKeymasterDevice(&HAL_MODULE_INFO_SYM.common);
+    keymaster1_device_t *keymaster_device = device->keymaster_device();
+    uint32_t rsa_key_sizes_to_test[] = {512, 1024, 4096};
+    uint32_t keysize;
+
+    /* Determine endianness of platform. */
+    {const int a = 1; am_big_endian = (*((char*)&a) == 0);}
+
+    LOG_I("Keymaster Module");
+    LOG_I("Name: %s", keymaster_device->common.module->name);
+    LOG_I("Author: %s", keymaster_device->common.module->author);
+    LOG_I("API version: %d" ,keymaster_device->common.module->module_api_version);
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("API smoke test...");
+    CHECK_RESULT_OK(test_api(keymaster_device));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing AES...");
+    for (uint32_t keysize = 128; keysize <= 256; keysize += 64) {
+        CHECK_RESULT_OK(test_km_aes(keymaster_device, keysize));
+    }
+
+    LOG_I("AES import and KAT...");
+    CHECK_RESULT_OK(test_km_aes_import(keymaster_device));
+
+    LOG_I("Try importing AES key with bad length...");
+    CHECK_RESULT_OK(test_km_aes_import_bad_length(keymaster_device));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing HMAC: KM_DIGEST_SHA1...");
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA1, 140));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA1, 160));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA1, 180));
+    LOG_I("Testing HMAC: KM_DIGEST_SHA_2_224...");
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_224, 200));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_224, 224));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_224, 248));
+    LOG_I("Testing HMAC: KM_DIGEST_SHA_2_256...");
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_256, 224));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_256, 256));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_256, 288));
+    LOG_I("Testing HMAC: KM_DIGEST_SHA_2_384...");
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_384, 360));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_384, 384));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_384, 408));
+    LOG_I("Testing HMAC: KM_DIGEST_SHA_2_512...");
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_512, 500));
+    CHECK_RESULT_OK(test_km_hmac(keymaster_device, KM_DIGEST_SHA_2_512, 512));
+
+    LOG_I("HMAC import and KAT...");
+    CHECK_RESULT_OK(test_km_hmac_import(keymaster_device));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing RSA...");
+    for (uint32_t i = 0; i < sizeof(rsa_key_sizes_to_test)/sizeof(uint32_t); i++) {
+        keysize = rsa_key_sizes_to_test[i];
+        CHECK_RESULT_OK(test_km_rsa(keymaster_device, keysize, 65537));
+        CHECK_RESULT_OK(test_km_rsa(keymaster_device, keysize, 17));
+    }
+
+    LOG_I("RSA import and export...");
+    CHECK_RESULT_OK(test_km_rsa_import_export(keymaster_device));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing ECDSA (P192)...");
+    CHECK_RESULT_OK(test_km_ec(keymaster_device, 192));
+    LOG_I("Testing ECDSA (P224)...");
+    CHECK_RESULT_OK(test_km_ec(keymaster_device, 224));
+    LOG_I("Testing ECDSA (P256)...");
+    CHECK_RESULT_OK(test_km_ec(keymaster_device, 256));
+    LOG_I("Testing ECDSA (P384)...");
+    CHECK_RESULT_OK(test_km_ec(keymaster_device, 384));
+    LOG_I("Testing ECDSA (P521)...");
+    CHECK_RESULT_OK(test_km_ec(keymaster_device, 521));
+
+    LOG_I("EC import and export...");
+    CHECK_RESULT_OK(test_km_ec_import_export(keymaster_device));
+
+    //--------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+    LOG_I("Testing key restrictions...");
+    CHECK_RESULT_OK(test_km_restrictions(keymaster_device));
+end:
+    return res;
+}
diff --git a/libkeymaster/ver1/test/test_km_aes.cpp b/libkeymaster/ver1/test/test_km_aes.cpp
new file mode 100644 (file)
index 0000000..3eab9e7
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hardware/keymaster1.h>
+#include <assert.h>
+
+#include "test_km_aes.h"
+#include "test_km_util.h"
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+static keymaster_error_t test_km_aes_roundtrip(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    keymaster_block_mode_t mode,
+    size_t msg_part1_len,
+    size_t msg_part2_len)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[2];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t nonce;
+    uint8_t nonce_bytes[16];
+    uint8_t input[64];
+    keymaster_blob_t input_blob = {0, 0};
+    keymaster_blob_t enc_output1 = {0, 0};
+    keymaster_blob_t enc_output2 = {0, 0};
+    keymaster_blob_t dec_output1 = {0, 0};
+    keymaster_blob_t dec_output2 = {0, 0};
+    size_t input_consumed = 0;
+
+    assert(msg_part1_len + msg_part2_len <= 64);
+
+    /* populate input message */
+    memset(input, 7, sizeof(input));
+
+    /* populate nonce */
+    memset(nonce_bytes, 3, 16);
+    nonce.data = &nonce_bytes[0];
+    nonce.data_length = (mode == KM_MODE_GCM) ? 12 : 16;
+
+    key_param[0].tag = KM_TAG_BLOCK_MODE;
+    key_param[0].enumerated = mode;
+    key_param[1].tag = KM_TAG_NONCE; // ignored for ECB
+    key_param[1].blob = nonce;
+    paramset.length = 2;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    input_blob.data = &input[0];
+    input_blob.data_length = msg_part1_len;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &input_blob, // first half of message
+        &input_consumed,
+        NULL, // no out_params
+        &enc_output1));
+    CHECK_TRUE(input_consumed == msg_part1_len);
+    CHECK_TRUE(enc_output1.data_length == msg_part1_len);
+
+    input_blob.data = input + msg_part1_len;
+    input_blob.data_length = msg_part2_len;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &input_blob, // second half of message
+        &input_consumed,
+        NULL, // no out_params
+        &enc_output2));
+    CHECK_TRUE(input_consumed == msg_part2_len);
+    CHECK_TRUE(enc_output2.data_length == msg_part2_len);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        NULL));
+
+    // key_params as for encrypt above
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &enc_output1, // first half of ciphertext
+        &input_consumed,
+        NULL, // no out_params
+        &dec_output1));
+    CHECK_TRUE(input_consumed == msg_part1_len);
+    CHECK_TRUE(dec_output1.data_length == msg_part1_len);
+
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &enc_output2, // second half of ciphertext
+        &input_consumed,
+        NULL, // no out_params
+        &dec_output2));
+    CHECK_TRUE(input_consumed == msg_part2_len);
+    CHECK_TRUE(dec_output2.data_length == msg_part2_len);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        NULL));
+
+    CHECK_TRUE((memcmp(&input[0], dec_output1.data, msg_part1_len) == 0) &&
+               (memcmp(&input[msg_part1_len], dec_output2.data, msg_part2_len) == 0));
+
+end:
+    km_free_blob(&enc_output1);
+    km_free_blob(&enc_output2);
+    km_free_blob(&dec_output1);
+    km_free_blob(&dec_output2);
+
+    return res;
+}
+
+static keymaster_error_t test_km_aes_roundtrip_noncegen(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    keymaster_block_mode_t mode)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t param[2];
+    keymaster_key_param_set_t paramset = {param, 0};
+    keymaster_key_param_set_t out_paramset = {NULL, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t input[16];
+    keymaster_blob_t input_blob = {input, sizeof(input)};
+    keymaster_blob_t enc_output = {0, 0};
+    keymaster_blob_t enc_output1 = {0, 0};
+    keymaster_blob_t dec_output = {0, 0};
+    size_t input_consumed = 0;
+    keymaster_blob_t nonce;
+    uint8_t nonce_bytes[16];
+
+    /* populate input message */
+    memset(input, 7, sizeof(input));
+
+    /* initialize nonce */
+    nonce.data = nonce_bytes;
+    nonce.data_length = (mode == KM_MODE_GCM) ? 12 : 16;
+
+    param[0].tag = KM_TAG_BLOCK_MODE;
+    param[0].enumerated = mode;
+    paramset.length = 1;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, &out_paramset, &handle));
+    CHECK_TRUE(out_paramset.length == 1);
+    CHECK_TRUE(out_paramset.params[0].tag == KM_TAG_NONCE);
+    CHECK_TRUE(out_paramset.params[0].blob.data_length == 16);
+    memcpy(nonce_bytes, out_paramset.params[0].blob.data, 16);
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output));
+    CHECK_TRUE(input_consumed == sizeof(input));
+    CHECK_TRUE(enc_output.data_length == sizeof(input));
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, NULL));
+
+    // Try again supplying same nonce -- should get same ciphertext.
+    param[1].tag = KM_TAG_NONCE;
+    param[1].blob = nonce;
+    paramset.length = 2;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output1));
+    CHECK_TRUE(input_consumed == sizeof(input));
+    CHECK_TRUE(enc_output1.data_length == sizeof(input));
+    CHECK_TRUE(memcmp(enc_output.data, enc_output1.data, sizeof(input)) == 0);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, NULL));
+
+    // And now decrypt
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output,  &input_consumed, NULL, &dec_output));
+    CHECK_TRUE(input_consumed == sizeof(input));
+    CHECK_TRUE(dec_output.data_length == sizeof(input));
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, NULL));
+
+    CHECK_TRUE(memcmp(input, dec_output.data, sizeof(input)) == 0);
+
+end:
+    km_free_blob(&enc_output);
+    km_free_blob(&enc_output1);
+    km_free_blob(&dec_output);
+    keymaster_free_param_set(&out_paramset);
+
+    return res;
+}
+
+static keymaster_error_t test_km_aes_gcm_roundtrip_noncegen(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t param[3];
+    keymaster_key_param_set_t paramset = {param, 0};
+    keymaster_key_param_set_t out_paramset = {NULL, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t input[16];
+    keymaster_blob_t input_blob = {input, sizeof(input)};
+    keymaster_blob_t enc_output = {0, 0};
+    keymaster_blob_t enc_output1 = {0, 0};
+    keymaster_blob_t dec_output = {0, 0};
+    keymaster_blob_t dec_final_output = {0, 0};
+    keymaster_blob_t tag = {0, 0};
+    keymaster_blob_t tag1 = {0, 0};
+    size_t input_consumed = 0;
+    keymaster_blob_t nonce;
+    uint8_t nonce_bytes[12];
+
+    /* populate input message */
+    memset(input, 7, sizeof(input));
+
+    /* initialize nonce */
+    nonce.data = nonce_bytes;
+    nonce.data_length = sizeof(nonce_bytes);
+
+    param[0].tag = KM_TAG_BLOCK_MODE;
+    param[0].enumerated = KM_MODE_GCM;
+    param[1].tag = KM_TAG_MAC_LENGTH;
+    param[1].integer = 128;
+    paramset.length = 2;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, &out_paramset, &handle));
+    CHECK_TRUE(out_paramset.length == 1);
+    CHECK_TRUE(out_paramset.params[0].tag == KM_TAG_NONCE);
+    CHECK_TRUE(out_paramset.params[0].blob.data_length == 12);
+    memcpy(nonce_bytes, out_paramset.params[0].blob.data, 12);
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output));
+    CHECK_TRUE(input_consumed == sizeof(input));
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &tag));
+
+    // Try again supplying same nonce -- should get same ciphertext.
+    param[2].tag = KM_TAG_NONCE;
+    param[2].blob = nonce;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output1));
+    CHECK_TRUE(input_consumed == sizeof(input));
+    CHECK_TRUE(
+        (enc_output.data_length == enc_output1.data_length) &&
+        (memcmp(enc_output.data, enc_output1.data, enc_output.data_length) == 0));
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &tag1));
+    CHECK_TRUE(
+        (tag.data_length == tag1.data_length) &&
+        (memcmp(tag.data, tag1.data, tag.data_length) == 0));
+
+    // And now decrypt
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output, &input_consumed, NULL, &dec_output));
+    CHECK_TRUE(input_consumed == sizeof(input));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &tag, &input_consumed, NULL, &dec_final_output));
+    CHECK_TRUE(input_consumed == tag.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, NULL));
+
+    CHECK_TRUE(
+        (dec_output.data_length + dec_final_output.data_length == sizeof(input)) &&
+        (memcmp(&input[0], dec_output.data, dec_output.data_length) == 0) &&
+        (memcmp(&input[dec_output.data_length], dec_final_output.data, dec_final_output.data_length) == 0));
+
+end:
+    km_free_blob(&enc_output);
+    km_free_blob(&enc_output1);
+    km_free_blob(&dec_output);
+    km_free_blob(&dec_final_output);
+    km_free_blob(&tag);
+    km_free_blob(&tag1);
+    keymaster_free_param_set(&out_paramset);
+
+    return res;
+}
+
+static keymaster_error_t test_km_aes_pkcs7(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    keymaster_block_mode_t mode,
+    size_t message_len)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t nonce;
+    uint8_t nonce_bytes[16];
+    uint8_t input[64];
+    keymaster_blob_t input_blob = {0, 0};
+    keymaster_blob_t enc_output = {0, 0};
+    keymaster_blob_t enc_output1 = {0, 0};
+    keymaster_blob_t dec_output = {0, 0};
+    keymaster_blob_t dec_output1 = {0, 0};
+    keymaster_blob_t dec_output2 = {0, 0};
+    size_t input_consumed = 0;
+
+    assert(message_len <= 64);
+
+    /* populate input message */
+    memset(input, 7, sizeof(input));
+
+    /* populate nonce */
+    memset(nonce_bytes, 3, sizeof(nonce_bytes));
+    nonce.data = nonce_bytes;
+    nonce.data_length = sizeof(nonce_bytes);
+
+    key_param[0].tag = KM_TAG_BLOCK_MODE;
+    key_param[0].enumerated = mode;
+    key_param[1].tag = KM_TAG_NONCE; // ignored for ECB
+    key_param[1].blob = nonce;
+    key_param[2].tag = KM_TAG_PADDING;
+    key_param[2].enumerated = KM_PAD_PKCS7;
+    paramset.length = 3;
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+
+    input_blob.data = input;
+    input_blob.data_length = message_len;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output));
+    CHECK_TRUE(input_consumed == message_len);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &enc_output1));
+    CHECK_TRUE((enc_output.data_length + enc_output1.data_length > message_len) &&
+           (enc_output.data_length + enc_output1.data_length <= message_len + 16) &&
+           ((enc_output.data_length + enc_output1.data_length) % 16 == 0));
+
+    // key_params as for encrypt above
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output, &input_consumed, NULL, &dec_output));
+    CHECK_TRUE(input_consumed == enc_output.data_length);
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output1, &input_consumed, NULL, &dec_output1));
+    CHECK_TRUE(input_consumed == enc_output1.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &dec_output2));
+
+    CHECK_TRUE(dec_output.data_length + dec_output1.data_length + dec_output2.data_length == message_len);
+    CHECK_TRUE((memcmp(input, dec_output.data, dec_output.data_length) == 0) &&
+        (memcmp(input + dec_output.data_length, dec_output1.data, dec_output1.data_length) == 0) &&
+        (memcmp(input + dec_output.data_length + dec_output1.data_length, dec_output2.data, dec_output2.data_length) == 0));
+
+end:
+    km_free_blob(&enc_output);
+    km_free_blob(&enc_output1);
+    km_free_blob(&dec_output);
+    km_free_blob(&dec_output1);
+    km_free_blob(&dec_output2);
+
+    return res;
+}
+
+static keymaster_error_t test_km_aes_gcm_roundtrip(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t tagsize,
+    size_t msg_part1_len,
+    size_t msg_part2_len)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[4];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t nonce;
+    uint8_t nonce_bytes[12];
+    keymaster_blob_t aad;
+    uint8_t aad_bytes[23];
+    uint8_t input[64];
+    keymaster_blob_t input_blob = {0, 0};
+    keymaster_blob_t enc_output1 = {0, 0};
+    keymaster_blob_t enc_output2 = {0, 0};
+    keymaster_blob_t enc_output3 = {0, 0};
+    keymaster_blob_t dec_output1 = {0, 0};
+    keymaster_blob_t dec_output2 = {0, 0};
+    keymaster_blob_t dec_output3 = {0, 0};
+    size_t input_consumed = 0;
+
+    LOG_I("Using %u-bit tag ...", tagsize);
+
+    assert(msg_part1_len + msg_part2_len <= 64);
+
+    /* populate input message */
+    memset(input, 7, sizeof(input));
+
+    /* populate nonce */
+    memset(nonce_bytes, 3, sizeof(nonce_bytes));
+    nonce.data = &nonce_bytes[0];
+    nonce.data_length = sizeof(nonce_bytes);
+
+    /* populate AAD */
+    memset(aad_bytes, 11, sizeof(aad_bytes));
+    aad.data = &aad_bytes[0];
+    aad.data_length = sizeof(aad_bytes);
+
+    key_param[0].tag = KM_TAG_BLOCK_MODE;
+    key_param[0].enumerated = KM_MODE_GCM;
+    key_param[1].tag = KM_TAG_NONCE;
+    key_param[1].blob = nonce;
+    key_param[2].tag = KM_TAG_MAC_LENGTH;
+    key_param[2].integer = tagsize;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    input_blob.data = &input[0];
+    input_blob.data_length = msg_part1_len;
+    key_param[0].tag = KM_TAG_ASSOCIATED_DATA;
+    key_param[0].blob = aad;
+    paramset.length = 1;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        &paramset, // AAD
+        &input_blob, // first half of message
+        &input_consumed,
+        NULL, // no out_params
+        &enc_output1));
+    CHECK_TRUE(input_consumed == msg_part1_len);
+
+    input_blob.data = &input[msg_part1_len];
+    input_blob.data_length = msg_part2_len;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &input_blob, // second half of message
+        &input_consumed,
+        NULL, // no params
+        &enc_output2));
+    CHECK_TRUE(input_consumed == msg_part2_len);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &enc_output3));
+    CHECK_TRUE(enc_output1.data_length + enc_output2.data_length + enc_output3.data_length == msg_part1_len + msg_part2_len + tagsize/8);
+
+    key_param[0].tag = KM_TAG_BLOCK_MODE;
+    key_param[0].enumerated = KM_MODE_GCM;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT,
+        key_blob,
+        &paramset, // as for 'begin encrypt' above
+        NULL, // no out_params
+        &handle));
+
+    key_param[0].tag = KM_TAG_ASSOCIATED_DATA;
+    key_param[0].blob = aad;
+    paramset.length = 1;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        &paramset, // as for 'update encrypt (1)' above
+        &enc_output1, // first half of ciphertext
+        &input_consumed,
+        NULL, // no out_params
+        &dec_output1));
+    CHECK_TRUE(input_consumed == enc_output1.data_length);
+
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &enc_output2, // second half of ciphertext
+        &input_consumed,
+        NULL, // no out_params
+        &dec_output2));
+    CHECK_TRUE(input_consumed == enc_output2.data_length);
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output3, &input_consumed, NULL, &dec_output3));
+    CHECK_TRUE(input_consumed == enc_output3.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        NULL));
+
+    CHECK_TRUE((dec_output1.data_length + dec_output2.data_length + dec_output3.data_length == msg_part1_len + msg_part2_len) &&
+               (memcmp(&input[0], dec_output1.data, dec_output1.data_length) == 0) &&
+               (memcmp(&input[dec_output1.data_length], dec_output2.data, dec_output2.data_length) == 0) &&
+               (memcmp(&input[dec_output1.data_length + dec_output2.data_length], dec_output3.data, dec_output3.data_length) == 0));
+
+end:
+    km_free_blob(&enc_output1);
+    km_free_blob(&enc_output2);
+    km_free_blob(&enc_output3);
+    km_free_blob(&dec_output1);
+    km_free_blob(&dec_output2);
+    km_free_blob(&dec_output3);
+
+    return res;
+}
+
+/**
+ * Update AAD twice, then update cipher twice, each time with a single byte.
+ */
+static keymaster_error_t test_km_aes_gcm_roundtrip_incr(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t param[4];
+    keymaster_key_param_set_t paramset = {param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t nonce;
+    uint8_t nonce_bytes[12];
+    keymaster_blob_t aad;
+    uint8_t aad_byte = 11;
+    uint8_t input_byte = 7;
+    keymaster_blob_t input_blob = {0, 0};
+    keymaster_blob_t enc_output1 = {0, 0};
+    keymaster_blob_t enc_output2 = {0, 0};
+    keymaster_blob_t enc_output3 = {0, 0};
+    keymaster_blob_t dec_output1 = {0, 0};
+    keymaster_blob_t dec_output2 = {0, 0};
+    keymaster_blob_t dec_output3 = {0, 0};
+    size_t input_consumed = 0;
+
+    /* populate input blob */
+    input_blob.data = &input_byte;
+    input_blob.data_length = 1;
+
+    /* populate nonce */
+    memset(nonce_bytes, 3, sizeof(nonce_bytes));
+    nonce.data = &nonce_bytes[0];
+    nonce.data_length = sizeof(nonce_bytes);
+
+    /* populate AAD */
+    aad.data = &aad_byte;
+    aad.data_length = 1;
+
+    /* begin encrypt */
+    param[0].tag = KM_TAG_BLOCK_MODE;
+    param[0].enumerated = KM_MODE_GCM;
+    param[1].tag = KM_TAG_NONCE;
+    param[1].blob = nonce;
+    param[2].tag = KM_TAG_MAC_LENGTH;
+    param[2].integer = 128;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+
+    /* update AAD (twice) */
+    param[0].tag = KM_TAG_ASSOCIATED_DATA;
+    param[0].blob = aad;
+    paramset.length = 1;
+    for (int i = 0; i < 2; i++) {
+        CHECK_RESULT_OK(device->update(device,
+            handle, &paramset, NULL, &input_consumed, NULL, NULL));
+        CHECK_TRUE(input_consumed == 0);
+    }
+
+    /* update cipher (twice) */
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output1));
+    CHECK_TRUE(input_consumed == 1);
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &input_blob, &input_consumed, NULL, &enc_output2));
+    CHECK_TRUE(input_consumed == 1);
+
+    /* finish */
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &enc_output3));
+    CHECK_TRUE(enc_output1.data_length + enc_output2.data_length + enc_output3.data_length == 2 + 16);
+
+    /* begin decrypt */
+    param[0].tag = KM_TAG_BLOCK_MODE;
+    param[0].enumerated = KM_MODE_GCM;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+
+    /* update AAD (twice) */
+    param[0].tag = KM_TAG_ASSOCIATED_DATA;
+    param[0].blob = aad;
+    paramset.length = 1;
+    for (int i = 0; i < 2; i++) {
+        CHECK_RESULT_OK(device->update(device,
+            handle, &paramset, NULL, &input_consumed, NULL, NULL));
+        CHECK_TRUE(input_consumed == 0);
+    }
+
+    /* update cipher (three times) */
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output1, &input_consumed, NULL, &dec_output1));
+    CHECK_TRUE(input_consumed == enc_output1.data_length);
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output2, &input_consumed, NULL, &dec_output2));
+    CHECK_TRUE(input_consumed == enc_output2.data_length);
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output3, &input_consumed, NULL, &dec_output3));
+    CHECK_TRUE(input_consumed == enc_output3.data_length);
+
+    /* finish */
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, NULL));
+
+end:
+    km_free_blob(&enc_output1);
+    km_free_blob(&enc_output2);
+    km_free_blob(&enc_output3);
+    km_free_blob(&dec_output1);
+    km_free_blob(&dec_output2);
+    km_free_blob(&dec_output3);
+
+    return res;
+}
+
+keymaster_error_t test_km_aes_import(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[5];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t enc_output1 = {0, 0};
+    size_t input_consumed = 0;
+
+    /* First NIST test vector from ECBVarKey128.rsp
+       http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
+       KEY = 80000000000000000000000000000000
+       PLAINTEXT = 00000000000000000000000000000000
+       CIPHERTEXT = 0edd33d3c621e546455bd8ba1418bec8
+     */
+
+    const uint8_t key[16] = {
+        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    const uint8_t plaintext[16] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    const uint8_t ciphertext[16] = {
+        0x0e, 0xdd, 0x33, 0xd3, 0xc6, 0x21, 0xe5, 0x46,
+        0x45, 0x5b, 0xd8, 0xba, 0x14, 0x18, 0xbe, 0xc8};
+
+    const keymaster_blob_t key_data = {key, sizeof(key)};
+    const keymaster_blob_t plainblob = {plaintext, sizeof(plaintext)};
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_AES;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = 128;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_ENCRYPT;
+    key_param[4].tag = KM_TAG_BLOCK_MODE;
+    key_param[4].enumerated = KM_MODE_ECB;
+    paramset.length = 5;
+    CHECK_RESULT_OK(device->import_key(device,
+        &paramset,
+        KM_KEY_FORMAT_RAW,
+        &key_data,
+        &key_blob,
+        NULL));
+
+    key_param[0].tag = KM_TAG_BLOCK_MODE;
+    key_param[0].enumerated = KM_MODE_ECB;
+    paramset.length = 1;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT,
+        &key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &plainblob,
+        &input_consumed,
+        NULL, // no out_params
+        &enc_output1));
+    CHECK_TRUE(input_consumed == 16);
+    CHECK_TRUE(enc_output1.data_length == 16);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        NULL));
+
+    CHECK_TRUE(memcmp(enc_output1.data, ciphertext, 16) == 0);
+
+end:
+    km_free_key_blob(&key_blob);
+    km_free_blob(&enc_output1);
+
+    return res;
+}
+
+keymaster_error_t test_km_aes_import_bad_length(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[5];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+
+    const uint8_t key[16] = {
+        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+    keymaster_blob_t key_data = {key, sizeof(key)};
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_AES;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = 128;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_ENCRYPT;
+    key_param[4].tag = KM_TAG_BLOCK_MODE;
+    key_param[4].enumerated = KM_MODE_ECB;
+    paramset.length = 5;
+
+    CHECK_RESULT_OK(device->import_key(device,
+        &paramset, KM_KEY_FORMAT_RAW, &key_data, &key_blob, NULL));
+
+    km_free_key_blob(&key_blob);
+    key_data.data_length = 1;
+    key_param[1].integer = 8;
+    CHECK_RESULT(KM_ERROR_INVALID_ARGUMENT, device->import_key(device,
+        &paramset, KM_KEY_FORMAT_RAW, &key_data, &key_blob, NULL));
+
+    km_free_key_blob(&key_blob);
+    key_data.data_length = 0;
+    key_param[1].integer = 0;
+    CHECK_RESULT(KM_ERROR_INVALID_ARGUMENT, device->import_key(device,
+        &paramset, KM_KEY_FORMAT_RAW, &key_data, &key_blob, NULL));
+
+end:
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
+
+keymaster_error_t test_km_aes(
+    keymaster1_device_t *device,
+    uint32_t keysize)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[12];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+
+    LOG_I("Generate %d-bit key ...", keysize);
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_AES;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = keysize;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_ENCRYPT;
+    key_param[4].tag = KM_TAG_PURPOSE;
+    key_param[4].enumerated = KM_PURPOSE_DECRYPT;
+    key_param[5].tag = KM_TAG_BLOCK_MODE;
+    key_param[5].enumerated = KM_MODE_ECB;
+    key_param[6].tag = KM_TAG_BLOCK_MODE;
+    key_param[6].enumerated = KM_MODE_CBC;
+    key_param[7].tag = KM_TAG_BLOCK_MODE;
+    key_param[7].enumerated = KM_MODE_CTR;
+    key_param[8].tag = KM_TAG_BLOCK_MODE;
+    key_param[8].enumerated = KM_MODE_GCM;
+    key_param[9].tag = KM_TAG_CALLER_NONCE;
+    key_param[9].boolean = true;
+    key_param[10].tag = KM_TAG_PADDING;
+    key_param[10].enumerated = KM_PAD_PKCS7;
+    key_param[11].tag = KM_TAG_MIN_MAC_LENGTH;
+    key_param[11].integer = 96;
+    paramset.length = 12;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &paramset,
+        &key_blob,
+        NULL));
+
+    LOG_I("Test key characteristics ...");
+    CHECK_RESULT_OK(device->get_key_characteristics(device,
+        &key_blob,
+        NULL, // client_id
+        NULL, // app_data
+        &pkey_characteristics));
+    print_characteristics(pkey_characteristics);
+
+    LOG_I("ECB round trip ...");
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_ECB, 32, 32));
+
+    LOG_I("CBC round trip ...");
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CBC, 32, 32));
+    CHECK_RESULT_OK(test_km_aes_roundtrip_noncegen(device, &key_blob, KM_MODE_CBC));
+
+    LOG_I("CTR round trip ...");
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 32, 32));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 32, 31));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 15, 17));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 33, 16));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 16, 1));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 16, 17));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 16, 33));
+    CHECK_RESULT_OK(test_km_aes_roundtrip(device, &key_blob, KM_MODE_CTR, 15, 33));
+    CHECK_RESULT_OK(test_km_aes_roundtrip_noncegen(device, &key_blob, KM_MODE_CTR));
+
+    LOG_I("GCM round trip ...");
+    CHECK_RESULT_OK(test_km_aes_gcm_roundtrip(device, &key_blob, 96, 32, 32));
+    CHECK_RESULT_OK(test_km_aes_gcm_roundtrip(device, &key_blob, 128, 32, 32));
+    CHECK_RESULT_OK(test_km_aes_gcm_roundtrip(device, &key_blob, 96, 16, 2));
+    CHECK_RESULT_OK(test_km_aes_gcm_roundtrip(device, &key_blob, 128, 13, 15));
+    CHECK_RESULT_OK(test_km_aes_gcm_roundtrip_noncegen(device, &key_blob));
+    CHECK_RESULT_OK(test_km_aes_gcm_roundtrip_incr(device, &key_blob));
+
+    LOG_I("PKCS7 padding (ECB)...");
+    CHECK_RESULT_OK(test_km_aes_pkcs7(device, &key_blob, KM_MODE_ECB, 3));
+    CHECK_RESULT_OK(test_km_aes_pkcs7(device, &key_blob, KM_MODE_ECB, 16));
+    CHECK_RESULT_OK(test_km_aes_pkcs7(device, &key_blob, KM_MODE_ECB, 37));
+
+    LOG_I("PKCS7 padding (CBC)...");
+    CHECK_RESULT_OK(test_km_aes_pkcs7(device, &key_blob, KM_MODE_CBC, 3));
+    CHECK_RESULT_OK(test_km_aes_pkcs7(device, &key_blob, KM_MODE_CBC, 16));
+    CHECK_RESULT_OK(test_km_aes_pkcs7(device, &key_blob, KM_MODE_CBC, 37));
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
diff --git a/libkeymaster/ver1/test/test_km_aes.h b/libkeymaster/ver1/test/test_km_aes.h
new file mode 100644 (file)
index 0000000..b6b9fbf
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_KM_AES_H__
+#define __TEST_KM_AES_H__
+
+#include <hardware/keymaster1.h>
+
+keymaster_error_t test_km_aes_import(
+    keymaster1_device_t *device);
+
+keymaster_error_t test_km_aes_import_bad_length(
+    keymaster1_device_t *device);
+
+keymaster_error_t test_km_aes(
+    keymaster1_device_t *device,
+    uint32_t keysize);
+
+#endif /* __TEST_KM_AES_H__ */
diff --git a/libkeymaster/ver1/test/test_km_ec.cpp b/libkeymaster/ver1/test/test_km_ec.cpp
new file mode 100644 (file)
index 0000000..b081947
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <hardware/keymaster1.h>
+
+#include "test_km_ec.h"
+#include "test_km_util.h"
+
+#include <assert.h>
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+static keymaster_error_t test_km_ec_sign_verify(
+    keymaster1_device_t *device,
+    keymaster_key_blob_t *key_blob,
+    uint32_t keylen,
+    keymaster_digest_t digest)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[2];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message[1000];
+    keymaster_blob_t messageblob = {0, 0};
+    keymaster_blob_t sig_output = {0, 0};
+    size_t message_consumed = 0;
+
+    /* populate message */
+    memset(message, 25, sizeof(message));
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_EC;
+    key_param[1].tag = KM_TAG_DIGEST;
+    key_param[1].enumerated = digest;
+    paramset.length = 2;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    messageblob.data = &message[0];
+    messageblob.data_length = 630;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 630);
+
+    messageblob.data = &message[630];
+    messageblob.data_length = 370;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 370);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &sig_output));
+    CHECK_TRUE(sig_output.data_length <= 2*keylen + 9);
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY,
+        key_blob,
+        &paramset, // same as for KM_PURPOSE_SIGN
+        NULL, // no out_params
+        &handle));
+
+    messageblob.data = &message[0];
+    messageblob.data_length = 480;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 480);
+
+    messageblob.data = &message[480];
+    messageblob.data_length = 520;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 520);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        &sig_output,
+        NULL, // no out_params
+        NULL));
+
+end:
+    km_free_blob(&sig_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_ec_sign_verify_empty_message(
+    keymaster1_device_t *device,
+    keymaster_key_blob_t *key_blob,
+    uint32_t keylen,
+    keymaster_digest_t digest)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[2];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message;
+    keymaster_blob_t messageblob = {0, 0};
+    keymaster_blob_t sig_output = {0, 0};
+    size_t message_consumed = 0;
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_EC;
+    key_param[1].tag = KM_TAG_DIGEST;
+    key_param[1].enumerated = digest;
+    paramset.length = 2;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data = &message;
+    messageblob.data_length = 0;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 0);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &sig_output));
+    CHECK_TRUE(sig_output.data_length <= 2*keylen + 9);
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data = &message;
+    messageblob.data_length = 0;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 0);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, &sig_output, NULL, NULL));
+
+end:
+    km_free_blob(&sig_output);
+
+    return res;
+}
+
+keymaster_error_t test_km_ec_import_export(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[6];
+    keymaster_key_param_set_t key_paramset = {key_param, 6};
+    keymaster_key_blob_t key_blob = {NULL, 0};
+
+    /* Test vector from Android M PDK: system/keymaster/ec_privkey_pk8.der */
+    const uint8_t key[] = {
+        0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+        0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+        0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+        0x73, 0x7c, 0x2e, 0xcd, 0x7b, 0x8d, 0x19, 0x40, 0xbf, 0x29, 0x30, 0xaa,
+        0x9b, 0x4e, 0xd3, 0xff, 0x94, 0x1e, 0xed, 0x09, 0x36, 0x6b, 0xc0, 0x32,
+        0x99, 0x98, 0x64, 0x81, 0xf3, 0xa4, 0xd8, 0x59, 0xa1, 0x44, 0x03, 0x42,
+        0x00, 0x04, 0xbf, 0x85, 0xd7, 0x72, 0x0d, 0x07, 0xc2, 0x54, 0x61, 0x68,
+        0x3b, 0xc6, 0x48, 0xb4, 0x77, 0x8a, 0x9a, 0x14, 0xdd, 0x8a, 0x02, 0x4e,
+        0x3b, 0xdd, 0x8c, 0x7d, 0xdd, 0x9a, 0xb2, 0xb5, 0x28, 0xbb, 0xc7, 0xaa,
+        0x1b, 0x51, 0xf1, 0x4e, 0xbb, 0xbb, 0x0b, 0xd0, 0xce, 0x21, 0xbc, 0xc4,
+        0x1c, 0x6e, 0xb0, 0x00, 0x83, 0xcf, 0x33, 0x76, 0xd1, 0x1f, 0xd4, 0x49,
+        0x49, 0xe0, 0xb2, 0x18, 0x3b, 0xfe};
+
+    const keymaster_blob_t key_data = {key, sizeof(key)};
+
+    keymaster_blob_t export_data = {NULL, 0};
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_EC;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = 256;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_SIGN;
+    key_param[4].tag = KM_TAG_PURPOSE;
+    key_param[4].enumerated = KM_PURPOSE_VERIFY;
+    key_param[5].tag = KM_TAG_DIGEST;
+    key_param[5].enumerated = KM_DIGEST_SHA1;
+    CHECK_RESULT_OK(device->import_key(device,
+        &key_paramset, KM_KEY_FORMAT_PKCS8, &key_data, &key_blob, NULL));
+
+    CHECK_RESULT_OK(test_km_ec_sign_verify(
+        device, &key_blob, 32, KM_DIGEST_SHA1));
+
+    CHECK_RESULT_OK(device->export_key(device,
+        KM_KEY_FORMAT_X509, &key_blob, NULL, NULL, &export_data));
+
+end:
+    km_free_blob(&export_data);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
+
+keymaster_error_t test_km_ec_p521_interop(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[6];
+    keymaster_key_param_set_t key_paramset = {key_param, 6};
+    keymaster_key_param_t op_param[2];
+    keymaster_key_param_set_t op_paramset = {op_param, 2};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_operation_handle_t handle;
+    const char *message = "This is a test";
+    keymaster_blob_t messageblob = {(const uint8_t*)message, strlen(message)};
+    size_t message_consumed = 0;
+    keymaster_blob_t sig = {0, 0};
+
+    /* Test vector from Android M CTS: ec_key6_secp521r1_pkcs8.der */
+    const uint8_t key[] = {
+        0x30, 0x81, 0xED, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86,
+        0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23,
+        0x04, 0x81, 0xD5, 0x30, 0x81, 0xD2, 0x02, 0x01, 0x01, 0x04, 0x41, 0x11,
+        0x45, 0x8C, 0x58, 0x6D, 0xB5, 0xDA, 0xA9, 0x2A, 0xFA, 0xB0, 0x3F, 0x4F,
+        0xE4, 0x6A, 0xA9, 0xD9, 0xC3, 0xCE, 0x9A, 0x9B, 0x7A, 0x00, 0x6A, 0x83,
+        0x84, 0xBE, 0xC4, 0xC7, 0x8E, 0x8E, 0x9D, 0x18, 0xD7, 0xD0, 0x8B, 0x5B,
+        0xCF, 0xA0, 0xE5, 0x3C, 0x75, 0xB0, 0x64, 0xAD, 0x51, 0xC4, 0x49, 0xBA,
+        0xE0, 0x25, 0x8D, 0x54, 0xB9, 0x4B, 0x1E, 0x88, 0x5D, 0xED, 0x08, 0xED,
+        0x4F, 0xB2, 0x5C, 0xE9, 0xA1, 0x81, 0x89, 0x03, 0x81, 0x86, 0x00, 0x04,
+        0x01, 0x49, 0xEC, 0x11, 0xC6, 0xDF, 0x0F, 0xA1, 0x22, 0xC6, 0xA9, 0xAF,
+        0xD9, 0x75, 0x4A, 0x4F, 0xA9, 0x51, 0x3A, 0x62, 0x7C, 0xA3, 0x29, 0xE3,
+        0x49, 0x53, 0x5A, 0x56, 0x29, 0x87, 0x5A, 0x8A, 0xDF, 0xBE, 0x27, 0xDC,
+        0xB9, 0x32, 0xC0, 0x51, 0x98, 0x63, 0x77, 0x10, 0x8D, 0x05, 0x4C, 0x28,
+        0xC6, 0xF3, 0x9B, 0x6F, 0x2C, 0x9A, 0xF8, 0x18, 0x02, 0xF9, 0xF3, 0x26,
+        0xB8, 0x42, 0xFF, 0x2E, 0x5F, 0x3C, 0x00, 0xAB, 0x76, 0x35, 0xCF, 0xB3,
+        0x61, 0x57, 0xFC, 0x08, 0x82, 0xD5, 0x74, 0xA1, 0x0D, 0x83, 0x9C, 0x1A,
+        0x0C, 0x04, 0x9D, 0xC5, 0xE0, 0xD7, 0x75, 0xE2, 0xEE, 0x50, 0x67, 0x1A,
+        0x20, 0x84, 0x31, 0xBB, 0x45, 0xE7, 0x8E, 0x70, 0xBE, 0xFE, 0x93, 0x0D,
+        0xB3, 0x48, 0x18, 0xEE, 0x4D, 0x5C, 0x26, 0x25, 0x9F, 0x5C, 0x6B, 0x8E,
+        0x28, 0xA6, 0x52, 0x95, 0x0F, 0x9F, 0x88, 0xD7, 0xB4, 0xB2, 0xC9, 0xD9};
+
+    /* Signature generated by Bouncy Castle in CTS run */
+    const uint8_t bc_sig[138] = {
+        0x30, 0x81, 0x87, 0x02, 0x42, 0x01, 0x90, 0xef, 0xd1, 0x43, 0x8c, 0xf7,
+        0xd2, 0x73, 0x19, 0x46, 0x09, 0xce, 0x74, 0x82, 0x10, 0x08, 0x3c, 0xb9,
+        0x65, 0x1e, 0x04, 0xde, 0x34, 0x9d, 0x8f, 0x66, 0x2b, 0xf7, 0x2e, 0x62,
+        0x10, 0xf4, 0x9c, 0xf7, 0xf5, 0x71, 0x9e, 0x6a, 0x5a, 0xeb, 0xce, 0xb7,
+        0x28, 0xd8, 0xd5, 0xd1, 0x1e, 0x7f, 0x8b, 0x85, 0x29, 0xd7, 0x04, 0x88,
+        0x2a, 0xf1, 0x99, 0x50, 0x71, 0x78, 0xd0, 0x14, 0xa9, 0x93, 0x68, 0x02,
+        0x41, 0x5c, 0xc9, 0x15, 0xcc, 0xd2, 0x12, 0xf3, 0xdb, 0x42, 0x8a, 0x07,
+        0x51, 0x85, 0x8b, 0xb9, 0x98, 0xc9, 0x27, 0xc1, 0x77, 0xb0, 0x7b, 0xdb,
+        0xae, 0x5f, 0x5c, 0x42, 0xe8, 0x5e, 0x4b, 0x89, 0xed, 0x93, 0xba, 0x73,
+        0x04, 0x98, 0x6a, 0xc7, 0x38, 0xb6, 0x9c, 0x6b, 0xa9, 0x13, 0x04, 0xc3,
+        0x33, 0xaf, 0xcb, 0x85, 0x8d, 0xfa, 0x4a, 0x33, 0x8a, 0x09, 0xfc, 0xdb,
+        0x5d, 0x3f, 0xcf, 0x49, 0x3a, 0x12};
+
+    const keymaster_blob_t key_data = {key, sizeof(key)};
+    const keymaster_blob_t bc_sig_blob = {bc_sig, sizeof(bc_sig)};
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_EC;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = 521;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_SIGN;
+    key_param[4].tag = KM_TAG_PURPOSE;
+    key_param[4].enumerated = KM_PURPOSE_VERIFY;
+    key_param[5].tag = KM_TAG_DIGEST;
+    key_param[5].enumerated = KM_DIGEST_NONE;
+    CHECK_RESULT_OK(device->import_key(device,
+        &key_paramset, KM_KEY_FORMAT_PKCS8, &key_data, &key_blob, NULL));
+
+    op_param[0].tag = KM_TAG_ALGORITHM;
+    op_param[0].enumerated = KM_ALGORITHM_EC;
+    op_param[1].tag = KM_TAG_DIGEST;
+    op_param[1].enumerated = KM_DIGEST_NONE;
+
+    /* 1. Generate a signature ourselves. */
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, &key_blob, &op_paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == messageblob.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &sig));
+
+    /* 2. Verify BC's signature. */
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY, &key_blob, &op_paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == messageblob.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, &bc_sig_blob, NULL, NULL));
+
+end:
+    km_free_key_blob(&key_blob);
+    km_free_blob(&sig);
+
+    return res;
+}
+
+keymaster_error_t test_km_ec(
+    keymaster1_device_t *device,
+    uint32_t keysize)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[8];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    uint32_t keylen = BYTES_PER_BITS(keysize);
+
+    LOG_I("Generate %d-bit key...", keysize);
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_EC;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = keysize;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_SIGN;
+    key_param[4].tag = KM_TAG_PURPOSE;
+    key_param[4].enumerated = KM_PURPOSE_VERIFY;
+    key_param[5].tag = KM_TAG_DIGEST;
+    key_param[5].enumerated = KM_DIGEST_SHA1;
+    key_param[6].tag = KM_TAG_DIGEST;
+    key_param[6].enumerated = KM_DIGEST_SHA_2_512;
+    key_param[7].tag = KM_TAG_DIGEST;
+    key_param[7].enumerated = KM_DIGEST_NONE;
+    paramset.length = 8;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &paramset, &key_blob, NULL));
+
+    LOG_I("ECDSA sign/verify with SHA1 hash...");
+    CHECK_RESULT_OK(test_km_ec_sign_verify(
+        device, &key_blob, keylen, KM_DIGEST_SHA1) );
+
+    LOG_I("ECDSA sign/verify with SHA512 hash...");
+    CHECK_RESULT_OK(test_km_ec_sign_verify(
+        device, &key_blob, keylen, KM_DIGEST_SHA_2_512) );
+
+    LOG_I("ECDSA sign/verify with SHA1 hash, empty message...");
+    CHECK_RESULT_OK(test_km_ec_sign_verify_empty_message(
+        device, &key_blob, keylen, KM_DIGEST_SHA1) );
+
+    LOG_I("ECDSA sign/verify with no digest, empty message...");
+    CHECK_RESULT_OK(test_km_ec_sign_verify_empty_message(
+        device, &key_blob, keylen, KM_DIGEST_NONE) );
+
+end:
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
diff --git a/libkeymaster/ver1/test/test_km_ec.h b/libkeymaster/ver1/test/test_km_ec.h
new file mode 100644 (file)
index 0000000..0581f6e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_KM_EC_H__
+#define __TEST_KM_EC_H__
+
+#include <hardware/keymaster1.h>
+
+keymaster_error_t test_km_ec(
+    keymaster1_device_t *device,
+    uint32_t keysize);
+
+keymaster_error_t test_km_ec_import_export(
+    keymaster1_device_t *device);
+
+keymaster_error_t test_km_ec_p521_interop(
+    keymaster1_device_t *device);
+
+#endif /* __TEST_KM_EC_H__ */
diff --git a/libkeymaster/ver1/test/test_km_hmac.cpp b/libkeymaster/ver1/test/test_km_hmac.cpp
new file mode 100644 (file)
index 0000000..0da2bdf
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hardware/keymaster1.h>
+
+#include "test_km_hmac.h"
+#include "test_km_util.h"
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+static keymaster_error_t test_km_hmac_sign_verify(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    keymaster_digest_t digest)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[5];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t app_id;
+    uint8_t app_id_bytes[8];
+    uint8_t message[20];
+    keymaster_blob_t message_blob = {0, 0};
+    keymaster_blob_t tag = {0, 0};
+    size_t message_consumed = 0;
+
+    uint32_t tagsize = BYTES_PER_BITS(block_length(digest));
+
+    /* populate message */
+    memset(message, 7, sizeof(message));
+
+    /* populate app_id */
+    memset(app_id_bytes, 4, sizeof(app_id_bytes));
+    app_id.data = &app_id_bytes[0];
+    app_id.data_length = sizeof(app_id_bytes);
+
+    key_param[0].tag = KM_TAG_APPLICATION_ID;
+    key_param[0].blob = app_id;
+    key_param[1].tag = KM_TAG_ALGORITHM;
+    key_param[1].enumerated = KM_ALGORITHM_HMAC;
+    key_param[2].tag = KM_TAG_PADDING; // ignored for HMAC
+    key_param[2].enumerated = KM_PAD_PKCS7;
+    key_param[3].tag = KM_TAG_DIGEST;
+    key_param[3].enumerated = digest;
+    key_param[4].tag = KM_TAG_MAC_LENGTH;
+    key_param[4].integer = block_length(digest);
+    paramset.length = 5;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    message_blob.data = &message[0];
+    message_blob.data_length = 11;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &message_blob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 11);
+
+    message_blob.data = &message[11];
+    message_blob.data_length = 9;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &message_blob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 9);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &tag));
+    CHECK_TRUE(tag.data_length == tagsize);
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY,
+        key_blob,
+        &paramset, // same as for KM_PURPOSE_SIGN
+        NULL, // no out_params
+        &handle));
+
+    message_blob.data = &message[0];
+    message_blob.data_length = 10;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &message_blob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 10);
+
+    message_blob.data = &message[10];
+    message_blob.data_length = 10;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &message_blob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 10);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        &tag,
+        NULL, // no out_params
+        NULL));
+
+end:
+    km_free_blob(&tag);
+
+    return res;
+}
+
+keymaster_error_t test_km_hmac_import(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[5];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_blob_t tag = {0, 0};
+    size_t message_consumed = 0;
+
+    /*  NIST test vector from HMAC.rsp
+        http://csrc.nist.gov/groups/STM/cavp/documents/mac/hmactestvectors.zip
+        [L = 28]
+        Count = 280
+        Klen = 66
+        Tlen = 24
+        Key = 056d8a62bdb898b39cdf10c24d7787e0a8853b647a37f7fe84d23748c6ec8d9efddb43306a6d4255d5da3223d2f6e33c43abecea1ea7926f7052eb96a203438efb73
+        Msg = ea9222041a580bdb27be76069fa60aa4f93f8e6ed6344e908623c1b8ce506a6ce89bfca0ccafc188ae7d3cabc8e90e3959c2169eeef8dc57e00930041ebd0ebf2c13c5ad6c7b58d29d45252aa15ac4f5832a3252b8e52f0fa5eee4c0628dc90ebee4c65283249963fb0077abb262f6817e5d2ab3bd640e61deb9261223276301
+        Mac = e9bc98284c402d5e72d48253f643a27321172f8e70a726ea
+     */
+
+    const uint8_t key[66] = {
+        0x05, 0x6d, 0x8a, 0x62, 0xbd, 0xb8, 0x98, 0xb3,
+        0x9c, 0xdf, 0x10, 0xc2, 0x4d, 0x77, 0x87, 0xe0,
+        0xa8, 0x85, 0x3b, 0x64, 0x7a, 0x37, 0xf7, 0xfe,
+        0x84, 0xd2, 0x37, 0x48, 0xc6, 0xec, 0x8d, 0x9e,
+        0xfd, 0xdb, 0x43, 0x30, 0x6a, 0x6d, 0x42, 0x55,
+        0xd5, 0xda, 0x32, 0x23, 0xd2, 0xf6, 0xe3, 0x3c,
+        0x43, 0xab, 0xec, 0xea, 0x1e, 0xa7, 0x92, 0x6f,
+        0x70, 0x52, 0xeb, 0x96, 0xa2, 0x03, 0x43, 0x8e,
+        0xfb, 0x73};
+    const uint8_t message[128] = {
+        0xea, 0x92, 0x22, 0x04, 0x1a, 0x58, 0x0b, 0xdb,
+        0x27, 0xbe, 0x76, 0x06, 0x9f, 0xa6, 0x0a, 0xa4,
+        0xf9, 0x3f, 0x8e, 0x6e, 0xd6, 0x34, 0x4e, 0x90,
+        0x86, 0x23, 0xc1, 0xb8, 0xce, 0x50, 0x6a, 0x6c,
+        0xe8, 0x9b, 0xfc, 0xa0, 0xcc, 0xaf, 0xc1, 0x88,
+        0xae, 0x7d, 0x3c, 0xab, 0xc8, 0xe9, 0x0e, 0x39,
+        0x59, 0xc2, 0x16, 0x9e, 0xee, 0xf8, 0xdc, 0x57,
+        0xe0, 0x09, 0x30, 0x04, 0x1e, 0xbd, 0x0e, 0xbf,
+        0x2c, 0x13, 0xc5, 0xad, 0x6c, 0x7b, 0x58, 0xd2,
+        0x9d, 0x45, 0x25, 0x2a, 0xa1, 0x5a, 0xc4, 0xf5,
+        0x83, 0x2a, 0x32, 0x52, 0xb8, 0xe5, 0x2f, 0x0f,
+        0xa5, 0xee, 0xe4, 0xc0, 0x62, 0x8d, 0xc9, 0x0e,
+        0xbe, 0xe4, 0xc6, 0x52, 0x83, 0x24, 0x99, 0x63,
+        0xfb, 0x00, 0x77, 0xab, 0xb2, 0x62, 0xf6, 0x81,
+        0x7e, 0x5d, 0x2a, 0xb3, 0xbd, 0x64, 0x0e, 0x61,
+        0xde, 0xb9, 0x26, 0x12, 0x23, 0x27, 0x63, 0x01};
+    const uint8_t mac[24] = {
+        0xe9, 0xbc, 0x98, 0x28, 0x4c, 0x40, 0x2d, 0x5e,
+        0x72, 0xd4, 0x82, 0x53, 0xf6, 0x43, 0xa2, 0x73,
+        0x21, 0x17, 0x2f, 0x8e, 0x70, 0xa7, 0x26, 0xea};
+
+    const keymaster_blob_t key_data = {key, sizeof(key)};
+    const keymaster_blob_t messageblob = {message, sizeof(message)};
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_HMAC;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = 66*8;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_SIGN;
+    key_param[4].tag = KM_TAG_DIGEST;
+    key_param[4].enumerated = KM_DIGEST_SHA_2_224;
+    paramset.length = 5;
+    CHECK_RESULT_OK(device->import_key(device,
+        &paramset,
+        KM_KEY_FORMAT_RAW,
+        &key_data,
+        &key_blob,
+        NULL));
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_HMAC;
+    key_param[1].tag = KM_TAG_DIGEST;
+    key_param[1].enumerated = KM_DIGEST_SHA_2_224;
+    key_param[2].tag = KM_TAG_MAC_LENGTH;
+    key_param[2].integer = 24*8;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN,
+        &key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob,
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 128);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &tag));
+    CHECK_TRUE(tag.data_length == 24);
+
+    CHECK_TRUE(memcmp(tag.data, mac, 24) == 0);
+
+end:
+    km_free_key_blob(&key_blob);
+    km_free_blob(&tag);
+
+    return res;
+}
+
+keymaster_error_t test_km_hmac(
+    keymaster1_device_t *device,
+    keymaster_digest_t digest,
+    uint32_t keysize)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[7];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+
+    LOG_I("Generate %u-bit key ...", keysize);
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_HMAC;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = keysize;
+    key_param[2].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[2].boolean = true;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_SIGN;
+    key_param[4].tag = KM_TAG_PURPOSE;
+    key_param[4].enumerated = KM_PURPOSE_VERIFY;
+    key_param[5].tag = KM_TAG_DIGEST;
+    key_param[5].enumerated = digest;
+    key_param[6].tag = KM_TAG_MIN_MAC_LENGTH;
+    key_param[6].integer = 64;
+    paramset.length = 7;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &paramset,
+        &key_blob,
+        NULL));
+
+    LOG_I("Test key characteristics ...");
+    CHECK_RESULT_OK(device->get_key_characteristics(device,
+        &key_blob,
+        NULL, // client_id
+        NULL, // app_data
+        &pkey_characteristics));
+    print_characteristics(pkey_characteristics);
+
+    LOG_I("Sign and verify ...");
+    CHECK_RESULT_OK(test_km_hmac_sign_verify(device, &key_blob, digest));
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
diff --git a/libkeymaster/ver1/test/test_km_hmac.h b/libkeymaster/ver1/test/test_km_hmac.h
new file mode 100644 (file)
index 0000000..6868fe7
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_KM_HMAC_H__
+#define __TEST_KM_HMAC_H__
+
+#include <hardware/keymaster1.h>
+
+keymaster_error_t test_km_hmac_import(
+    keymaster1_device_t *device);
+
+keymaster_error_t test_km_hmac(
+    keymaster1_device_t *device,
+    keymaster_digest_t digest,
+    uint32_t keysize); // bits
+
+#endif /* __TEST_KM_HMAC_H__ */
diff --git a/libkeymaster/ver1/test/test_km_restrictions.cpp b/libkeymaster/ver1/test/test_km_restrictions.cpp
new file mode 100644 (file)
index 0000000..957e7e3
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <time.h>
+#include <openssl/hmac.h>
+#include <hardware/keymaster1.h>
+#include <hardware/hw_auth_token.h>
+#include "test_km_restrictions.h"
+#include "test_km_util.h"
+#include "km_shared_util.h"
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+/**
+ * Endianness of platform, initialized in \p main().
+ */
+bool am_big_endian;
+
+#if 0
+static uint32_t hton32(
+    uint32_t a)
+{
+    if (am_big_endian) {
+        return a;
+    } else {
+        uint32_t b = 0;
+        for (int i = 0; i < 4; i++) {
+            b |= ((a >> (8*i)) & 0xFF) << (8*(3-i));
+        }
+        return b;
+    }
+}
+
+static uint64_t hton64(
+    uint64_t a)
+{
+    if (am_big_endian) {
+        return a;
+    } else {
+        uint64_t b = 0;
+        for (int i = 0; i < 8; i++) {
+            b |= ((a >> (8*i)) & 0xFF) << (8*(7-i));
+        }
+        return b;
+    }
+}
+
+static void make_auth_token(
+    hw_auth_token_t *auth_token,
+    uint8_t version,
+    uint64_t challenge,
+    uint64_t user_id,
+    uint32_t authenticator_type,
+    bool old)
+{
+    assert(auth_token != NULL);
+    auth_token->version = version;
+    auth_token->challenge = challenge;
+    auth_token->user_id = user_id;
+    auth_token->authenticator_id = 0;
+    auth_token->authenticator_type = hton32(authenticator_type);
+
+    /* Timestamp */
+    // FIXME gettimeofday() and tlApiGetSecureTimestamp() return completely
+    // different things. We want secure time here.
+    //
+    // struct timeval tv;
+    // gettimeofday(&tv, NULL);
+    // auth_token->timestamp = hton64(tv.tv_sec * 1000000ull + tv.tv_usec);
+    auth_token->timestamp = hton64(old ? 0ull : 0xFFFFFFFF00000000ull);
+
+    /* HMAC using test key = [0x2A]*32. TODO integrated test with Gatekeeper. */
+    uint8_t key[32];
+    memset(key, 0x2A, 32);
+    uint8_t data[37]; // size of packed hw_auth_token_t minus the HMAC
+    uint8_t *pos;
+    data[0] = auth_token->version;
+    pos = data + 1;
+    set_u64_increment_pos(&pos, auth_token->challenge);
+    set_u64_increment_pos(&pos, auth_token->user_id);
+    set_u64_increment_pos(&pos, auth_token->authenticator_id);
+    set_u32_increment_pos(&pos, auth_token->authenticator_type);
+    set_u64_increment_pos(&pos, auth_token->timestamp);
+    HMAC_CTX ctx;
+    HMAC_CTX_init(&ctx);
+    if (0 == HMAC_Init_ex(&ctx, key, 32, EVP_sha256(), NULL)) {
+        assert(!"HMAC_Init_ex failed");
+    }
+    if (0 == HMAC_Update(&ctx, data, sizeof(data))) {
+        assert(!"HMAC_Update failed");
+    }
+    unsigned int len = 32;
+    if ((0 == HMAC_Final(&ctx, auth_token->hmac, &len)) || (len != 32)) {
+        assert(!"HMAC_Final failed");
+    }
+    HMAC_CTX_cleanup(&ctx);
+}
+
+static void serialize_auth_token(
+    uint8_t token_data[69],
+    const hw_auth_token_t *auth_token)
+{
+    uint8_t *pos;
+    token_data[0] = auth_token->version;
+    pos = token_data + 1;
+    set_u64_increment_pos(&pos, auth_token->challenge);
+    set_u64_increment_pos(&pos, auth_token->user_id);
+    set_u64_increment_pos(&pos, auth_token->authenticator_id);
+    set_u32_increment_pos(&pos, auth_token->authenticator_type);
+    set_u64_increment_pos(&pos, auth_token->timestamp);
+    set_data_increment_pos(&pos, auth_token->hmac, 32);
+}
+
+static keymaster_error_t test_km_restrictions_auth_token(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t generate_param[7];
+    keymaster_key_param_set_t generate_paramset = {generate_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+    static const uint64_t user_id = 0x123456789abcdef0ull;
+    hw_auth_token_t auth_token;
+    uint8_t token_data[69];
+    keymaster_blob_t token_blob = {token_data, 69};
+    keymaster_key_param_t begin_param[4];
+    keymaster_key_param_set_t begin_paramset = {begin_param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_key_param_set_t begin_out_paramset = {NULL, 0};
+    uint8_t iv[16];
+    keymaster_key_param_t update_param[1];
+    keymaster_key_param_set_t update_paramset = {update_param, 0};
+    uint8_t plaintext_data[32];
+    keymaster_blob_t plaintext = {plaintext_data, 32};
+    keymaster_blob_t ciphertext = {NULL, 0};
+    size_t input_consumed = 0;
+    keymaster_blob_t decrypted = {NULL, 0};
+
+    LOG_I("Auth-token tests ...");
+
+    LOG_I("Generate key ...");
+    generate_param[0].tag = KM_TAG_ALGORITHM;
+    generate_param[0].enumerated = KM_ALGORITHM_AES;
+    generate_param[1].tag = KM_TAG_KEY_SIZE;
+    generate_param[1].integer = 128;
+    generate_param[2].tag = KM_TAG_PURPOSE;
+    generate_param[2].enumerated = KM_PURPOSE_ENCRYPT;
+    generate_param[3].tag = KM_TAG_PURPOSE;
+    generate_param[3].enumerated = KM_PURPOSE_DECRYPT;
+    generate_param[4].tag = KM_TAG_BLOCK_MODE;
+    generate_param[4].enumerated = KM_MODE_CBC;
+    generate_param[5].tag = KM_TAG_USER_SECURE_ID;
+    generate_param[5].long_integer = user_id;
+    generate_param[6].tag = KM_TAG_USER_AUTH_TYPE;
+    generate_param[6].enumerated = HW_AUTH_PASSWORD;
+    generate_paramset.length = 7;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &generate_paramset, &key_blob, &pkey_characteristics));
+    print_characteristics(pkey_characteristics);
+
+    LOG_I("Begin encrypt ...");
+    begin_param[0].tag = KM_TAG_BLOCK_MODE;
+    begin_param[0].enumerated = KM_MODE_CBC;
+    begin_param[1].tag = KM_TAG_AUTH_TOKEN;
+    begin_param[1].blob = token_blob;
+    begin_param[2].tag = KM_TAG_USER_SECURE_ID;
+    begin_param[2].long_integer = user_id;
+    begin_paramset.length = 3;
+
+    LOG_I("unauthorized ...");
+    /* Bad version */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION + 1, 0, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+            &begin_paramset, &begin_out_paramset, &handle));
+    /* Bad user_id */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION , 0, user_id + 1,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+            &begin_paramset, &begin_out_paramset, &handle));
+    /* Bad authenticator_type */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION , 0, user_id,
+        HW_AUTH_FINGERPRINT, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+            &begin_paramset, &begin_out_paramset, &handle));
+    /* Bad hmac */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION , 0, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    token_data[68] ^= 1;
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+            &begin_paramset, &begin_out_paramset, &handle));
+
+    LOG_I("authorized ...");
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION, 0, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT_OK(device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+        &begin_paramset, &begin_out_paramset, &handle));
+    CHECK_TRUE(begin_out_paramset.length == 1);
+    CHECK_TRUE(begin_out_paramset.params[0].tag == KM_TAG_NONCE);
+    CHECK_TRUE(begin_out_paramset.params[0].blob.data_length == 16);
+    memcpy(iv, begin_out_paramset.params[0].blob.data, 16);
+
+    LOG_I("Update encrypt ...");
+    update_param[0].tag = KM_TAG_AUTH_TOKEN;
+    update_param[0].blob = token_blob;
+    update_paramset.length = 1;
+    memset(plaintext_data, 3, 32);
+
+    LOG_I("unauthorized ...");
+    /* Bad version */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION + 1, 0, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->update(device, handle, &update_paramset,
+            &plaintext, &input_consumed, NULL, &ciphertext));
+    /* Bad user_id */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION , 0, user_id + 1,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->update(device, handle, &update_paramset,
+            &plaintext, &input_consumed, NULL, &ciphertext));
+    /* Bad authenticator_type */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION , 0, user_id,
+        HW_AUTH_FINGERPRINT, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->update(device, handle, &update_paramset,
+            &plaintext, &input_consumed, NULL, &ciphertext));
+    /* Bad hmac */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION , 0, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    token_data[68] ^= 1;
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->update(device, handle, &update_paramset,
+            &plaintext, &input_consumed, NULL, &ciphertext));
+
+    LOG_I("authorized ...");
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION, handle, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT_OK(device->update(device, handle, &update_paramset,
+        &plaintext, &input_consumed, NULL, &ciphertext));
+    CHECK_TRUE(input_consumed == 32);
+    CHECK_TRUE(ciphertext.data_length == 32);
+
+    LOG_I("Finish encrypt ...");
+    /* Use the same params (i.e. just the auth token) */
+    CHECK_RESULT_OK(device->finish(device, handle, &update_paramset,
+        NULL, NULL, NULL));
+
+    LOG_I("Begin decrypt ...");
+    /* Use the same params as previously with the addition of the IV. Note that
+     * this includes the auth_token used for the update() and finish() calls
+     * above. This should be OK as the 'challenge' is ignored for a begin().
+     */
+    begin_param[3].tag = KM_TAG_NONCE;
+    begin_param[3].blob.data_length = 16;
+    begin_param[3].blob.data = iv;
+    begin_paramset.length = 4;
+    CHECK_RESULT_OK(device->begin(device, KM_PURPOSE_DECRYPT, &key_blob,
+        &begin_paramset, NULL, &handle));
+
+    LOG_I("Update decrypt ...");
+    /* Need a new auth token with the correct 'challenge'. */
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION, handle, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT_OK(device->update(device, handle, &update_paramset,
+        &ciphertext, &input_consumed, NULL, &decrypted));
+    CHECK_TRUE(input_consumed == 32);
+    CHECK_TRUE(decrypted.data_length == 32);
+
+    LOG_I("Finish decrypt ...");
+    /* Use the same params (i.e. just the auth token) */
+    CHECK_RESULT_OK(device->finish(device, handle, &update_paramset,
+        NULL, NULL, NULL));
+
+    CHECK_TRUE(memcmp(plaintext.data, decrypted.data, 32) == 0);
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+    keymaster_free_param_set(&begin_out_paramset);
+    km_free_blob(&ciphertext);
+    km_free_blob(&decrypted);
+
+    return res;
+}
+
+static keymaster_error_t test_km_restrictions_timeout(
+    keymaster1_device_t *device)
+{ // TODO
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t generate_param[8];
+    keymaster_key_param_set_t generate_paramset = {generate_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+    static const uint64_t user_id = 0x123456789abcdef0ull;
+    hw_auth_token_t auth_token;
+    uint8_t token_data[69];
+    keymaster_blob_t token_blob = {token_data, 69};
+    keymaster_key_param_t begin_param[4];
+    keymaster_key_param_set_t begin_paramset = {begin_param, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_operation_handle_t handle1;
+
+    LOG_I("Timeout tests ...");
+
+    LOG_I("Generate key (timeout = 3s) ...");
+    generate_param[0].tag = KM_TAG_ALGORITHM;
+    generate_param[0].enumerated = KM_ALGORITHM_AES;
+    generate_param[1].tag = KM_TAG_KEY_SIZE;
+    generate_param[1].integer = 128;
+    generate_param[2].tag = KM_TAG_PURPOSE;
+    generate_param[2].enumerated = KM_PURPOSE_ENCRYPT;
+    generate_param[3].tag = KM_TAG_PURPOSE;
+    generate_param[3].enumerated = KM_PURPOSE_DECRYPT;
+    generate_param[4].tag = KM_TAG_BLOCK_MODE;
+    generate_param[4].enumerated = KM_MODE_ECB;
+    generate_param[5].tag = KM_TAG_USER_SECURE_ID;
+    generate_param[5].long_integer = user_id;
+    generate_param[6].tag = KM_TAG_USER_AUTH_TYPE;
+    generate_param[6].enumerated = HW_AUTH_ANY;
+    generate_param[7].tag = KM_TAG_AUTH_TIMEOUT;
+    generate_param[7].integer = 3; // seconds
+    generate_paramset.length = 8;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &generate_paramset, &key_blob, &pkey_characteristics));
+    print_characteristics(pkey_characteristics);
+
+    LOG_I("Begin encrypt with new auth token ...");
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION, 0, user_id,
+        HW_AUTH_PASSWORD, false);
+    serialize_auth_token(token_data, &auth_token);
+    begin_param[0].tag = KM_TAG_BLOCK_MODE;
+    begin_param[0].enumerated = KM_MODE_ECB;
+    begin_param[1].tag = KM_TAG_AUTH_TOKEN;
+    begin_param[1].blob = token_blob;
+    begin_param[2].tag = KM_TAG_USER_SECURE_ID;
+    begin_param[2].long_integer = user_id;
+    begin_paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+        &begin_paramset, NULL, &handle));
+
+    // FIXME We can't do this test until we have secure time in the auth token.
+    // LOG_I("Sleep (4s) ...");
+    // sleep(4);
+
+    LOG_I("Begin encrypt with old auth token ...");
+    make_auth_token(&auth_token, HW_AUTH_TOKEN_VERSION, 0, user_id,
+        HW_AUTH_PASSWORD, true);
+    serialize_auth_token(token_data, &auth_token);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device, KM_PURPOSE_ENCRYPT, &key_blob,
+            &begin_paramset, NULL, &handle1));
+
+    CHECK_RESULT_OK(device->abort(device, handle));
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
+#endif
+
+static keymaster_error_t test_km_restrictions_app_id_and_data(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_params[7];
+    keymaster_key_param_set_t generate_paramset = {key_params, 0};
+    const uint8_t id_bytes[] = {1, 2, 3};
+    const uint8_t data_bytes[] = {4, 5, 6, 7};
+    keymaster_blob_t application_id = {id_bytes, sizeof(id_bytes)};
+    keymaster_blob_t application_data = {data_bytes, sizeof(data_bytes)};
+    const uint8_t wrong_id_bytes[] = {3, 2, 1};
+    const uint8_t wrong_data_bytes[] = {4, 5, 6, 7, 8};
+    keymaster_blob_t wrong_application_id = {wrong_id_bytes, sizeof(wrong_id_bytes)};
+    keymaster_blob_t wrong_application_data = {wrong_data_bytes, sizeof(wrong_data_bytes)};
+    keymaster_key_blob_t key_blob = {NULL, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+    keymaster_blob_t export_data = {NULL, 0};
+    keymaster_operation_handle_t handle;
+    keymaster_key_param_t op_params[4];
+    keymaster_key_param_set_t begin_paramset = {op_params, 0};
+
+    /* generate key */
+    key_params[0].tag = KM_TAG_ALGORITHM;
+    key_params[0].enumerated = KM_ALGORITHM_EC;
+    key_params[1].tag = KM_TAG_KEY_SIZE;
+    key_params[1].integer = 256;
+    key_params[2].tag = KM_TAG_PURPOSE;
+    key_params[2].enumerated = KM_PURPOSE_SIGN;
+    key_params[3].tag = KM_TAG_DIGEST;
+    key_params[3].enumerated = KM_DIGEST_SHA_2_256;
+    key_params[4].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_params[4].boolean = true;
+    key_params[5].tag = KM_TAG_APPLICATION_ID;
+    key_params[5].blob = application_id;
+    key_params[6].tag = KM_TAG_APPLICATION_DATA;
+    key_params[6].blob = application_data;
+    generate_paramset.length = 7;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &generate_paramset, &key_blob, NULL));
+
+    /* get_key_characteristics (good case) */
+    CHECK_RESULT_OK(device->get_key_characteristics(device,
+        &key_blob, &application_id, &application_data, &pkey_characteristics));
+
+    /* get_key_characteristics (bad cases) */
+    keymaster_free_characteristics(pkey_characteristics);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->get_key_characteristics(device,
+            &key_blob, &application_id, NULL, &pkey_characteristics));
+    keymaster_free_characteristics(pkey_characteristics);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->get_key_characteristics(device,
+            &key_blob, NULL, &application_data, &pkey_characteristics));
+    keymaster_free_characteristics(pkey_characteristics);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->get_key_characteristics(device,
+            &key_blob, &application_id, &wrong_application_data, &pkey_characteristics));
+    keymaster_free_characteristics(pkey_characteristics);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->get_key_characteristics(device,
+            &key_blob, &wrong_application_id, &application_data, &pkey_characteristics));
+
+    /* export_key (good case) */
+    CHECK_RESULT_OK(device->export_key(device,
+        KM_KEY_FORMAT_X509, &key_blob, &application_id, &application_data, &export_data));
+
+    /* export_key (bad cases) */
+    km_free_blob(&export_data);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->export_key(device,
+            KM_KEY_FORMAT_X509, &key_blob, &application_id, NULL, &export_data));
+    km_free_blob(&export_data);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->export_key(device,
+            KM_KEY_FORMAT_X509, &key_blob, NULL, &application_data, &export_data));
+    km_free_blob(&export_data);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->export_key(device,
+            KM_KEY_FORMAT_X509, &key_blob, &application_id, &wrong_application_data, &export_data));
+    km_free_blob(&export_data);
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->export_key(device,
+            KM_KEY_FORMAT_X509, &key_blob, &wrong_application_id, &application_data, &export_data));
+
+    /* begin (good case) */
+    op_params[0].tag = KM_TAG_ALGORITHM;
+    op_params[0].enumerated = KM_ALGORITHM_EC;
+    op_params[1].tag = KM_TAG_DIGEST;
+    op_params[1].enumerated = KM_DIGEST_SHA_2_256;
+    op_params[2].tag = KM_TAG_APPLICATION_ID;
+    op_params[2].blob = application_id;
+    op_params[3].tag = KM_TAG_APPLICATION_DATA;
+    op_params[3].blob = application_data;
+    begin_paramset.length = 4;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, &key_blob, &begin_paramset, NULL, &handle));
+    CHECK_RESULT_OK(device->abort(device,
+        handle));
+
+    /* begin (bad cases) */
+    begin_paramset.length = 3;
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device,
+            KM_PURPOSE_SIGN, &key_blob, &begin_paramset, NULL, &handle));
+    op_params[2].tag = KM_TAG_APPLICATION_DATA;
+    op_params[2].blob = application_data;
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device,
+            KM_PURPOSE_SIGN, &key_blob, &begin_paramset, NULL, &handle));
+    op_params[3].tag = KM_TAG_APPLICATION_ID;
+    op_params[3].blob = wrong_application_id;
+    begin_paramset.length = 4;
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device,
+            KM_PURPOSE_SIGN, &key_blob, &begin_paramset, NULL, &handle));
+    op_params[2].blob = wrong_application_data;
+    op_params[3].blob = application_id;
+    CHECK_RESULT(KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+        device->begin(device,
+            KM_PURPOSE_SIGN, &key_blob, &begin_paramset, NULL, &handle));
+
+end:
+    km_free_blob(&export_data);
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
+
+keymaster_error_t test_km_restrictions(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+
+    /* FIXME: Test currently uses old 'dummy' HMAC key, so fails.
+     * Need integration test with Gatekeeper.
+     */
+    // CHECK_RESULT_OK(test_km_restrictions_auth_token(device));
+    // CHECK_RESULT_OK(test_km_restrictions_timeout(device));
+    CHECK_RESULT_OK(test_km_restrictions_app_id_and_data(device));
+
+end:
+    return res;
+}
diff --git a/libkeymaster/ver1/test/test_km_restrictions.h b/libkeymaster/ver1/test/test_km_restrictions.h
new file mode 100644 (file)
index 0000000..a607619
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_KM_RESTRICTIONS_H__
+#define __TEST_KM_RESTRICTIONS_H__
+
+#include <hardware/keymaster1.h>
+
+keymaster_error_t test_km_restrictions(
+    keymaster1_device_t *device);
+
+#endif /* __TEST_KM_RESTRICTIONS_H__ */
diff --git a/libkeymaster/ver1/test/test_km_rsa.cpp b/libkeymaster/ver1/test/test_km_rsa.cpp
new file mode 100644 (file)
index 0000000..3643b54
--- /dev/null
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <hardware/keymaster1.h>
+
+#include "test_km_rsa.h"
+#include "test_km_util.h"
+
+#include <memory>
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+template<typename T> class OptionalValue
+{
+public:
+    OptionalValue(T val)
+    : _val(val), _isSet(true){}
+
+    OptionalValue(std::nullptr_t)
+    : _val(KM_DIGEST_NONE), _isSet(false)
+    {}
+
+    operator bool() const
+    { return _isSet; }
+
+    T operator *() const
+    {return _val;}
+
+private:
+    T _val;
+    bool _isSet;
+};
+
+static keymaster_error_t test_km_rsa_sign_verify(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes,
+    keymaster_padding_t padding,
+    keymaster_digest_t digest)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message[1000];
+    keymaster_blob_t messageblob = {0, 0};
+    keymaster_blob_t sig_output = {0, 0};
+    size_t message_consumed = 0;
+
+    /* populate message */
+    memset(message, 24, sizeof(message));
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_PADDING;
+    key_param[1].enumerated = padding;
+    key_param[2].tag = KM_TAG_DIGEST;
+    key_param[2].enumerated = digest;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    messageblob.data = &message[0];
+    messageblob.data_length = 630;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 630);
+
+    messageblob.data = &message[630];
+    messageblob.data_length = 370;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 370);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &sig_output));
+    CHECK_TRUE(sig_output.data_length == keybytes);
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY,
+        key_blob,
+        &paramset, // same as for KM_PURPOSE_SIGN
+        NULL, // no out_params
+        &handle));
+
+    messageblob.data = &message[0];
+    messageblob.data_length = 480;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 480);
+
+    messageblob.data = &message[480];
+    messageblob.data_length = 520;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &messageblob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 520);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        &sig_output,
+        NULL, // no out_params
+        NULL));
+
+end:
+    km_free_blob(&sig_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_sign_verify_pkcs1_1_5_raw(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message[512];
+    keymaster_blob_t messageblob = {message, 0};
+    keymaster_blob_t sig_output = {0, 0};
+    size_t message_consumed = 0;
+
+    /* populate message */
+    memset(message, 24, sizeof(message));
+
+    LOG_I("Message of maximum allowed size...");
+    messageblob.data_length = keybytes - 11; // maximum allowed
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_PADDING;
+    key_param[1].enumerated = KM_PAD_RSA_PKCS1_1_5_SIGN;
+    key_param[2].tag = KM_TAG_DIGEST;
+    key_param[2].enumerated = KM_DIGEST_NONE;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == messageblob.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &sig_output));
+    CHECK_TRUE(sig_output.data_length == keybytes);
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == messageblob.data_length);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, &sig_output, NULL, NULL));
+
+    km_free_blob(&sig_output);
+
+    LOG_I("Message exceeding maximum allowed size...");
+    messageblob.data_length += 1;
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == messageblob.data_length);
+
+    CHECK_RESULT(KM_ERROR_INVALID_INPUT_LENGTH,
+        device->finish(device,
+            handle, NULL, NULL, NULL, &sig_output));
+
+end:
+    km_free_blob(&sig_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_concurrent(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle[4];
+    uint8_t message[100];
+    keymaster_blob_t messageblob = {message, sizeof(message)};
+    keymaster_blob_t sig_output[4];
+    size_t message_consumed = 0;
+
+    memset(sig_output, 0, sizeof(sig_output));
+
+    /* populate message */
+    memset(message, 24, sizeof(message));
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_PADDING;
+    key_param[1].enumerated = KM_PAD_RSA_PKCS1_1_5_SIGN;
+    key_param[2].tag = KM_TAG_DIGEST;
+    key_param[2].enumerated = KM_DIGEST_MD5;
+    paramset.length = 3;
+
+    // start 3 RSA signature operations
+    for (int i = 0; i < 3; i++) {
+        CHECK_RESULT_OK(device->begin(device,
+            KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle[i]));
+    }
+    // 4 is too many
+    CHECK_RESULT(KM_ERROR_TOO_MANY_OPERATIONS, device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle[3]));
+
+    // update the 3 we've started
+    for (int i = 0; i < 3; i++) {
+        CHECK_RESULT_OK(device->update(device,
+            handle[i], NULL, &messageblob, &message_consumed, NULL, NULL));
+        CHECK_TRUE(message_consumed == sizeof(message));
+    }
+
+    // finish one of them
+    CHECK_RESULT_OK(device->finish(device,
+        handle[0], NULL, NULL, NULL, &sig_output[0]));
+    CHECK_TRUE(sig_output[0].data_length == keybytes);
+
+    // now start another
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle[3]));
+
+    // update it
+    CHECK_RESULT_OK(device->update(device,
+        handle[3], NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == sizeof(message));
+
+    // finish all of them
+    for (int i = 1; i < 4; i++) {
+        CHECK_RESULT_OK(device->finish(device,
+            handle[i], NULL, NULL, NULL, &sig_output[i]));
+        CHECK_TRUE(sig_output[i].data_length == keybytes);
+    }
+
+end:
+    for (int i = 0; i < 4; i++) {
+        km_free_blob(&sig_output[i]);
+    }
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_sign_verify_empty_message(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message;
+    keymaster_blob_t messageblob = {0, 0};
+    keymaster_blob_t sig_output = {0, 0};
+    size_t message_consumed = 0;
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_PADDING;
+    key_param[1].enumerated = KM_PAD_RSA_PSS;
+    key_param[2].tag = KM_TAG_DIGEST;
+    key_param[2].enumerated = KM_DIGEST_SHA_2_256;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data = &message;
+    messageblob.data_length = 0;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 0);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &sig_output));
+    CHECK_TRUE(sig_output.data_length == keybytes);
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data = &message;
+    messageblob.data_length = 0;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 0);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, &sig_output, NULL, NULL));
+
+end:
+    km_free_blob(&sig_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_sign_verify_pkcs1_no_digest_too_long(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message[BYTES_PER_BITS(4096) - 10];
+    keymaster_blob_t messageblob = {message, 0};
+    keymaster_blob_t sig_output = {NULL, 0};
+    size_t message_consumed = 0;
+
+    memset(message, 0x80, sizeof(message));
+
+    /* 1. Sign message of maximum length. */
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_PADDING;
+    key_param[1].enumerated = KM_PAD_RSA_PKCS1_1_5_SIGN;
+    key_param[2].tag = KM_TAG_DIGEST;
+    key_param[2].enumerated = KM_DIGEST_NONE;
+    paramset.length = 3;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_SIGN, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data_length = keybytes - 11;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == keybytes - 11);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &sig_output));
+    CHECK_TRUE(sig_output.data_length == keybytes);
+
+    /* 2. Try to verify with message extended by one byte. */
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data_length = keybytes - 10;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == keybytes - 10);
+
+    CHECK_RESULT(KM_ERROR_INVALID_INPUT_LENGTH,
+        device->finish(device,
+            handle, NULL, &sig_output, NULL, NULL));
+
+end:
+    km_free_blob(&sig_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_verify_empty_signature(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t message[BYTES_PER_BITS(4096) - 11];
+    keymaster_blob_t messageblob = {message, 0};
+    keymaster_blob_t sig = {NULL, 0};
+    size_t message_consumed = 0;
+
+    memset(message, 0x80, sizeof(message));
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_PADDING;
+    key_param[1].enumerated = KM_PAD_RSA_PKCS1_1_5_SIGN;
+    key_param[2].tag = KM_TAG_DIGEST;
+    key_param[2].enumerated = KM_DIGEST_NONE;
+    paramset.length = 3;
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_VERIFY, key_blob, &paramset, NULL, &handle));
+
+    messageblob.data_length = keybytes - 11;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &messageblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == keybytes - 11);
+
+    CHECK_RESULT(KM_ERROR_VERIFICATION_FAILED,
+        device->finish(device,
+            handle, NULL, &sig, NULL, NULL));
+
+end:
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_encrypt_decrypt(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes,
+    keymaster_padding_t padding,
+    OptionalValue<keymaster_digest_t> digest)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[4];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t plaintext[BYTES_PER_BITS(4096)]; // maximum key size
+    keymaster_blob_t plainblob = {0, 0};
+    keymaster_blob_t enc_output = {0, 0};
+    keymaster_blob_t dec_output = {0, 0};
+    size_t message_consumed = 0;
+
+    uint32_t padlen = 0;
+    if (padding == KM_PAD_RSA_OAEP) {
+        padlen = 2 + 2*BYTES_PER_BITS(block_length(*digest));
+    } else if (padding == KM_PAD_RSA_PKCS1_1_5_ENCRYPT) {
+        padlen = 11;
+    }
+
+    if (padlen > keybytes) {
+        LOG_I("Invalid key size / digest combination: skipping test.");
+        return KM_ERROR_OK;
+    }
+    uint32_t msgsize = keybytes - padlen;
+
+    /* populate message */
+    memset(plaintext, 25, sizeof(plaintext));
+    paramset.length=0;
+
+    key_param[paramset.length].tag = KM_TAG_ALGORITHM;
+    key_param[paramset.length].enumerated = KM_ALGORITHM_RSA;
+    paramset.length++;
+
+    key_param[paramset.length].tag = KM_TAG_PADDING;
+    key_param[paramset.length].enumerated = padding;
+    paramset.length++;
+
+    if(digest)
+    {
+        key_param[paramset.length].tag = KM_TAG_DIGEST;
+        key_param[paramset.length].enumerated = *digest;
+        paramset.length++;
+    }
+
+    // Must be last one
+    key_param[paramset.length].tag = KM_TAG_PURPOSE;
+    key_param[paramset.length].enumerated = KM_PURPOSE_ENCRYPT;
+    paramset.length++;
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    plainblob.data = &plaintext[0];
+    plainblob.data_length = 3;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &plainblob, // first part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == 3);
+
+    plainblob.data = &plaintext[3];
+    plainblob.data_length = msgsize - 3;
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &plainblob, // last part of message
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == msgsize - 3);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &enc_output));
+    CHECK_TRUE(enc_output.data_length == keybytes);
+
+    // Skip last param (KM_TAG_PURPOSE)
+    paramset.length--;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT,
+        key_blob,
+        &paramset,
+        NULL, // no out_params
+        &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle,
+        NULL, // no params
+        &enc_output,
+        &message_consumed,
+        NULL, // no out_params
+        NULL));
+    CHECK_TRUE(message_consumed == keybytes);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle,
+        NULL, // no params
+        NULL, // no signature
+        NULL, // no out_params
+        &dec_output));
+    CHECK_TRUE(dec_output.data_length == msgsize);
+
+    CHECK_TRUE(memcmp(plaintext, dec_output.data, msgsize) == 0);
+
+end:
+    km_free_blob(&enc_output);
+    km_free_blob(&dec_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_encrypt_decrypt_empty_message(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes,
+    keymaster_padding_t padding)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[3];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t plaintext = 0;
+    keymaster_blob_t plainblob = {0, 0};
+    keymaster_blob_t enc_output = {0, 0};
+    keymaster_blob_t dec_output = {0, 0};
+    size_t message_consumed = 0;
+
+    paramset.length=0;
+
+    key_param[paramset.length].tag = KM_TAG_ALGORITHM;
+    key_param[paramset.length].enumerated = KM_ALGORITHM_RSA;
+    paramset.length++;
+
+    key_param[paramset.length].tag = KM_TAG_PADDING;
+    key_param[paramset.length].enumerated = padding;
+    paramset.length++;
+
+    key_param[paramset.length].tag = KM_TAG_PURPOSE;
+    key_param[paramset.length].enumerated = KM_PURPOSE_ENCRYPT;
+    paramset.length++;
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+
+    plainblob.data = &plaintext;
+    plainblob.data_length = 0;
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &plainblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 0);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &enc_output));
+    CHECK_TRUE(enc_output.data_length == keybytes);
+
+    // Skip last param (KM_TAG_PURPOSE)
+    paramset.length--;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &enc_output, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == keybytes);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &dec_output));
+    CHECK_TRUE(dec_output.data_length == 0);
+
+end:
+    km_free_blob(&enc_output);
+    km_free_blob(&dec_output);
+
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_raw_too_large(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t param[4];
+    keymaster_key_param_set_t paramset = {param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t msg[BYTES_PER_BITS(4096)]; // maximum key size
+    keymaster_blob_t msg_blob = {msg, 0};
+    keymaster_blob_t output = {0, 0};
+    size_t message_consumed = 0;
+
+    /* populate message with large number */
+    memset(msg, 0xFF, keybytes);
+    msg_blob.data_length = keybytes;
+
+    /* Encrypt */
+    param[0].tag = KM_TAG_ALGORITHM;
+    param[0].enumerated = KM_ALGORITHM_RSA;
+    param[1].tag = KM_TAG_PADDING;
+    param[1].enumerated = KM_PAD_NONE;
+    param[2].tag = KM_TAG_DIGEST;
+    param[2].enumerated = KM_DIGEST_NONE;
+    param[3].tag = KM_TAG_PURPOSE;
+    param[3].enumerated = KM_PURPOSE_ENCRYPT;
+    paramset.length = 4;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &msg_blob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == keybytes);
+    CHECK_RESULT(KM_ERROR_INVALID_ARGUMENT, device->finish(device,
+        handle, NULL, NULL, NULL, &output));
+
+    /* Decrypt */
+    km_free_blob(&output);
+    param[3].enumerated = KM_PURPOSE_DECRYPT;
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &msg_blob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == keybytes);
+    CHECK_RESULT(KM_ERROR_INVALID_ARGUMENT, device->finish(device,
+        handle, NULL, NULL, NULL, &output));
+
+end:
+    km_free_blob(&output);
+    return res;
+}
+
+static keymaster_error_t test_km_rsa_encrypt_raw_one(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob,
+    uint32_t keybytes)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t param[5];
+    keymaster_key_param_set_t paramset = {param, 0};
+    keymaster_operation_handle_t handle;
+    uint8_t plaintext[1] = {1};
+    keymaster_blob_t oneblob = {plaintext, 1}; // numeric value 1
+    keymaster_blob_t enc_output = {NULL, 0};
+    keymaster_blob_t dec_output = {NULL, 0};
+    size_t message_consumed = 0;
+    uint8_t one[BYTES_PER_BITS(4096)];
+
+    memset(one, 0, keybytes-1);
+    one[keybytes-1] = 1; // 1^e == 1
+
+    param[0].tag = KM_TAG_ALGORITHM;
+    param[0].enumerated = KM_ALGORITHM_RSA;
+    param[1].tag = KM_TAG_PADDING;
+    param[1].enumerated = KM_PAD_NONE;
+    param[2].tag = KM_TAG_DIGEST;
+    param[2].enumerated = KM_DIGEST_NONE;
+    param[3].tag = KM_TAG_PURPOSE;
+    param[3].enumerated = KM_PURPOSE_ENCRYPT;
+    param[4].tag = KM_TAG_PURPOSE;
+    param[4].enumerated = KM_PURPOSE_DECRYPT;
+    paramset.length = 5;
+
+    /* Encrypt {1} and check result. */
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_ENCRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &oneblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 1);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &enc_output));
+    CHECK_TRUE(enc_output.data_length == keybytes);
+    CHECK_TRUE(memcmp(enc_output.data, one, keybytes) == 0);
+
+    /* Decrypt {1} and check result. */
+
+    CHECK_RESULT_OK(device->begin(device,
+        KM_PURPOSE_DECRYPT, key_blob, &paramset, NULL, &handle));
+
+    CHECK_RESULT_OK(device->update(device,
+        handle, NULL, &oneblob, &message_consumed, NULL, NULL));
+    CHECK_TRUE(message_consumed == 1);
+
+    CHECK_RESULT_OK(device->finish(device,
+        handle, NULL, NULL, NULL, &dec_output));
+    CHECK_TRUE(dec_output.data_length == keybytes);
+    CHECK_TRUE(memcmp(dec_output.data, one, keybytes) == 0);
+
+end:
+    km_free_blob(&enc_output);
+    km_free_blob(&dec_output);
+    return res;
+}
+
+keymaster_error_t test_km_rsa_import_export(
+    keymaster1_device_t *device)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[6];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+
+    /* Test vector from Android M PDK: system/keymaster/rsa_privkey_pk8.der */
+    const uint8_t key[] = {
+        0x30, 0x82, 0x02, 0x75, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+        0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+        0x02, 0x5f, 0x30, 0x82, 0x02, 0x5b, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+        0x00, 0xc6, 0x09, 0x54, 0x09, 0x04, 0x7d, 0x86, 0x34, 0x81, 0x2d, 0x5a,
+        0x21, 0x81, 0x76, 0xe4, 0x5c, 0x41, 0xd6, 0x0a, 0x75, 0xb1, 0x39, 0x01,
+        0xf2, 0x34, 0x22, 0x6c, 0xff, 0xe7, 0x76, 0x52, 0x1c, 0x5a, 0x77, 0xb9,
+        0xe3, 0x89, 0x41, 0x7b, 0x71, 0xc0, 0xb6, 0xa4, 0x4d, 0x13, 0xaf, 0xe4,
+        0xe4, 0xa2, 0x80, 0x5d, 0x46, 0xc9, 0xda, 0x29, 0x35, 0xad, 0xb1, 0xff,
+        0x0c, 0x1f, 0x24, 0xea, 0x06, 0xe6, 0x2b, 0x20, 0xd7, 0x76, 0x43, 0x0a,
+        0x4d, 0x43, 0x51, 0x57, 0x23, 0x3c, 0x6f, 0x91, 0x67, 0x83, 0xc3, 0x0e,
+        0x31, 0x0f, 0xcb, 0xd8, 0x9b, 0x85, 0xc2, 0xd5, 0x67, 0x71, 0x16, 0x97,
+        0x85, 0xac, 0x12, 0xbc, 0xa2, 0x44, 0xab, 0xda, 0x72, 0xbf, 0xb1, 0x9f,
+        0xc4, 0x4d, 0x27, 0xc8, 0x1e, 0x1d, 0x92, 0xde, 0x28, 0x4f, 0x40, 0x61,
+        0xed, 0xfd, 0x99, 0x28, 0x07, 0x45, 0xea, 0x6d, 0x25, 0x02, 0x03, 0x01,
+        0x00, 0x01, 0x02, 0x81, 0x80, 0x1b, 0xe0, 0xf0, 0x4d, 0x9c, 0xae, 0x37,
+        0x18, 0x69, 0x1f, 0x03, 0x53, 0x38, 0x30, 0x8e, 0x91, 0x56, 0x4b, 0x55,
+        0x89, 0x9f, 0xfb, 0x50, 0x84, 0xd2, 0x46, 0x0e, 0x66, 0x30, 0x25, 0x7e,
+        0x05, 0xb3, 0xce, 0xab, 0x02, 0x97, 0x2d, 0xfa, 0xbc, 0xd6, 0xce, 0x5f,
+        0x6e, 0xe2, 0x58, 0x9e, 0xb6, 0x79, 0x11, 0xed, 0x0f, 0xac, 0x16, 0xe4,
+        0x3a, 0x44, 0x4b, 0x8c, 0x86, 0x1e, 0x54, 0x4a, 0x05, 0x93, 0x36, 0x57,
+        0x72, 0xf8, 0xba, 0xf6, 0xb2, 0x2f, 0xc9, 0xe3, 0xc5, 0xf1, 0x02, 0x4b,
+        0x06, 0x3a, 0xc0, 0x80, 0xa7, 0xb2, 0x23, 0x4c, 0xf8, 0xae, 0xe8, 0xf6,
+        0xc4, 0x7b, 0xbf, 0x4f, 0xd3, 0xac, 0xe7, 0x24, 0x02, 0x90, 0xbe, 0xf1,
+        0x6c, 0x0b, 0x3f, 0x7f, 0x3c, 0xdd, 0x64, 0xce, 0x3a, 0xb5, 0x91, 0x2c,
+        0xf6, 0xe3, 0x2f, 0x39, 0xab, 0x18, 0x83, 0x58, 0xaf, 0xcc, 0xcd, 0x80,
+        0x81, 0x02, 0x41, 0x00, 0xe4, 0xb4, 0x9e, 0xf5, 0x0f, 0x76, 0x5d, 0x3b,
+        0x24, 0xdd, 0xe0, 0x1a, 0xce, 0xaa, 0xf1, 0x30, 0xf2, 0xc7, 0x66, 0x70,
+        0xa9, 0x1a, 0x61, 0xae, 0x08, 0xaf, 0x49, 0x7b, 0x4a, 0x82, 0xbe, 0x6d,
+        0xee, 0x8f, 0xcd, 0xd5, 0xe3, 0xf7, 0xba, 0x1c, 0xfb, 0x1f, 0x0c, 0x92,
+        0x6b, 0x88, 0xf8, 0x8c, 0x92, 0xbf, 0xab, 0x13, 0x7f, 0xba, 0x22, 0x85,
+        0x22, 0x7b, 0x83, 0xc3, 0x42, 0xff, 0x7c, 0x55, 0x02, 0x41, 0x00, 0xdd,
+        0xab, 0xb5, 0x83, 0x9c, 0x4c, 0x7f, 0x6b, 0xf3, 0xd4, 0x18, 0x32, 0x31,
+        0xf0, 0x05, 0xb3, 0x1a, 0xa5, 0x8a, 0xff, 0xdd, 0xa5, 0xc7, 0x9e, 0x4c,
+        0xce, 0x21, 0x7f, 0x6b, 0xc9, 0x30, 0xdb, 0xe5, 0x63, 0xd4, 0x80, 0x70,
+        0x6c, 0x24, 0xe9, 0xeb, 0xfc, 0xab, 0x28, 0xa6, 0xcd, 0xef, 0xd3, 0x24,
+        0xb7, 0x7e, 0x1b, 0xf7, 0x25, 0x1b, 0x70, 0x90, 0x92, 0xc2, 0x4f, 0xf5,
+        0x01, 0xfd, 0x91, 0x02, 0x40, 0x23, 0xd4, 0x34, 0x0e, 0xda, 0x34, 0x45,
+        0xd8, 0xcd, 0x26, 0xc1, 0x44, 0x11, 0xda, 0x6f, 0xdc, 0xa6, 0x3c, 0x1c,
+        0xcd, 0x4b, 0x80, 0xa9, 0x8a, 0xd5, 0x2b, 0x78, 0xcc, 0x8a, 0xd8, 0xbe,
+        0xb2, 0x84, 0x2c, 0x1d, 0x28, 0x04, 0x05, 0xbc, 0x2f, 0x6c, 0x1b, 0xea,
+        0x21, 0x4a, 0x1d, 0x74, 0x2a, 0xb9, 0x96, 0xb3, 0x5b, 0x63, 0xa8, 0x2a,
+        0x5e, 0x47, 0x0f, 0xa8, 0x8d, 0xbf, 0x82, 0x3c, 0xdd, 0x02, 0x40, 0x1b,
+        0x7b, 0x57, 0x44, 0x9a, 0xd3, 0x0d, 0x15, 0x18, 0x24, 0x9a, 0x5f, 0x56,
+        0xbb, 0x98, 0x29, 0x4d, 0x4b, 0x6a, 0xc1, 0x2f, 0xfc, 0x86, 0x94, 0x04,
+        0x97, 0xa5, 0xa5, 0x83, 0x7a, 0x6c, 0xf9, 0x46, 0x26, 0x2b, 0x49, 0x45,
+        0x26, 0xd3, 0x28, 0xc1, 0x1e, 0x11, 0x26, 0x38, 0x0f, 0xde, 0x04, 0xc2,
+        0x4f, 0x91, 0x6d, 0xec, 0x25, 0x08, 0x92, 0xdb, 0x09, 0xa6, 0xd7, 0x7c,
+        0xdb, 0xa3, 0x51, 0x02, 0x40, 0x77, 0x62, 0xcd, 0x8f, 0x4d, 0x05, 0x0d,
+        0xa5, 0x6b, 0xd5, 0x91, 0xad, 0xb5, 0x15, 0xd2, 0x4d, 0x7c, 0xcd, 0x32,
+        0xcc, 0xa0, 0xd0, 0x5f, 0x86, 0x6d, 0x58, 0x35, 0x14, 0xbd, 0x73, 0x24,
+        0xd5, 0xf3, 0x36, 0x45, 0xe8, 0xed, 0x8b, 0x4a, 0x1c, 0xb3, 0xcc, 0x4a,
+        0x1d, 0x67, 0x98, 0x73, 0x99, 0xf2, 0xa0, 0x9f, 0x5b, 0x3f, 0xb6, 0x8c,
+        0x88, 0xd5, 0xe5, 0xd9, 0x0a, 0xc3, 0x34, 0x92, 0xd6};
+
+    const keymaster_blob_t key_data = {key, sizeof(key)};
+
+    keymaster_blob_t export_data = {NULL, 0};
+
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[1].boolean = true;
+    key_param[2].tag = KM_TAG_PURPOSE;
+    key_param[2].enumerated = KM_PURPOSE_SIGN;
+    key_param[3].tag = KM_TAG_PURPOSE;
+    key_param[3].enumerated = KM_PURPOSE_VERIFY;
+    key_param[4].tag = KM_TAG_PADDING;
+    key_param[4].enumerated = KM_PAD_RSA_PSS;
+    key_param[5].tag = KM_TAG_DIGEST;
+    key_param[5].enumerated = KM_DIGEST_SHA1;
+    paramset.length = 6;
+    CHECK_RESULT_OK(device->import_key(device,
+        &paramset, KM_KEY_FORMAT_PKCS8, &key_data, &key_blob, &pkey_characteristics));
+    print_characteristics(pkey_characteristics);
+
+    CHECK_RESULT_OK(test_km_rsa_sign_verify(device,
+        &key_blob, 128, KM_PAD_RSA_PSS, KM_DIGEST_SHA1));
+
+    CHECK_RESULT_OK(device->export_key(device,
+        KM_KEY_FORMAT_X509, &key_blob, NULL, NULL, &export_data));
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    free(pkey_characteristics);
+    km_free_blob(&export_data);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
+
+keymaster_error_t test_km_rsa(
+    keymaster1_device_t *device,
+    uint32_t keysize,
+    uint64_t e)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_key_param_t key_param[18];
+    keymaster_key_param_set_t paramset = {key_param, 0};
+    keymaster_key_blob_t key_blob = {0, 0};
+    keymaster_key_characteristics_t *pkey_characteristics = NULL;
+    uint32_t keybytes = BYTES_PER_BITS(keysize);
+
+    LOG_I("Generate %d-bit key, public exponent %" PRIu64 "...", keysize, e);
+    key_param[0].tag = KM_TAG_ALGORITHM;
+    key_param[0].enumerated = KM_ALGORITHM_RSA;
+    key_param[1].tag = KM_TAG_KEY_SIZE;
+    key_param[1].integer = keysize;
+    key_param[2].tag = KM_TAG_RSA_PUBLIC_EXPONENT;
+    key_param[2].long_integer = e;
+    key_param[3].tag = KM_TAG_NO_AUTH_REQUIRED;
+    key_param[3].boolean = true;
+    key_param[4].tag = KM_TAG_PURPOSE;
+    key_param[4].enumerated = KM_PURPOSE_SIGN;
+    key_param[5].tag = KM_TAG_PURPOSE;
+    key_param[5].enumerated = KM_PURPOSE_VERIFY;
+    key_param[6].tag = KM_TAG_PURPOSE;
+    key_param[6].enumerated = KM_PURPOSE_ENCRYPT;
+    key_param[7].tag = KM_TAG_PURPOSE;
+    key_param[7].enumerated = KM_PURPOSE_DECRYPT;
+    key_param[8].tag = KM_TAG_PADDING;
+    key_param[8].enumerated = KM_PAD_NONE;
+    key_param[9].tag = KM_TAG_PADDING;
+    key_param[9].enumerated = KM_PAD_RSA_PSS;
+    key_param[10].tag = KM_TAG_PADDING;
+    key_param[10].enumerated = KM_PAD_RSA_PKCS1_1_5_SIGN;
+    key_param[11].tag = KM_TAG_PADDING;
+    key_param[11].enumerated = KM_PAD_RSA_OAEP;
+    key_param[12].tag = KM_TAG_PADDING;
+    key_param[12].enumerated = KM_PAD_RSA_PKCS1_1_5_ENCRYPT;
+    key_param[13].tag = KM_TAG_DIGEST;
+    key_param[13].enumerated = KM_DIGEST_NONE;
+    key_param[14].tag = KM_TAG_DIGEST;
+    key_param[14].enumerated = KM_DIGEST_SHA1;
+    key_param[15].tag = KM_TAG_DIGEST;
+    key_param[15].enumerated = KM_DIGEST_SHA_2_256;
+    key_param[16].tag = KM_TAG_DIGEST;
+    key_param[16].enumerated = KM_DIGEST_NONE;
+    key_param[17].tag = KM_TAG_DIGEST;
+    key_param[17].enumerated = KM_DIGEST_MD5;
+    paramset.length = 18;
+    CHECK_RESULT_OK(device->generate_key(device,
+        &paramset, &key_blob, &pkey_characteristics));
+
+    print_characteristics(pkey_characteristics);
+
+    LOG_I("Sign/verify with KM_PAD_RSA_PSS and SHA1...");
+    CHECK_RESULT_OK( test_km_rsa_sign_verify(
+        device, &key_blob, keybytes, KM_PAD_RSA_PSS, KM_DIGEST_SHA1) );
+
+    LOG_I("Sign/verify with KM_PAD_RSA_PSS and SHA256...");
+    CHECK_RESULT_OK( test_km_rsa_sign_verify(
+        device, &key_blob, keybytes, KM_PAD_RSA_PSS, KM_DIGEST_SHA_2_256) );
+
+    LOG_I("Sign/verify with KM_PAD_RSA_PKCS1_1_5_SIGN and SHA1...");
+    CHECK_RESULT_OK( test_km_rsa_sign_verify(
+        device, &key_blob, keybytes, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_DIGEST_SHA1) );
+
+    LOG_I("Sign/verify with KM_PAD_RSA_PKCS1_1_5_SIGN and SHA256...");
+    CHECK_RESULT_OK( test_km_rsa_sign_verify(
+        device, &key_blob, keybytes, KM_PAD_RSA_PKCS1_1_5_SIGN, KM_DIGEST_SHA_2_256) );
+
+    LOG_I("Sign/verify with KM_PAD_RSA_PKCS1_1_5_SIGN and no digest [sic]...");
+    CHECK_RESULT_OK( test_km_rsa_sign_verify_pkcs1_1_5_raw(
+        device, &key_blob, keybytes) );
+
+    LOG_I("Sign/verify with empty message...");
+    CHECK_RESULT_OK( test_km_rsa_sign_verify_empty_message(
+        device, &key_blob, keybytes) );
+
+    LOG_I("Sign/verify with KM_PAD_RSA_PKCS1_1_5_SIGN and no digest, message too long...");
+    CHECK_RESULT_OK(test_km_rsa_sign_verify_pkcs1_no_digest_too_long(
+        device, &key_blob, keybytes));
+
+    LOG_I("Verify with empty signature...");
+    CHECK_RESULT_OK(test_km_rsa_verify_empty_signature(
+        device, &key_blob, keybytes));
+
+    LOG_I("Encrypt/decrypt with KM_PAD_RSA_OAEP and SHA1...");
+    CHECK_RESULT_OK( test_km_rsa_encrypt_decrypt(
+        device, &key_blob, keybytes, KM_PAD_RSA_OAEP, KM_DIGEST_SHA1) );
+    LOG_I("Encrypt/decrypt with KM_PAD_RSA_OAEP and SHA256...");
+    CHECK_RESULT_OK( test_km_rsa_encrypt_decrypt(
+        device, &key_blob, keybytes, KM_PAD_RSA_OAEP, KM_DIGEST_SHA_2_256) );
+
+    LOG_I("Encrypt/decrypt with KM_PAD_RSA_PKCS1_1_5_ENCRYPT...");
+    CHECK_RESULT_OK( test_km_rsa_encrypt_decrypt(
+        device, &key_blob, keybytes, KM_PAD_RSA_PKCS1_1_5_ENCRYPT, KM_DIGEST_NONE) );
+
+    LOG_I("Encrypt/decrypt with KM_PAD_NONE...");
+    CHECK_RESULT_OK( test_km_rsa_encrypt_decrypt(
+        device, &key_blob, keybytes, KM_PAD_NONE, KM_DIGEST_NONE) );
+
+    LOG_I("Encrypt/decrypt with KM_PAD_NONE and no digest provided...");
+    CHECK_RESULT_OK( test_km_rsa_encrypt_decrypt(
+        device, &key_blob, keybytes, KM_PAD_NONE, nullptr));
+
+    LOG_I("Encrypt with KM_PAD_NONE, message numerically larger than modulus...");
+    CHECK_RESULT_OK(test_km_rsa_raw_too_large(
+        device, &key_blob, keybytes));
+
+    LOG_I("Encrypt/decrypt 1 with KM_PAD_NONE...");
+    CHECK_RESULT_OK(test_km_rsa_encrypt_raw_one(
+        device, &key_blob, keybytes));
+
+    LOG_I("Encrypt/decrypt with KM_PAD_RSA_PKCS1_1_5_ENCRYPT and empty message...");
+    CHECK_RESULT_OK( test_km_rsa_encrypt_decrypt_empty_message(
+        device, &key_blob, keybytes, KM_PAD_RSA_PKCS1_1_5_ENCRYPT) );
+
+    LOG_I("Concurrent RSA operations...");
+    CHECK_RESULT_OK(test_km_rsa_concurrent(
+        device, &key_blob, keybytes));
+
+end:
+    keymaster_free_characteristics(pkey_characteristics);
+    km_free_key_blob(&key_blob);
+
+    return res;
+}
diff --git a/libkeymaster/ver1/test/test_km_rsa.h b/libkeymaster/ver1/test/test_km_rsa.h
new file mode 100644 (file)
index 0000000..b3b39fe
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_KM_RSA_H__
+#define __TEST_KM_RSA_H__
+
+#include <hardware/keymaster1.h>
+
+keymaster_error_t test_km_rsa_import_export(
+    keymaster1_device_t *device);
+
+keymaster_error_t test_km_rsa(
+    keymaster1_device_t *device,
+    uint32_t keysize,
+    uint64_t e);
+
+#endif /* __TEST_KM_RSA_H__ */
diff --git a/libkeymaster/ver1/test/test_km_util.cpp b/libkeymaster/ver1/test/test_km_util.cpp
new file mode 100644 (file)
index 0000000..cbb757f
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <hardware/keymaster_defs.h>
+#include <hardware/keymaster1.h>
+
+#include "test_km_util.h"
+
+#undef  LOG_ANDROID
+#undef  LOG_TAG
+#define LOG_TAG "TlcTeeKeyMasterTest"
+#include "log.h"
+
+// static void print_blob(
+//     const keymaster_blob_t *blob)
+// {
+//     print_buffer(blob->data, blob->data_length);
+// }
+
+static void print_uint64(
+    uint64_t x)
+{
+    printf("0x%08x%08x\n", (uint32_t)(x >> 32), (uint32_t)(x & 0xFFFFFFFF));
+}
+
+static void print_bool(
+    bool x)
+{
+    if (x) {
+        printf("true\n");
+    } else {
+        printf("false\n");
+    }
+}
+
+static void print_param_set(
+    const keymaster_key_param_set_t *param_set)
+{
+    for (size_t i = 0; i < param_set->length; i++) {
+        const keymaster_key_param_t param = param_set->params[i];
+        switch (param.tag) {
+#define PRINT_ENUM printf("0x%08x\n", param.enumerated)
+#define PRINT_UINT printf("%u\n", param.integer)
+#define PRINT_ULONG print_uint64(param.long_integer)
+#define PRINT_BOOL print_bool(param.boolean)
+#define PRINT_DATETIME print_uint64(param.date_time)
+#define PARAM_CASE(tag, printval) \
+    case tag: \
+        printf("%s: ", #tag); \
+        printval; \
+        break;
+#define PARAM_CASE_ENUM(tag) PARAM_CASE(tag, PRINT_ENUM)
+#define PARAM_CASE_UINT(tag) PARAM_CASE(tag, PRINT_UINT)
+#define PARAM_CASE_ULONG(tag) PARAM_CASE(tag, PRINT_ULONG)
+#define PARAM_CASE_BOOL(tag) PARAM_CASE(tag, PRINT_BOOL)
+#define PARAM_CASE_DATETIME(tag) PARAM_CASE(tag, PRINT_DATETIME)
+        PARAM_CASE_DATETIME(KM_TAG_ACTIVE_DATETIME)
+        PARAM_CASE_ENUM(KM_TAG_ALGORITHM)
+        PARAM_CASE_UINT(KM_TAG_AUTH_TIMEOUT)
+        PARAM_CASE_ENUM(KM_TAG_BLOB_USAGE_REQUIREMENTS)
+        PARAM_CASE_ENUM(KM_TAG_BLOCK_MODE)
+        PARAM_CASE_BOOL(KM_TAG_BOOTLOADER_ONLY)
+        PARAM_CASE_BOOL(KM_TAG_CALLER_NONCE)
+        PARAM_CASE_DATETIME(KM_TAG_CREATION_DATETIME)
+        PARAM_CASE_ENUM(KM_TAG_DIGEST)
+        PARAM_CASE_UINT(KM_TAG_KEY_SIZE)
+        PARAM_CASE_UINT(KM_TAG_MAX_USES_PER_BOOT)
+        PARAM_CASE_UINT(KM_TAG_MIN_MAC_LENGTH)
+        PARAM_CASE_UINT(KM_TAG_MIN_SECONDS_BETWEEN_OPS)
+        PARAM_CASE_BOOL(KM_TAG_NO_AUTH_REQUIRED)
+        PARAM_CASE_ENUM(KM_TAG_ORIGIN)
+        PARAM_CASE_DATETIME(KM_TAG_ORIGINATION_EXPIRE_DATETIME)
+        PARAM_CASE_ENUM(KM_TAG_PADDING)
+        PARAM_CASE_ENUM(KM_TAG_PURPOSE)
+        PARAM_CASE_BOOL(KM_TAG_ROLLBACK_RESISTANT)
+        PARAM_CASE_ULONG(KM_TAG_RSA_PUBLIC_EXPONENT)
+        PARAM_CASE_DATETIME(KM_TAG_USAGE_EXPIRE_DATETIME)
+        PARAM_CASE_ENUM(KM_TAG_USER_AUTH_TYPE)
+        PARAM_CASE_ULONG(KM_TAG_USER_SECURE_ID)
+#undef PARAM_CASE_ENUM
+#undef PARAM_CASE_UINT
+#undef PARAM_CASE_ULONG
+#undef PARAM_CASE_BOOL
+#undef PARAM_CASE_DATETIME
+#undef PARAM_CASE
+#undef PRINT_ENUM
+#undef PRINT_UINT
+#undef PRINT_ULONG
+#undef PRINT_BOOL
+#undef PRINT_DATETIME
+            default:
+                printf("(unknown tag 0x%08x)\n", param.tag);
+        }
+    }
+}
+
+void print_buffer(
+    const uint8_t *buf,
+    size_t buflen)
+{
+    printf("[");
+    for (size_t i = 0; i < buflen; i++) {
+        printf("0x%02x, ", buf[i]);
+    }
+    printf("]\n");
+}
+
+void print_characteristics(
+    const keymaster_key_characteristics_t *characteristics)
+{
+    printf("\nHardware-enforced characteristics:\n");
+    print_param_set(&characteristics->hw_enforced);
+    printf("\nSoftware-enforced characteristics:\n");
+    print_param_set(&characteristics->sw_enforced);
+}
+
+keymaster_error_t print_raw_key(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob)
+{
+    keymaster_error_t res = KM_ERROR_OK;
+    keymaster_blob_t key_data = {0, 0};
+
+    CHECK_RESULT_OK( device->export_key(device,
+        KM_KEY_FORMAT_RAW, key_blob, NULL, NULL, &key_data) );
+    
+    print_buffer(key_data.data, key_data.data_length);
+
+end:
+    km_free_blob(&key_data);
+    return res;
+}
+
+uint32_t block_length(
+    keymaster_digest_t digest)
+{
+    switch (digest) {
+        case KM_DIGEST_MD5:
+            return 128;
+        case KM_DIGEST_SHA1:
+            return 160;
+        case KM_DIGEST_SHA_2_224:
+            return 224;
+        case KM_DIGEST_SHA_2_256:
+            return 256;
+        case KM_DIGEST_SHA_2_384:
+            return 384;
+        case KM_DIGEST_SHA_2_512:
+            return 512;
+        default:
+            return 0;
+    }
+}
+
+void km_free_blob(
+    keymaster_blob_t *blob)
+{
+    if (blob != NULL) {
+        free((void*)blob->data);
+        blob->data = NULL;
+        blob->data_length = 0;
+    }
+}
+
+void km_free_key_blob(
+    keymaster_key_blob_t *key_blob)
+{
+    if (key_blob != NULL) {
+        free((void*)key_blob->key_material);
+        key_blob->key_material = NULL;
+        key_blob->key_material_size = 0;
+    }
+}
diff --git a/libkeymaster/ver1/test/test_km_util.h b/libkeymaster/ver1/test/test_km_util.h
new file mode 100644 (file)
index 0000000..a1ff2fb
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEST_KM_UTIL_H__
+#define __TEST_KM_UTIL_H__
+
+#include <hardware/keymaster_defs.h>
+#include <hardware/keymaster1.h>
+
+#define BYTES_PER_BITS(nbits) (((nbits) + 7) / 8)
+
+#define CHECK_RESULT(result, expr) \
+    do { \
+        keymaster_error_t res1 = (expr); \
+        if (res1 != result) { \
+            LOG_E("%s == %d, expected %d", #expr, res1, result); \
+            res = KM_ERROR_UNKNOWN_ERROR; \
+            goto end; \
+        } \
+    } while (0)
+
+#define FREE(ptr) \
+    do { \
+        free(ptr); \
+        ptr = NULL; \
+    } while (0)
+
+#define CHECK_RESULT_OK(expr) \
+    do { \
+        res = (expr); \
+        if (res != KM_ERROR_OK) { \
+            LOG_E("%s == %d\n", #expr, res); \
+            goto end; \
+        } \
+    } while (0)
+
+#define CHECK_TRUE(expr) \
+    do { \
+        if (!(expr)) { \
+            LOG_E("'%s' is false", #expr); \
+            res = KM_ERROR_UNKNOWN_ERROR; \
+            goto end; \
+        } \
+    } while (false)
+
+void print_buffer(
+    const uint8_t *buf,
+    size_t buflen);
+
+void print_characteristics(
+    const keymaster_key_characteristics_t *characteristics);
+
+keymaster_error_t print_raw_key(
+    keymaster1_device_t *device,
+    const keymaster_key_blob_t *key_blob);
+
+/**
+ * Block length corresponding to hash.
+ * 
+ * @param digest digest algorithm
+ * @return hash output size in bits
+ * @retval 0 invalid \p digest
+ */
+uint32_t block_length(
+    keymaster_digest_t digest);
+
+void km_free_blob(
+    keymaster_blob_t *blob);
+
+void km_free_key_blob(
+    keymaster_key_blob_t *key_blob);
+
+#endif /* __TEST_KM_UTIL_H__ */
diff --git a/libvirtualdisplaymodule/Android.mk b/libvirtualdisplaymodule/Android.mk
new file mode 100644 (file)
index 0000000..818fbc4
--- /dev/null
@@ -0,0 +1,22 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifeq ($(BOARD_USES_VDS_BGRA8888), true)
+LOCAL_C_INCLUDES += \
+       $(TOP)/hardware/samsung_slsi/$(TARGET_SOC)/libhwcutilsmodule \
+       $(TOP)/hardware/samsung_slsi/exynos/libmpp
+endif
+
+LOCAL_SRC_FILES += \
+       ./../../$(TARGET_SOC)/libvirtualdisplaymodule/ExynosVirtualDisplayModule.cpp
diff --git a/libvirtualdisplaymodule/ExynosVirtualDisplayModule.cpp b/libvirtualdisplaymodule/ExynosVirtualDisplayModule.cpp
new file mode 100644 (file)
index 0000000..e3f2287
--- /dev/null
@@ -0,0 +1,692 @@
+#include "ExynosVirtualDisplayModule.h"
+#include "ExynosHWCUtils.h"
+#include "ExynosMPPModule.h"
+
+#ifdef EVD_DBUG
+#define DISPLAY_LOGD(msg, ...) ALOGD("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGV(msg, ...) ALOGV("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGI(msg, ...) ALOGI("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGW(msg, ...) ALOGW("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGE(msg, ...) ALOGE("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#else
+#define DISPLAY_LOGD(msg, ...)
+#define DISPLAY_LOGV(msg, ...)
+#define DISPLAY_LOGI(msg, ...)
+#define DISPLAY_LOGW(msg, ...)
+#define DISPLAY_LOGE(msg, ...)
+#endif
+
+ExynosVirtualDisplayModule::ExynosVirtualDisplayModule(struct exynos5_hwc_composer_device_1_t *pdev)
+    : ExynosVirtualDisplay(pdev)
+{
+    mGLESFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+    mDisplayFd  = 0;
+}
+
+void ExynosVirtualDisplayModule::determineYuvOverlay(hwc_display_contents_1_t *contents)
+{
+    DISPLAY_LOGD("EVD::determineYuvOverlay");
+
+    mForceOverlayLayerIndex = -1;
+    mHasDrmSurface = false;
+    mYuvLayers = 0;
+    mForceFb = false;
+    mIsSecureDRM = false;
+    mIsNormalDRM = false;
+
+    if (contents->outbuf) {
+        private_handle_t *h = private_handle_t::dynamicCast(contents->outbuf);
+        mExternalMPPDstFormat = h->format;
+    } else {
+        DISPLAY_LOGD("BufferQueue is abandoned.");
+    }
+
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        ExynosMPPModule* supportedExternalMPP = NULL;
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+        if (layer.handle) {
+            private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
+
+            /* check yuv drm surface */
+            if (!mForceFb && !isFormatRgb(handle->format) && (getDrmMode(handle->flags) != NO_DRM)) {
+                if (isOverlaySupported(contents->hwLayers[i], i, false, NULL, &supportedExternalMPP))
+                {
+                        this->mYuvLayers++;
+
+                        /* If not DRM layer is addressed before */
+                        if (mHasDrmSurface == false) {
+                            /* Assign MPP */
+                            if (supportedExternalMPP != NULL)
+                                supportedExternalMPP->mState = MPP_STATE_ASSIGNED;
+
+                            mForceOverlayLayerIndex = i;
+                            layer.compositionType = HWC_OVERLAY;
+                            mLayerInfos[i]->mExternalMPP = supportedExternalMPP;
+                            mLayerInfos[i]->mInternalMPP = NULL;
+                            mLayerInfos[i]->compositionType = layer.compositionType;
+                            mLayerInfos[i]->mWindowIndex = i;
+                            supportedExternalMPP->setDisplay(this);
+
+                            if (getDrmMode(handle->flags) == SECURE_DRM) {
+                                mIsSecureDRM = true;
+                                mOverlayLayer = &layer;
+                                DISPLAY_LOGD("determineYuvOverlay: secure drm layer, %d", i);
+                            }
+
+                            /* todo: selecting overlay composition but need to check for EGL */
+                            if (getDrmMode(handle->flags) == NORMAL_DRM) {
+                                mIsNormalDRM = true;
+                                mOverlayLayer = &layer;
+                                calcDisplayRect(layer);
+                                DISPLAY_LOGD("determineYuvOverlay: normal drm layer, %d", i);
+                            }
+                        }
+                    } else {
+                    if (getDrmMode(handle->flags) != NO_DRM) {
+                            /* This layer should be overlay but HWC can't handle it */
+                            layer.compositionType = HWC_OVERLAY;
+                            mLayerInfos[i]->compositionType = layer.compositionType;
+                            layer.flags |= HWC_SKIP_RENDERING;
+                        }
+                    }
+
+                    if (getDrmMode(handle->flags) != NO_DRM) {
+                        this->mHasDrmSurface = true;
+                    mForceOverlayLayerIndex = i;
+                }
+            }
+        }
+    }
+}
+
+void ExynosVirtualDisplayModule::determineSupportedOverlays(hwc_display_contents_1_t *contents)
+{
+    DISPLAY_LOGD("determineSupportedOverlays");
+
+    int ret = 0;
+    mIsRotationState = false;
+    mCompositionType = COMPOSITION_GLES;
+    mOverlayLayer = NULL;
+    mFBTargetLayer = NULL;
+    memset(mFBLayer, 0x0, sizeof(mFBLayer));
+    mNumFB = 0;
+    mFbNeeded = false;
+
+    if (contents->outbuf) {
+        private_handle_t *h = private_handle_t::dynamicCast(contents->outbuf);
+        DISPLAY_LOGD("DSO: Outbuf layer f=%x, fds[%d](%d, %d, %d), sz(%d) wxh(%dx%d)m stride(%d) fence(%d) P(%d)",
+                    h->format, h->sNumFds, h->fd, h->fd1, h->fd2, h->size, h->width,
+                    h->height, h->stride, contents->outbufAcquireFenceFd, getDrmMode(h->flags));
+        mExternalMPPDstFormat = h->format;
+    }
+
+    /* determine composition type */
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+        if (layer.handle) {
+            private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
+            DISPLAY_LOGD("DSO: layer %d type=%d, f=%x, w=%d, h=%d, s=%d, vs=%d, "
+                  "{%.1f, %.1f, %.1f, %.1f}, {%d, %d, %d, %d}"
+                  "fl=%08x, hdl=%p, trf=%02x, bl=%04x, Af=%d, Rf=%d, P=%d",
+                    i, layer.compositionType, h->format, h->width, h->height, h->stride,
+                    h->vstride, layer.sourceCropf.left, layer.sourceCropf.top,
+                    layer.sourceCropf.right, layer.sourceCropf.bottom,
+                    layer.displayFrame.left, layer.displayFrame.top,
+                    layer.displayFrame.right, layer.displayFrame.bottom,
+                    layer.flags, layer.handle, layer.transform, layer.blending,
+                    layer.acquireFenceFd, layer.releaseFenceFd, getDrmMode(layer.flags));
+        }
+
+        if (!mFbNeeded) {
+            mFirstFb = i;
+            mFbNeeded = true;
+        }
+        mLastFb = i;
+    }
+}
+
+bool ExynosVirtualDisplayModule::isOverlaySupported(hwc_layer_1_t &layer, size_t index,
+        bool useVPPOverlay, ExynosMPPModule **supportedInternalMPP,
+        ExynosMPPModule **supportedExternalMPP)
+{
+    int ret = 0;
+    private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
+    ExynosMPPModule *externalMPP = mExternalMPPs[WFD_EXT_MPP_IDX];
+    unsigned int bpp = formatToBpp(handle->format);
+    unsigned int left = max(layer.displayFrame.left, 0);
+    unsigned int right = layer.displayFrame.right;
+    unsigned int visible_width = 0;
+
+    DISPLAY_LOGD(" isOverlaySupported:: index(%d)", index);
+
+    float width = 0;
+    float height = 0;
+
+    if (layer.flags & HWC_SKIP_LAYER) {
+        mLayerInfos[index]->mCheckOverlayFlag |= eSkipLayer;
+        DISPLAY_LOGD("\tlayer %u: skipping", index);
+        return false;
+    }
+
+    if (!handle) {
+        DISPLAY_LOGD("\tlayer %u: handle is NULL", index);
+        mLayerInfos[index]->mCheckOverlayFlag |= eInvalidHandle;
+        return false;
+    }
+
+    width = layer.sourceCropf.right - layer.sourceCropf.left;
+    height = layer.sourceCropf.bottom - layer.sourceCropf.top;
+
+    if ((bpp == 16) &&
+            ((layer.displayFrame.left % 2 != 0) || (layer.displayFrame.right % 2 != 0))) {
+        DISPLAY_LOGD("\tlayer %u: eNotAlignedDstPosition", index);
+        mLayerInfos[index]->mCheckOverlayFlag |= eNotAlignedDstPosition;
+        return false;
+    }
+
+    visible_width = (right - left) * bpp / 8;
+    if (visible_width < BURSTLEN_BYTES) {
+        DISPLAY_LOGD("\tlayer %u: visible area is too narrow", index);
+        mLayerInfos[index]->mCheckOverlayFlag |= eUnsupportedDstWidth;
+        return false;
+    }
+
+    if (!isFormatRgb(handle->format)) {
+        ret = externalMPP->isFormatSupportedByMPP(mExternalMPPDstFormat);
+        if (ret > 0) {
+            *supportedExternalMPP = externalMPP;
+            return true;
+        } else {
+            DISPLAY_LOGD("\tlayer %u: %d ProcessingNotSupported", index, -ret);
+            mLayerInfos[index]->mCheckMPPFlag |= -ret;
+        }
+    }
+
+    /* Can't find valid MPP */
+    DISPLAY_LOGD("\tlayer %u: can't find valid MPP", index);
+    mLayerInfos[index]->mCheckOverlayFlag |= eInsufficientMPP;
+    return false;
+}
+
+int ExynosVirtualDisplayModule::prepare(hwc_display_contents_1_t *contents)
+{
+    int ret = 0;
+    mIsRotationState = false;
+    mCompositionType = COMPOSITION_GLES;
+    mOverlayLayer = NULL;
+    mFBTargetLayer = NULL;
+    memset(mFBLayer, 0x0, sizeof(mFBLayer));
+    mNumFB = 0;
+
+    if (contents->outbuf) {
+        private_handle_t *h = private_handle_t::dynamicCast(contents->outbuf);
+        DISPLAY_LOGD("PREP: Outbuf layer f=%x, fds[%d](%d, %d, %d), sz(%d) wxh(%dx%d)m stride(%d) Af(%d) P(%d)",
+                    h->format, h->sNumFds, h->fd, h->fd1, h->fd2, h->size, h->width,
+                    h->height, h->stride, contents->outbufAcquireFenceFd, getDrmMode(h->flags));
+        mExternalMPPDstFormat = h->format;
+    }
+
+    /* determine composition type */
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+        if (layer.compositionType == HWC_FRAMEBUFFER) {
+            if (!layer.handle)
+                mNumFB++;
+            goto cont;
+        }
+
+        if (layer.compositionType == HWC_OVERLAY) {
+            if (!layer.handle)
+                goto cont;
+
+            if (layer.flags & HWC_SKIP_RENDERING) {
+                layer.releaseFenceFd = layer.acquireFenceFd;
+                goto cont;
+            }
+
+            mOverlayLayer = &layer;
+            goto cont;
+        }
+
+        if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+            if (!layer.handle)
+                goto cont;
+
+            mFBTargetLayer = &layer;
+            goto cont;
+        }
+
+cont:
+        if (layer.handle) {
+            private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
+            DISPLAY_LOGD("PREP: layer %d type=%d, f=%x, w=%d, h=%d, s=%d, vs=%d, "
+                  "{%.1f, %.1f, %.1f, %.1f}, {%d, %d, %d, %d}"
+                  "fl=%08x, hdl=%p, trf=%02x, bl=%04x, Af=%d, Rf=%d, P=%d",
+                    i, layer.compositionType, h->format, h->width, h->height, h->stride,
+                    h->vstride, layer.sourceCropf.left, layer.sourceCropf.top,
+                    layer.sourceCropf.right, layer.sourceCropf.bottom,
+                    layer.displayFrame.left, layer.displayFrame.top,
+                    layer.displayFrame.right, layer.displayFrame.bottom,
+                    layer.flags, layer.handle, layer.transform, layer.blending,
+                    layer.acquireFenceFd, layer.releaseFenceFd, getDrmMode(layer.flags));
+        }
+    }
+
+    if (mOverlayLayer && (mNumFB > 0))
+        mCompositionType = COMPOSITION_MIXED;
+    else if (mOverlayLayer || mIsRotationState)
+        mCompositionType = COMPOSITION_HWC;
+
+    DISPLAY_LOGD("prepare cType 0x%x, PrevCType 0x%x, ovl 0x%p, mNumFB %d",
+        mCompositionType, mPrevCompositionType, mOverlayLayer, mNumFB);
+
+    setSinkBufferUsage();
+
+    if (mCompositionType != mPrevCompositionType) {
+        DISPLAY_LOGD("prepare mCompositionType 0x%x, mPrevCompositionType are not same\n");
+            ExynosMPPModule* externalMPP = mExternalMPPs[WFD_EXT_MPP_IDX];
+
+            externalMPP->mDstBuffers[externalMPP->mCurrentBuf] = NULL;
+            externalMPP->mDstBufFence[externalMPP->mCurrentBuf] = -1;
+            externalMPP->cleanupM2M();
+            externalMPP->setDisplay(this);
+    }
+    return 0;
+}
+
+int ExynosVirtualDisplayModule::set(hwc_display_contents_1_t *contents)
+{
+    DISPLAY_LOGD("set %u layers for virtual, mCompositionType %d, contents->outbuf %p",
+        contents->numHwLayers, mCompositionType, contents->outbuf);
+    mOverlayLayer = NULL;
+    mFBTargetLayer = NULL;
+    memset(mFBLayer, 0x0, sizeof(mFBLayer));
+    int IsNormalDRMWithSkipLayer = false;
+    mNumFB = 0;
+
+    if (contents->outbuf) {
+        private_handle_t *h = private_handle_t::dynamicCast(contents->outbuf);
+        DISPLAY_LOGD("prepare: Outbuf layer f=%x, fds[%d](%d, %d, %d), sz(%d) wxh(%dx%d)m stride(%d) fence(%d) P(%d)",
+                    h->format, h->sNumFds, h->fd, h->fd1, h->fd2, h->size, h->width,
+                    h->height, h->stride, contents->outbufAcquireFenceFd, getDrmMode(h->flags));
+        mExternalMPPDstFormat = h->format;
+    }
+
+    /* Find normal drm layer with HWC_SKIP_LAYER, HDCP disabled and normal DRM */
+     for (size_t i = 0; i < contents->numHwLayers; i++) {
+         hwc_layer_1_t &layer = contents->hwLayers[i];
+         if (layer.flags & HWC_SKIP_LAYER) {
+             DISPLAY_LOGE("set skipping layer %d", i);
+             if (layer.handle) {
+                 private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
+                 if (getDrmMode(h->flags) == NORMAL_DRM && mIsWFDState) {
+                     DISPLAY_LOGE("set skipped normal drm layer %d", i);
+                     IsNormalDRMWithSkipLayer = true;
+                 }
+             }
+             continue;
+         }
+    }
+
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+        if (layer.compositionType == HWC_FRAMEBUFFER) {
+            if (!layer.handle)
+                goto cont;
+            mNumFB++;
+        }
+
+        if (layer.compositionType == HWC_OVERLAY) {
+            if (!layer.handle)
+                goto cont;
+
+            if (layer.flags & HWC_SKIP_RENDERING) {
+                goto cont;
+            }
+
+            mOverlayLayer = &layer;
+            goto cont;
+        }
+
+        if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+            if (!layer.handle)
+                goto cont;
+
+            mFBTargetLayer = &layer;
+            goto cont;
+        }
+
+cont:
+        if (layer.handle) {
+            private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
+            DISPLAY_LOGD("SET: layer %d type=%d, f=%x, w=%d, h=%d, s=%d, vs=%d, "
+                  "{%.1f, %.1f, %.1f, %.1f}, {%d, %d, %d, %d}"
+                  "fl=%08x, hdl=%p, trf=%02x, bl=%04x, Af=%d, Rf=%d, P=%d",
+                    i, layer.compositionType, h->format, h->width, h->height, h->stride,
+                    h->vstride, layer.sourceCropf.left, layer.sourceCropf.top,
+                    layer.sourceCropf.right, layer.sourceCropf.bottom,
+                    layer.displayFrame.left, layer.displayFrame.top,
+                    layer.displayFrame.right, layer.displayFrame.bottom,
+                    layer.flags, layer.handle, layer.transform, layer.blending,
+                    layer.acquireFenceFd, layer.releaseFenceFd, getDrmMode(layer.flags));
+        }
+    }
+
+    if (mFBTargetLayer && IsNormalDRMWithSkipLayer) {
+        for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+            if (layer.acquireFenceFd >= 0 && layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+                close(layer.acquireFenceFd);
+                layer.acquireFenceFd = -1;
+            }
+        }
+
+        if (mFBTargetLayer && mFBTargetLayer->acquireFenceFd >= 0)
+            contents->retireFenceFd = mFBTargetLayer->acquireFenceFd;
+
+        if (contents->outbufAcquireFenceFd >= 0) {
+            close(contents->outbufAcquireFenceFd);
+            contents->outbufAcquireFenceFd = -1;
+        }
+    } else if (mFBTargetLayer && mCompositionType == COMPOSITION_GLES) {
+        processGles(contents);
+    } else if (mFBTargetLayer && mOverlayLayer && mCompositionType == COMPOSITION_MIXED) {
+        processMixed(contents);
+    } else if (mOverlayLayer) {
+        processHwc(contents);
+    } else {
+        for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+            if (layer.acquireFenceFd >= 0 && layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+                close(layer.acquireFenceFd);
+                layer.acquireFenceFd = -1;
+            }
+        }
+
+        if (mFBTargetLayer && mFBTargetLayer->acquireFenceFd >= 0)
+            contents->retireFenceFd = mFBTargetLayer->acquireFenceFd;
+
+        if (contents->outbufAcquireFenceFd >= 0) {
+            close(contents->outbufAcquireFenceFd);
+            contents->outbufAcquireFenceFd = -1;
+        }
+    }
+
+    mPrevCompositionType = mCompositionType;
+
+    return 0;
+}
+
+void ExynosVirtualDisplayModule::processGles(hwc_display_contents_1_t *contents)
+{
+    DISPLAY_LOGD("processGles, FBTgt->acqFence %d, FBTgt->relFence %d, outbufAcqFence %d",
+        mFBTargetLayer->acquireFenceFd, mFBTargetLayer->releaseFenceFd,
+        contents->outbufAcquireFenceFd);
+
+    if (mFBTargetLayer != NULL && mFBTargetLayer->acquireFenceFd >= 0)
+        contents->retireFenceFd = mFBTargetLayer->acquireFenceFd;
+
+    if (contents->outbufAcquireFenceFd >= 0) {
+        close(contents->outbufAcquireFenceFd);
+        contents->outbufAcquireFenceFd = -1;
+    }
+}
+
+void ExynosVirtualDisplayModule::processHwc(hwc_display_contents_1_t *contents)
+{
+    DISPLAY_LOGD("processHwc, outbufAcqFence %d", contents->outbufAcquireFenceFd);
+
+    int fence = postFrame(contents);
+
+    manageFences(contents, fence);
+}
+
+void ExynosVirtualDisplayModule::processMixed(hwc_display_contents_1_t *contents)
+{
+    DISPLAY_LOGD("processMixed, FBTgt->acqFence %d, FBTgt->relFence %d, outbufAcqFence %d",
+        mFBTargetLayer->acquireFenceFd, mFBTargetLayer->releaseFenceFd,
+        contents->outbufAcquireFenceFd);
+
+    int fence = postFrame(contents);
+
+    manageFences(contents, fence);
+}
+
+int ExynosVirtualDisplayModule::postFrame(hwc_display_contents_1_t *contents)
+{
+    int ret = -1;
+    int win_map = 0;
+    int tot_ovly_wins = 0;
+    private_handle_t *handle_op, *h;
+
+    memset(mLastHandles, 0, sizeof(mLastHandles));
+    memset(mLastMPPMap, 0, sizeof(mLastMPPMap));
+
+    if (contents->outbuf) {
+        handle_op = private_handle_t::dynamicCast(contents->outbuf);
+    }
+
+    for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
+        mLastMPPMap[i].internal_mpp.type = -1;
+        mLastMPPMap[i].external_mpp.type = -1;
+    }
+
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+        size_t window_index = mLayerInfos[i]->mWindowIndex + 1;
+
+        if (layer.flags & HWC_SKIP_RENDERING) {
+            layer.releaseFenceFd = layer.acquireFenceFd;
+            continue;
+        }
+
+        if (layer.compositionType == HWC_OVERLAY) {
+            mLastHandles[window_index] = layer.handle;
+
+            if (mLayerInfos[i]->mExternalMPP != NULL) {
+                mLastMPPMap[window_index].external_mpp.type = mLayerInfos[i]->mExternalMPP->mType;
+                mLastMPPMap[window_index].external_mpp.index = mLayerInfos[i]->mExternalMPP->mIndex;
+
+                ret = postToMPP(layer, mFBTargetLayer, i, contents);
+                if (ret < 0) {
+                    DISPLAY_LOGE("postToMPP failed in extended/drm mode.");
+                }
+                mLayerInfos[i]->mExternalMPP->mCurrentBuf =
+                    (mLayerInfos[i]->mExternalMPP->mCurrentBuf + 1)%
+                    mLayerInfos[i]->mExternalMPP->mNumAvailableDstBuffers;
+            }
+        }
+    }
+
+    return ret;
+}
+
+int ExynosVirtualDisplayModule::postToMPP(hwc_layer_1_t &layer, hwc_layer_1_t *layerB,
+        int index, hwc_display_contents_1_t *contents)
+{
+    int dst_format = mExternalMPPDstFormat;
+    private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
+    ExynosMPPModule *exynosMPP = mLayerInfos[index]->mExternalMPP;
+    ExynosMPPModule *exynosInternalMPP = mLayerInfos[index]->mInternalMPP;
+    hwc_layer_1_t extMPPOutLayer;
+    hwc_frect_t sourceCrop = { 0, 0,  (float)WIDTH(layer.displayFrame),
+            (float)HEIGHT(layer.displayFrame) };
+    int originalTransform = layer.transform;
+    hwc_rect_t originalDisplayFrame = layer.displayFrame;
+    int err;
+
+    DISPLAY_LOGD("postToMPP is called with mFBTargetLayer(0x%x)", mFBTargetLayer);
+
+    if (exynosMPP == NULL) {
+        DISPLAY_LOGE("postToMPP is called but externMPP is NULL");
+        return -1;
+    }
+
+    exynosMPP->mDstBuffers[exynosMPP->mCurrentBuf] = contents->outbuf;
+    exynosMPP->mDstBufFence[exynosMPP->mCurrentBuf] = contents->outbufAcquireFenceFd;
+
+    if (layerB) {
+        if (is2StepBlendingRequired(layer, contents->outbuf)) {
+            private_handle_t *handleB = private_handle_t::dynamicCast(layerB->handle);
+            hwc_frect_t sourceCropB = { 0, 0,
+                    (float)WIDTH(layerB->displayFrame), (float)HEIGHT(layerB->displayFrame) };
+
+            DISPLAY_LOGD("Performing 2-Step blending operation");
+
+            calcDisplayRect(*layerB);
+
+            err = exynosMPP->processM2M(*layerB, dst_format, &sourceCropB, false);
+            if (err < 0) {
+                DISPLAY_LOGE("2 step - failed to configure MPP, %d", err);
+                return -1;
+            }
+
+            exynosMPP->mDstBufFence[exynosMPP->mCurrentBuf] =
+                            exynosMPP->mDstConfig.releaseFenceFd;
+            exynosMPP->mDstConfig.releaseFenceFd = -1;
+        }else {
+            DISPLAY_LOGD("Performing 1-Step blending operation");
+            int tempFence = sync_merge("scaler_blend", layerB->acquireFenceFd,
+                    layer.acquireFenceFd);
+
+            close(layerB->acquireFenceFd);
+            layerB->acquireFenceFd = -1;
+            close(layer.acquireFenceFd);
+            layer.acquireFenceFd = tempFence;
+        }
+
+        calcDisplayRect(layer);
+
+        err = exynosMPP->processM2MWithB(layer, *layerB, dst_format, &sourceCrop);
+        if (err < 0) {
+            DISPLAY_LOGE("failed to configure MPP for blending, %d", err);
+            return -1;
+        }
+    } else {
+        DISPLAY_LOGD("Performing Only-Scaling operation");
+
+        err = exynosMPP->processM2M(layer, dst_format, &sourceCrop, false);
+        if (err < 0) {
+            DISPLAY_LOGE("failed to configure MPP for scaling, %d", err);
+            return -1;
+        }
+    }
+
+    /* Restore displayFrame*/
+    layer.displayFrame = originalDisplayFrame;
+
+    return exynosMPP->mDstConfig.releaseFenceFd;
+}
+
+bool ExynosVirtualDisplayModule::is2StepBlendingRequired(hwc_layer_1_t &layer,
+        buffer_handle_t &outbuf)
+{
+    private_handle_t *outhandle = private_handle_t::dynamicCast(outbuf);
+
+    if (outhandle->width != WIDTH(layer.displayFrame) ||
+        outhandle->height != HEIGHT(layer.displayFrame))
+        return true;
+    return false;
+}
+
+bool ExynosVirtualDisplayModule::manageFences(hwc_display_contents_1_t *contents, int fence)
+{
+    for (size_t i = 0; i < contents->numHwLayers; i++) {
+        hwc_layer_1_t &layer = contents->hwLayers[i];
+
+        if (layer.acquireFenceFd >= 0) {
+            close(layer.acquireFenceFd);
+            layer.acquireFenceFd = -1;
+        }
+
+        if (layer.flags & HWC_SKIP_RENDERING) {
+            layer.releaseFenceFd = layer.acquireFenceFd;
+        }
+
+        if (!(layer.flags & HWC_SKIP_RENDERING) &&
+                (layer.releaseFenceFd <= -1) &&
+                ((layer.compositionType == HWC_OVERLAY) ||
+                (mFbNeeded == true && layer.compositionType == HWC_FRAMEBUFFER_TARGET))) {
+
+            if (fence >= 0) {
+                int dup_fd = dup(fence);
+                if (dup_fd < 0)
+                    DISPLAY_LOGE("release fence dup failed: %s", strerror(errno));
+
+                layer.releaseFenceFd = dup_fd;
+            } else {
+                layer.releaseFenceFd = -1;
+            }
+        }
+
+        if (layer.handle) {
+            private_handle_t *h = private_handle_t::dynamicCast(layer.handle);
+            DISPLAY_LOGD("CLEAN: layer %d type=%d, f=%x, w=%d, h=%d, s=%d, vs=%d, "
+                  "{%.1f, %.1f, %.1f, %.1f}, {%d, %d, %d, %d}"
+                  "fl=%08x, hdl=%p, trf=%02x, bl=%04x, Af=%d, Rf=%d, P=%d",
+                    i, layer.compositionType, h->format, h->width, h->height, h->stride,
+                    h->vstride, layer.sourceCropf.left, layer.sourceCropf.top,
+                    layer.sourceCropf.right, layer.sourceCropf.bottom,
+                    layer.displayFrame.left, layer.displayFrame.top,
+                    layer.displayFrame.right, layer.displayFrame.bottom,
+                    layer.flags, layer.handle, layer.transform, layer.blending,
+                    layer.acquireFenceFd, layer.releaseFenceFd, getDrmMode(layer.flags));
+        }
+    }
+
+    if (contents->outbufAcquireFenceFd >= 0) {
+        close(contents->outbufAcquireFenceFd);
+        contents->outbufAcquireFenceFd = -1;
+    }
+
+    contents->retireFenceFd = fence;
+    return true;
+}
+
+void ExynosVirtualDisplayModule::deInit()
+{
+}
+
+int ExynosVirtualDisplayModule::clearDisplay()
+{
+    return 0;
+}
+
+ExynosVirtualDisplayModule::~ExynosVirtualDisplayModule()
+{
+}
+
+int32_t ExynosVirtualDisplayModule::getDisplayAttributes(const uint32_t attribute)
+{
+    switch(attribute) {
+        case HWC_DISPLAY_COMPOSITION_TYPE:
+            return mCompositionType;
+        case HWC_DISPLAY_GLES_FORMAT:
+            return mGLESFormat;
+        case HWC_DISPLAY_SINK_BQ_FORMAT:
+            if (mIsRotationState)
+                return -1;
+            else
+                return mGLESFormat;
+        case HWC_DISPLAY_SINK_BQ_USAGE:
+            return mSinkUsage;
+        case HWC_DISPLAY_SINK_BQ_WIDTH:
+            if (mDisplayWidth == 0)
+                return mWidth;
+            return mDisplayWidth;
+        case HWC_DISPLAY_SINK_BQ_HEIGHT:
+            if (mDisplayHeight == 0)
+                return mHeight;
+            return mDisplayHeight;
+        default:
+            ALOGE("unknown display attribute %u", attribute);
+            return -EINVAL;
+    }
+    return 0;
+}
diff --git a/libvirtualdisplaymodule/ExynosVirtualDisplayModule.h b/libvirtualdisplaymodule/ExynosVirtualDisplayModule.h
new file mode 100644 (file)
index 0000000..5083bbe
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef EXYNOS_VIRTUAL_DISPLAY_MODULE_H
+#define EXYNOS_VIRTUAL_DISPLAY_MODULE_H
+
+#include "ExynosVirtualDisplay.h"
+
+class ExynosVirtualDisplayModule : public ExynosVirtualDisplay {
+       public:
+               ExynosVirtualDisplayModule(struct exynos5_hwc_composer_device_1_t *pdev);
+               ~ExynosVirtualDisplayModule();
+
+               int postFrame(hwc_display_contents_1_t *contents);
+               int postToMPP(hwc_layer_1_t & layer, hwc_layer_1_t *layerB,
+                                               int index, hwc_display_contents_1_t *contents);
+               void processGles(hwc_display_contents_1_t *contents);
+               void processHwc(hwc_display_contents_1_t *contents);
+               void processMixed(hwc_display_contents_1_t *contents);
+               bool is2StepBlendingRequired(hwc_layer_1_t & layer, buffer_handle_t & outbuf);
+               bool manageFences(hwc_display_contents_1_t *contents, int fence);
+
+               virtual int clearDisplay();
+               virtual int32_t getDisplayAttributes(const uint32_t attribute);
+               virtual int prepare(hwc_display_contents_1_t *contents);
+               virtual int set(hwc_display_contents_1_t *contents);
+               virtual void determineYuvOverlay(hwc_display_contents_1_t *contents);
+               virtual void determineSupportedOverlays(hwc_display_contents_1_t *contents);
+               virtual bool isOverlaySupported(hwc_layer_1_t & layer,
+                               size_t index, bool useVPPOverlay,
+                               ExynosMPPModule **supportedInternalMPP,
+                               ExynosMPPModule **supportedExternalMPP);
+               virtual void deInit();
+};
+
+#endif
diff --git a/libvirtualdisplaymodule/NOTICE b/libvirtualdisplaymodule/NOTICE
new file mode 100644 (file)
index 0000000..c1c71a2
--- /dev/null
@@ -0,0 +1,189 @@
+
+   Copyright (c) 2014, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/mobicore/Android.mk b/mobicore/Android.mk
new file mode 100644 (file)
index 0000000..bd576fc
--- /dev/null
@@ -0,0 +1,10 @@
+# Some things are specific to Android 6.0 and later (use stlport absence as indicator)
+ifneq ($(wildcard external/stlport/libstlport.mk),)
+# Up to Lollipop
+TRUSTONIC_ANDROID_LEGACY_SUPPORT = yes
+else
+# Since Marshmallow
+TRUSTONIC_ANDROID_LEGACY_SUPPORT =
+endif
+
+include $(call all-subdir-makefiles)
diff --git a/mobicore/ClientLib/Android.mk b/mobicore/ClientLib/Android.mk
new file mode 100644 (file)
index 0000000..ff7a501
--- /dev/null
@@ -0,0 +1,165 @@
+LOCAL_PATH := $(call my-dir)
+
+ifndef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+# Proxy server lib
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libMcProxy
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_CFLAGS := -fvisibility=hidden
+LOCAL_CFLAGS += -DTBASE_API_LEVEL=5
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -DLOG_ANDROID
+LOCAL_CFLAGS += -DGOOGLE_PROTOBUF_NO_RTTI
+
+LOCAL_C_INCLUDES := \
+       $(LOCAL_PATH)/include \
+       $(LOCAL_PATH)/include/GP \
+       external/protobuf/src
+
+ifeq ($(APP_PROJECT_PATH),)
+LOCAL_SHARED_LIBRARIES := \
+       liblog \
+       libprotobuf-cpp-lite
+else
+LOCAL_C_INCLUDES += \
+       ${COMP_PATH_AndroidProtoBuf}/Bin/host/include
+
+LOCAL_STATIC_LIBRARIES := \
+       libprotobuf-cpp-lite
+endif
+
+LOCAL_SRC_FILES := \
+       src/driver_client.cpp \
+       src/proxy_server.cpp \
+       src/mc.pb.cpp
+
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDES)
+
+include $(BUILD_STATIC_LIBRARY)
+
+endif # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+# Client lib
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libMcClient
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_CFLAGS := -fvisibility=hidden
+LOCAL_CFLAGS += -DTBASE_API_LEVEL=5
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -DLOG_ANDROID
+ifndef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_CFLAGS += -DGOOGLE_PROTOBUF_NO_RTTI
+else # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_CFLAGS += -DWITHOUT_PROXY
+endif # TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+LOCAL_C_INCLUDES := \
+       $(LOCAL_PATH)/include \
+       $(LOCAL_PATH)/include/GP
+
+ifeq ($(APP_PROJECT_PATH),)
+LOCAL_SHARED_LIBRARIES := \
+       liblog
+
+ifdef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+include external/stlport/libstlport.mk
+
+LOCAL_C_INCLUDES += \
+       external/stlport/stlport
+
+LOCAL_SHARED_LIBRARIES += \
+       libstlport
+else # TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_C_INCLUDES += \
+       external/protobuf/src
+
+LOCAL_SHARED_LIBRARIES += \
+       libprotobuf-cpp-lite
+endif # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+else # !NDK
+LOCAL_LDLIBS := -llog
+
+LOCAL_CFLAGS += -static-libstdc++
+
+LOCAL_C_INCLUDES += \
+       ${COMP_PATH_AndroidProtoBuf}/Bin/host/include
+
+LOCAL_STATIC_LIBRARIES := \
+       libprotobuf-cpp-lite
+endif # NDK
+
+LOCAL_SRC_FILES := \
+       src/common_client.cpp \
+       src/driver_client.cpp \
+       src/mc_client_api.cpp \
+       src/tee_client_api.cpp
+
+ifndef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_SRC_FILES += \
+       src/proxy_client.cpp \
+       src/mc.pb.cpp
+endif # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+LOCAL_EXPORT_CFLAGS := -DLOG_ANDROID
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDES)
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Static version of the client lib for recovery
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libMcClient_static
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_CFLAGS := -fvisibility=hidden
+LOCAL_CFLAGS += -DTBASE_API_LEVEL=5
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -DLOG_ANDROID
+LOCAL_CFLAGS += -DWITHOUT_PROXY
+
+LOCAL_C_INCLUDES := \
+       $(LOCAL_PATH)/include \
+       $(LOCAL_PATH)/include/GP
+
+ifdef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+include external/stlport/libstlport.mk
+
+LOCAL_C_INCLUDES += \
+       external/stlport/stlport
+
+LOCAL_SHARED_LIBRARIES += \
+       libstlport
+endif # TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+LOCAL_SRC_FILES := \
+       src/common_client.cpp \
+       src/driver_client.cpp \
+       src/mc_client_api.cpp \
+       src/tee_client_api.cpp
+
+LOCAL_EXPORT_CFLAGS := -DLOG_ANDROID
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/GP
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDES)
+
+include $(BUILD_STATIC_LIBRARY)
+
+# =============================================================================
+
+# adding the root folder to the search path appears to make absolute paths
+# work for import-module - lets see how long this works and what surprises
+# future developers get from this.
+$(call import-add-path,/)
+$(call import-module,$(COMP_PATH_AndroidProtoBuf))
diff --git a/mobicore/ClientLib/MODULE_LICENSE_BSD b/mobicore/ClientLib/MODULE_LICENSE_BSD
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mobicore/ClientLib/NOTICE b/mobicore/ClientLib/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/ClientLib/include/GP/tee_client_api.h b/mobicore/ClientLib/include/GP/tee_client_api.h
new file mode 100644 (file)
index 0000000..df3dcb5
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This header file corresponds to V1.0 of the GlobalPlatform
+ * TEE Client API Specification
+ */
+#ifndef   __TEE_CLIENT_API_H__
+#define   __TEE_CLIENT_API_H__
+
+#include "tee_client_types.h"
+#include "tee_client_error.h"
+
+#if TBASE_API_LEVEL >= 3
+#include "tee_client_api_imp.h"
+
+#if (!defined(TEEC_EXPORT)) && defined(__cplusplus)
+#define TEEC_EXPORT       extern "C"
+#else
+#define TEEC_EXPORT
+#endif // __cplusplus
+
+/* The header tee_client_api_imp.h must define implementation-dependent
+   types, constants and macros.
+
+   The implementation-dependent types are:
+     - TEEC_Context_IMP
+     - TEEC_Session_IMP
+     - TEEC_SharedMemory_IMP
+     - TEEC_Operation_IMP
+
+   The implementation-dependent constants are:
+     - TEEC_CONFIG_SHAREDMEM_MAX_SIZE
+   The implementation-dependent macros are:
+     - TEEC_PARAM_TYPES
+*/
+
+typedef struct {
+    uint32_t   a;
+    uint32_t   b;
+} TEEC_Value;
+
+/* Type definitions */
+typedef struct TEEC_Context {
+    TEEC_Context_IMP imp;
+} TEEC_Context;
+
+typedef struct TEEC_Session {
+    TEEC_Session_IMP imp;
+} TEEC_Session;
+
+typedef struct TEEC_SharedMemory {
+    void                    *buffer;
+    size_t                  size;
+    uint32_t                flags;
+    TEEC_SharedMemory_IMP   imp;
+} TEEC_SharedMemory;
+
+typedef struct {
+    void    *buffer;
+    size_t  size;
+} TEEC_TempMemoryReference;
+
+typedef struct {
+    TEEC_SharedMemory *parent;
+    size_t  size;
+    size_t  offset;
+} TEEC_RegisteredMemoryReference;
+
+
+
+typedef union {
+    TEEC_TempMemoryReference        tmpref;
+    TEEC_RegisteredMemoryReference  memref;
+    TEEC_Value                      value;
+} TEEC_Parameter;
+
+typedef struct TEEC_Operation {
+    volatile uint32_t    started;
+    uint32_t             paramTypes;
+    TEEC_Parameter       params[4];
+    TEEC_Operation_IMP   imp;
+} TEEC_Operation;
+
+
+#define TEEC_ORIGIN_API                     0x00000001
+#define TEEC_ORIGIN_COMMS                   0x00000002
+#define TEEC_ORIGIN_TEE                     0x00000003
+#define TEEC_ORIGIN_TRUSTED_APP             0x00000004
+
+#define TEEC_MEM_INPUT                      0x00000001
+#define TEEC_MEM_OUTPUT                     0x00000002
+
+#define TEEC_NONE                           0x0
+#define TEEC_VALUE_INPUT                    0x1
+#define TEEC_VALUE_OUTPUT                   0x2
+#define TEEC_VALUE_INOUT                    0x3
+#define TEEC_MEMREF_TEMP_INPUT              0x5
+#define TEEC_MEMREF_TEMP_OUTPUT             0x6
+#define TEEC_MEMREF_TEMP_INOUT              0x7
+#define TEEC_MEMREF_WHOLE                   0xC
+#define TEEC_MEMREF_PARTIAL_INPUT           0xD
+#define TEEC_MEMREF_PARTIAL_OUTPUT          0xE
+#define TEEC_MEMREF_PARTIAL_INOUT           0xF
+
+#define TEEC_LOGIN_PUBLIC                   0x00000000
+#define TEEC_LOGIN_USER                     0x00000001
+#define TEEC_LOGIN_GROUP                    0x00000002
+#define TEEC_LOGIN_APPLICATION              0x00000004
+#define TEEC_LOGIN_USER_APPLICATION         0x00000005
+#define TEEC_LOGIN_GROUP_APPLICATION        0x00000006
+
+#define TEEC_TIMEOUT_INFINITE               0xFFFFFFFF
+
+#pragma GCC visibility push(default)
+
+TEEC_EXPORT TEEC_Result TEEC_InitializeContext(
+    const char   *name,
+    TEEC_Context *context);
+
+TEEC_EXPORT void  TEEC_FinalizeContext(
+    TEEC_Context *context);
+
+TEEC_EXPORT TEEC_Result  TEEC_RegisterSharedMemory(
+    TEEC_Context      *context,
+    TEEC_SharedMemory *sharedMem);
+
+TEEC_EXPORT TEEC_Result  TEEC_AllocateSharedMemory(
+    TEEC_Context      *context,
+    TEEC_SharedMemory *sharedMem);
+
+TEEC_EXPORT void  TEEC_ReleaseSharedMemory (
+    TEEC_SharedMemory *sharedMem);
+
+TEEC_EXPORT TEEC_Result  TEEC_OpenSession (
+    TEEC_Context    *context,
+    TEEC_Session    *session,
+    const TEEC_UUID *destination,
+    uint32_t        connectionMethod,
+    const void      *connectionData,
+    TEEC_Operation  *operation,
+    uint32_t        *returnOrigin);
+
+TEEC_EXPORT void  TEEC_CloseSession (
+    TEEC_Session *session);
+
+TEEC_EXPORT TEEC_Result TEEC_InvokeCommand(
+    TEEC_Session     *session,
+    uint32_t         commandID,
+    TEEC_Operation   *operation,
+    uint32_t         *returnOrigin);
+
+TEEC_EXPORT void  TEEC_RequestCancellation(
+    TEEC_Operation *operation);
+
+#pragma GCC visibility pop
+
+#endif /* TBASE_API_LEVEL */
+
+#endif /* __TEE_CLIENT_API_H__ */
diff --git a/mobicore/ClientLib/include/GP/tee_client_api_imp.h b/mobicore/ClientLib/include/GP/tee_client_api_imp.h
new file mode 100644 (file)
index 0000000..163d810
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This header file defines the implementation-dependent types,
+ * constants and macros for all the Trusted Foundations implementations
+ * of the TEE Client API
+ */
+#ifndef   __TEE_CLIENT_API_IMP_H__
+#define   __TEE_CLIENT_API_IMP_H__
+
+#if TBASE_API_LEVEL >= 3
+
+#include <pthread.h>
+
+#define TEEC_MEM_INOUT (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT)
+
+typedef struct {
+    uint32_t                    reserved;
+} TEEC_Context_IMP;
+
+typedef struct {
+    uint32_t                    sessionId;
+    TEEC_Context_IMP            context;
+    void                        *tci;
+    bool                        active;
+    pthread_mutex_t             mutex_tci;  //mutex to serialize CA requests
+} TEEC_Session_IMP;
+
+typedef struct {
+    bool                        implementation_allocated;
+} TEEC_SharedMemory_IMP;
+
+typedef struct {
+    TEEC_Session_IMP            *session;
+} TEEC_Operation_IMP;
+
+/* There is no natural, compile-time limit on the shared memory, but a specific
+   implementation may introduce a limit (in particular on TrustZone) */
+#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE ((size_t)0xFFFFFFFF)
+
+#define TEEC_PARAM_TYPES(entry0Type, entry1Type, entry2Type, entry3Type) \
+   ((entry0Type) | ((entry1Type) << 4) | ((entry2Type) << 8) | ((entry3Type) << 12))
+
+#endif /* TBASE_API_LEVEL >= 3 */
+
+#endif /* __TEE_CLIENT_API_IMP_H__ */
diff --git a/mobicore/ClientLib/include/GP/tee_client_error.h b/mobicore/ClientLib/include/GP/tee_client_error.h
new file mode 100644 (file)
index 0000000..8aa4fbf
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEE_CLIENT_ERROR_H__
+#define __TEE_CLIENT_ERROR_H__
+
+#define TEEC_SUCCESS                      ((TEEC_Result)0x00000000)
+
+/**
+ * Generic error code : Generic error
+ **/
+#define TEEC_ERROR_GENERIC                ((TEEC_Result)0xFFFF0000)
+
+/**
+ * Generic error code : The underlying security system denies the access to the
+ * object
+ **/
+#define TEEC_ERROR_ACCESS_DENIED          ((TEEC_Result)0xFFFF0001)
+
+/**
+ * Generic error code : The pending operation is cancelled.
+ **/
+#define TEEC_ERROR_CANCEL                 ((TEEC_Result)0xFFFF0002)
+
+/**
+ * Generic error code : The underlying system detects a conflict
+ **/
+#define TEEC_ERROR_ACCESS_CONFLICT        ((TEEC_Result)0xFFFF0003)
+
+/**
+ * Generic error code : Too much data for the operation or some data remain
+ * unprocessed by the operation.
+ **/
+#define TEEC_ERROR_EXCESS_DATA            ((TEEC_Result)0xFFFF0004)
+
+/**
+ * Generic error code : Error of data format
+ **/
+#define TEEC_ERROR_BAD_FORMAT             ((TEEC_Result)0xFFFF0005)
+
+/**
+ * Generic error code : The specified parameters are invalid
+ **/
+#define TEEC_ERROR_BAD_PARAMETERS         ((TEEC_Result)0xFFFF0006)
+
+/**
+ * Generic error code : Illegal state for the operation.
+ **/
+#define TEEC_ERROR_BAD_STATE              ((TEEC_Result)0xFFFF0007)
+
+/**
+ * Generic error code : The item is not found
+ **/
+#define TEEC_ERROR_ITEM_NOT_FOUND         ((TEEC_Result)0xFFFF0008)
+
+/**
+ * Generic error code : The specified operation is not implemented
+ **/
+#define TEEC_ERROR_NOT_IMPLEMENTED        ((TEEC_Result)0xFFFF0009)
+
+/**
+ * Generic error code : The specified operation is not supported
+ **/
+#define TEEC_ERROR_NOT_SUPPORTED          ((TEEC_Result)0xFFFF000A)
+
+/**
+ * Generic error code : Insufficient data is available for the operation.
+ **/
+#define TEEC_ERROR_NO_DATA                ((TEEC_Result)0xFFFF000B)
+
+/**
+ * Generic error code : Not enough memory to perform the operation
+ **/
+#define TEEC_ERROR_OUT_OF_MEMORY          ((TEEC_Result)0xFFFF000C)
+
+/**
+ * Generic error code : The service is currently unable to handle the request;
+ * try later
+ **/
+#define TEEC_ERROR_BUSY                   ((TEEC_Result)0xFFFF000D)
+
+/**
+ * Generic communication error
+ **/
+#define TEEC_ERROR_COMMUNICATION          ((TEEC_Result)0xFFFF000E)
+
+/**
+ * Generic error code : security violation
+ **/
+#define TEEC_ERROR_SECURITY               ((TEEC_Result)0xFFFF000F)
+
+/**
+ * Generic error code : the buffer is too short
+ **/
+#define TEEC_ERROR_SHORT_BUFFER           ((TEEC_Result)0xFFFF0010)
+
+/**
+ * Error of communication: The target of the connection is dead
+ **/
+#define TEEC_ERROR_TARGET_DEAD            ((TEEC_Result)0xFFFF3024)
+
+/**
+ * File system error code: not enough space to complete the operation.
+ **/
+#define TEEC_ERROR_STORAGE_NO_SPACE       ((TEEC_Result)0xFFFF3041)
+
+/*------------------------------------------------------------------------------
+   Implementation-specific errors 
+------------------------------------------------------------------------------*/
+#define TEEC_TBASE_ERROR_STORAGE_ITEM_EXISTS        ((TEEC_Result)0x80000000)
+#define TEEC_TBASE_ERROR_STORAGE_CORRUPTED          ((TEEC_Result)0x80000001)
+#define TEEC_TBASE_ERROR_STORAGE_UNREACHABLE        ((TEEC_Result)0x80000002)
+#define TEEC_TBASE_ERROR_NO_MORE_HANDLES            ((TEEC_Result)0x80000003)
+#define TEEC_TBASE_ERROR_ITEM_EXISTS                ((TEEC_Result)0x80000004)
+
+#endif /* __TEE_CLIENT_ERROR_H__ */
+
diff --git a/mobicore/ClientLib/include/GP/tee_client_types.h b/mobicore/ClientLib/include/GP/tee_client_types.h
new file mode 100644 (file)
index 0000000..6642592
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TEE_CLIENT_TYPES_H__
+#define __TEE_CLIENT_TYPES_H__
+
+#include <limits.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#ifndef NULL
+#  ifdef __cplusplus
+#     define NULL  0
+#  else
+#     define NULL  ((void *)0)
+#  endif
+#endif
+
+#define IN
+#define OUT
+
+typedef uint32_t TEEC_Result;
+
+/** Definition of an UUID (from RFC 4122 http://www.ietf.org/rfc/rfc4122.txt) */
+typedef struct TEE_UUID {
+    uint32_t timeLow;
+    uint16_t timeMid;
+    uint16_t timeHiAndVersion;
+    uint8_t clockSeqAndNode[8];
+} TEE_UUID;
+typedef TEE_UUID TEEC_UUID;
+
+/** Type definition for a TEE Identity */
+typedef struct TEE_Identity {
+    uint32_t login;
+    TEE_UUID uuid;
+} TEE_Identity;
+
+#endif /* __TEE_CLIENT_TYPES_H__ */
diff --git a/mobicore/ClientLib/include/GpTci.h b/mobicore/ClientLib/include/GpTci.h
new file mode 100644 (file)
index 0000000..55639d4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _GP_TCI_H_
+#define _GP_TCI_H_
+
+typedef struct {
+    uint32_t   a;
+    uint32_t   b;
+} TEE_Value;
+
+typedef struct {
+    uint32_t    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 */
+    uint32_t    outputSize;
+} _TEEC_MemoryReferenceInternal;
+
+typedef union {
+    TEE_Value                      value;
+    _TEEC_MemoryReferenceInternal   memref;
+} _TEEC_ParameterInternal;
+
+typedef enum {
+    _TA_OPERATION_OPEN_SESSION =    1,
+    _TA_OPERATION_INVOKE_COMMAND =  2,
+    _TA_OPERATION_CLOSE_SESSION =   3,
+} _TEEC_TCI_type;
+
+typedef struct {
+    _TEEC_TCI_type          type;
+    uint32_t                commandId;
+    uint32_t                paramTypes;
+    _TEEC_ParameterInternal params[4];
+    bool                    isCancelled;
+} _TEEC_OperationInternal;
+
+typedef struct {
+    char header[8];// = "TCIGP000"`: version indicator (to support future format changes)
+    TEEC_UUID destination;
+    _TEEC_OperationInternal operation; //the data of the ongoing operation (if any)
+    uint32_t ready;
+    // The following fields are set by the secure world (in a future version, they may also be set by the normal world communication layer):
+    uint32_t returnOrigin;
+    uint32_t returnStatus;
+} _TEEC_TCI;
+
+/**
+ * Termination codes
+ */
+#define TA_EXIT_CODE_PANIC  (300)
+#define TA_EXIT_CODE_TCI    (301)
+#define TA_EXIT_CODE_PARAMS (302)
+#define TA_EXIT_CODE_FINISHED       (303)
+#define TA_EXIT_CODE_SESSIONSTATE   (304)
+#define TA_EXIT_CODE_CREATEFAILED   (305)
+
+#endif // _GP_TCI_H_
diff --git a/mobicore/ClientLib/include/Mci/mcimcp.h b/mobicore/ClientLib/include/Mci/mcimcp.h
new file mode 100644 (file)
index 0000000..34f0deb
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MCP_H_
+#define MCP_H_
+
+
+#include "mcUuid.h"
+#include "mcLoadFormat.h"
+#include "mcVersionInfo.h"
+#include "stdbool.h"
+
+#define FLAG_RESPONSE       (1U << 31)  /**< Flag to indicate that this is the response to a MCP command. */
+
+#define MCP_MAP_MAX_BUF        4 /** Maximum number of buffers that can be mapped at once */
+
+/** 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. */
+    MC_MCP_RET_ERR_CLOSE_TASK_FAILED                = 28, /**< Closing of task not yet possible, try again later. */
+    MC_MCP_RET_ERR_SERVICE_BLOCKED                  = 29, /**< Service is blocked and a session cannot be opened to it. */
+    MC_MCP_RET_ERR_SERVICE_LOCKED                   = 30, /**< Service is locked and a session cannot be opened to it. */
+    MC_MCP_RET_ERR_SERVICE_KILLED                   = 31, /**< Service was forcefully killed (due to an administrative command). */
+
+    // 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. */
+    // obsolete: MC_MCP_CMD_DONATE_RAM   = 0x00000008,
+    MC_MCP_CMD_GET_MOBICORE_VERSION      = 0x00000009,   /**< Get MobiCore version information. */
+    MC_MCP_CMD_CLOSE_MCP                 = 0x0000000A,   /**< Close MCP and unmap MCI. */
+    MC_MCP_CMD_LOAD_TOKEN                = 0x0000000B,   /**< Load token for device attestation */
+    MC_MCP_CMD_CHECK_LOAD_TA             = 0x0000000C,   /**< Check that TA can be loaded */
+    MC_MCP_CMD_MULTIMAP                  = 0x0000000D,
+    MC_MCP_CMD_MULTIUNMAP                = 0x0000000E,
+} mcpCmdId_t;
+
+
+/** Types of WSM known to the MobiCore.
+ */
+typedef uint32_t wsmType_t;
+
+#define WSM_TYPE_MASK       0xFF
+#define WSM_INVALID         0       /**< Invalid memory type */
+#define WSM_CONTIGUOUS      1       /**< Reference to WSM points to a contiguous region of pages. */
+#define WSM_L2              2       /**< Reference to WSM points to an L2 table describing the memory region to share */
+#define WSM_L1              3       /**< Reference to WSM points to an L1 table describing the memory region to share */
+#define WSM_WSM_UNCACHED    0x100   /**< Bitflag indicating that WSM should be uncached */
+#define WSM_L2_UNCACHED     0x100   /**< Bitflag indicating that L2 table should be uncached */
+
+/** Magic number used to identify if Open Command supports GP client authentication. */
+#define MC_GP_CLIENT_AUTH_MAGIC    0x47504131  /* "GPA1" */
+
+/** Initialisation values flags. */
+#define MC_IV_FLAG_IRQ             (1 << 0)    /* Set if IRQ is present */
+#define MC_IV_FLAG_TIME            (1 << 1)    /* Set if GP TIME API is supported */
+
+typedef struct {
+    uint32_t flags;  /**< Flags to know what data to expect. */
+    uint32_t irq;    /**< IRQ number to use. */
+    uint32_t timeOffset;/**< Offset from MCI base address of mcTime struct. */
+    uint32_t timeLen;/**< Length of mcTime struct. */
+} initValues_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 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.
+ * @{ */
+
+/** GP client authentication data */
+typedef struct {
+    uint32_t          mclfMagic;        /**< ASCII "GPA1" if GP client authentication is supported,
+                                                   "MCLF" otherwise. */
+    mcIdentity_t      mcIdentity;       /**< GP identity information: login method and data */
+} cmdOpenData_t;
+
+/** Open Command */
+typedef struct {
+    commandHeader_t   cmdHeader;        /**< Command header. */
+    mcUuid_t          uuid;             /**< Byte array containing the service UUID. */
+    uint8_t           pad1[4];          /**< Padding to be 64-bit aligned */
+    uint64_t          adrTciBuffer;     /**< Physical address of the TCI */
+    uint64_t          adrLoadData;      /**< Physical address of the data to load. */
+    uint32_t          ofsTciBuffer;     /**< Offset to the data. */
+    uint32_t          lenTciBuffer;     /**< Length of the TCI. */
+    wsmType_t         wsmTypeTci;       /**< Type of WSM used for the TCI */
+    wsmType_t         wsmTypeLoadData;  /**< Type of the memory containing the data to load. */
+    uint32_t          ofsLoadData;      /**< Offset to the data. */
+    uint32_t          lenLoadData;      /**< Length of the data to load. */
+    union {
+        cmdOpenData_t cmdOpenData;      /**< Magic number and login info for GP client authentication. */
+        mclfHeader_t  tlHeader;         /**< Service header */
+    };
+    uint32_t          is_gpta;          /**< true if looking for an SD/GP-TA */
+} 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;
+
+/** TA Load Check Command */
+typedef struct {
+    commandHeader_t   cmdHeader;        /**< Command header. */
+    mcUuid_t          uuid;             /**< Byte array containing the service UUID. */
+    uint8_t           pad1[4];          /**< Padding to be 64-bit aligned */
+    uint64_t          adrLoadData;      /**< Physical address of the data to load. */
+    wsmType_t         wsmTypeLoadData;  /**< Type of the memory containing 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. */
+} mcpCmdCheckLoad_t, *mcpCmdCheckLoad_ptr;
+
+/** TA Load Check Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+} mcpRspCheckLoad_t, *mcpRspCheckLoad_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 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         ofsBuffer;     /**< Offset to the payload. */
+    uint64_t         adrBuffer;     /**< Physical address of the memory */
+    uint32_t         lenBuffer;     /**< Length of the buffer. */
+    uint8_t          pad1[4];       /**< Padding to be 64-bit aligned */
+} 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
+
+/** @defgroup MCPMULTIMAP MULTIMAP
+ * Map up to MCP_MAP_MAX_BUF portions of memory to a session.
+ * The MULTIMAP command provides MCP_MAP_MAX_BUF blocks of memory to the context of a service.
+ * The memory then becomes world-shared memory (WSM).
+ * The only allowed memory type here is WSM_L2.
+ * @{ */
+
+/** NWd physical buffer description
+ *
+ * Note: Information is coming from NWd kernel. So it should not be trusted more than NWd kernel is trusted.
+ */
+typedef struct {
+    uint64_t         adrBuffer;     /**< Physical address, for buffer or for L2 table (1K) */
+    uint32_t         ofsBuffer;     /**< Offset of buffer */
+    uint32_t         lenBuffer;     /**< Length of buffer */
+    wsmType_t        wsmType;       /**< Type of address */
+    uint8_t          pad1[4];       /**< Padding to be 64-bit aligned */
+} mcpBufferMap_t;
+
+/** Multimap Command */
+typedef struct {
+    commandHeader_t  cmdHeader; /**< Command header. */
+    uint32_t         sessionId; /** Session ID */
+    mcpBufferMap_t   buffers[MCP_MAP_MAX_BUF];
+} mcpCmdMultimap_t, *mcpCmdMultimap_ptr;
+
+/** Multimap Command Response */
+typedef struct {
+    responseHeader_t  rspHeader;        /**< Response header. */
+    uint64_t          secureVirtAdr[MCP_MAP_MAX_BUF]; /**< Virtual address in the context of the service the WSM is mapped to, already includes a possible offset! */
+} mcpRspMultimap_t, *mcpRspMultimap_ptr;
+
+/** @} *///End MCPMULTIMAP
+
+/** @defgroup MCPMULTIUNMAP MULTIUNMAP
+ * Unmap up to MCP_MAP_MAX_BUF portions of world-shared memory from a session.
+ * The MULTIUNMAP command is used to unmap MCP_MAP_MAX_BUF previously mapped blocks of
+ * world shared memory from the context of a session.
+ *
+ * Attention: The memory blocks will be immediately unmapped from the specified session.
+ * If the service is still accessing the memory, the service will trigger a segmentation fault.
+ * @{ */
+
+/** NWd mapped buffer description
+ *
+ * Note: Information is coming from NWd kernel. So it should not be trusted more than NWd kernel is trusted.
+ */
+typedef struct {
+    uint64_t         secureVirtAdr; /**< Physical address, for buffer or for L2 table (1K) */
+    uint32_t         lenBuffer;     /**< Length of buffer - unused */
+    uint8_t          pad1[4];       /**< Padding to be 64-bit aligned */
+} mcpBufferUnmap_t;
+
+/** Multiunmap Command */
+typedef struct {
+    commandHeader_t  cmdHeader; /**< Command header. */
+    uint32_t         sessionId; /** Session ID */
+    mcpBufferUnmap_t buffers[MCP_MAP_MAX_BUF]; /* For len and sva */
+} mcpCmdMultiunmap_t, *mcpCmdMultiunmap_ptr;
+
+/** Multiunmap Command Response */
+typedef struct {
+    responseHeader_t rspHeader; /**< Response header. */
+} mcpRspMultiunmap_t, *mcpRspMultiunmap_ptr;
+
+/** @} */// End MCPMULTIUNMAP
+
+/** @} */// End SESSCMD
+
+/** @defgroup MCPLOADTOKEN
+ * Load a token from the normal world and share it with <t-base
+ * If something fails, the device attestation functionality will be disabled
+ * @{ */
+
+/** Load Token */
+typedef struct {
+    commandHeader_t   cmdHeader;        /**< Command header. */
+    wsmType_t         wsmTypeLoadData;  /**< Type of the memory containing the data to load. */
+    uint64_t          adrLoadData;      /**< Physical address of the data to load. */
+    uint64_t          ofsLoadData;      /**< Offset to the data to load. */
+    uint64_t          lenLoadData;      /**< Length of the data to load. */
+} mcpCmdLoadToken_t, *mcpCmdLoadToken_ptr;
+
+/** Load Token Command Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+} mcpRspLoadToken_t, *mcpRspLoadToken_ptr;
+
+/** @} *///End MCPLOADTOKEN
+
+/** @} */// End CMD
+
+/** Structure of the MCP buffer. */
+typedef union {
+    initValues_t                 initValues;             /**< initialization values. */
+    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. */
+    mcpCmdGetMobiCoreVersion_t   cmdGetMobiCoreVersion;  /**< Get MobiCore Version command. */
+    mcpRspGetMobiCoreVersion_t   rspGetMobiCoreVersion;  /**< Response to GET_MOBICORE_VERSION command. */
+    mcpCmdLoadToken_t            cmdLoadToken;
+    mcpRspLoadToken_t            rspLoadToken;
+    mcpCmdCheckLoad_t            cmdCheckLoad;           /**< TA load check command. */
+    mcpRspCheckLoad_t            rspCheckLoad;           /**< Response to TA load check. */
+    mcpCmdMultimap_t             cmdMultimap;            /**< Map a list of WSM to service context. */
+    mcpRspMultimap_t             rspMultimap;            /**< Response to MULTIMAP command. */
+    mcpCmdMultiunmap_t           cmdMultiunmap;            /**< Map a list of WSM to service context. */
+    mcpRspMultiunmap_t           rspMultiunmap;            /**< Response to MULTIMAP 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      timeout;    /**< Secure-world timeout: when t-base goes to sleep, its next deadline is written here */
+    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/ClientLib/include/Mci/mcinq.h b/mobicore/ClientLib/include/Mci/mcinq.h
new file mode 100644 (file)
index 0000000..59659d8
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef 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
+ * Note that there is one queue for NWd->SWd and one queue for SWd->NWd
+ * @{ */
+#define NQ_SIZE(n)   (2*(sizeof(notificationQueueHeader_t) + (n)*sizeof(notification_t)))
+#define MIN_NQ_LEN NQ_SIZE(MIN_NQ_ELEM)   /**< Minimum size for the notification queue data structure */
+#define MAX_NQ_LEN NQ_SIZE(MAX_NQ_ELEM)   /**< Maximum size for the notification queue data structure */
+/** @} */
+
+/** \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 */
+    ERR_SESSION_KILLED      = -6, /**< session was force-killed (due to an administrative command). */
+} 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/ClientLib/include/MobiCoreDriverApi.h b/mobicore/ClientLib/include/MobiCoreDriverApi.h
new file mode 100644 (file)
index 0000000..8439f24
--- /dev/null
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCDRIVER_H_
+#define MCDRIVER_H_
+
+#if (!defined(__MC_CLIENT_LIB_API)) && defined(__cplusplus)
+#define __MC_CLIENT_LIB_API       extern "C"
+#else
+#define __MC_CLIENT_LIB_API
+#endif // __cplusplus
+
+
+#include <stdint.h>
+#ifndef WIN32
+#include <stdbool.h>
+#endif
+
+#include "mcUuid.h"
+#include "mcSpid.h"
+#include "mcVersionInfo.h"
+
+/*
+ *  MobiCore driver API error codes.
+ *  MAJOR part of error code is stable.
+ *  MCP part contains MCP result code. See MCI/mcimcp.h
+ *  DETAIL part may be used in testing for specific error code.
+ *
+ *  Detail error codes may change in different releases
+ *  Please do not test DETAIL part when comparing error codes.
+ */
+#define MC_DRV_ERROR_MAJOR(ecode)    ((ecode)       & 0xFF)     /**< Get MAJOR part of error code. */
+#define MC_DRV_ERROR_MCP(ecode)     (((ecode)>>8)   & 0xFF)     /**< Get MCP part of error code. */
+#define MC_DRV_ERROR_DETAIL(ecode)  (((ecode)>>16)  & 0x0FFF)   /**< Get detail part of error code. */
+
+typedef uint32_t mcResult_t;
+/**
+ * Return values of MobiCore driver functions.
+ */
+#define MC_DRV_OK                                   0x00000000 /**< Function call succeeded. */
+#define MC_DRV_NO_NOTIFICATION                      0x00000001 /**< No notification available. */
+#define MC_DRV_ERR_NOTIFICATION                     0x00000002 /**< Error during notification on communication level. */
+#define MC_DRV_ERR_NOT_IMPLEMENTED                  0x00000003 /**< Function not implemented. */
+#define MC_DRV_ERR_OUT_OF_RESOURCES                 0x00000004 /**< No more resources available. */
+#define MC_DRV_ERR_INIT                             0x00000005 /**< Driver initialization failed. */
+#define MC_DRV_ERR_UNKNOWN                          0x00000006 /**< Unknown error. */
+#define MC_DRV_ERR_UNKNOWN_DEVICE                   0x00000007 /**< The specified device is unknown. */
+#define MC_DRV_ERR_UNKNOWN_SESSION                  0x00000008 /**< The specified session is unknown. */
+#define MC_DRV_ERR_INVALID_OPERATION                0x00000009 /**< The specified operation is not allowed. */
+#define MC_DRV_ERR_INVALID_RESPONSE                 0x0000000a /**< The response header from the MC is invalid. */
+#define MC_DRV_ERR_TIMEOUT                          0x0000000b /**< Function call timed out. */
+#define MC_DRV_ERR_NO_FREE_MEMORY                   0x0000000c /**< Can not allocate additional memory. */
+#define MC_DRV_ERR_FREE_MEMORY_FAILED               0x0000000d /**< Free memory failed. */
+#define MC_DRV_ERR_SESSION_PENDING                  0x0000000e /**< Still some open sessions pending. */
+#define MC_DRV_ERR_DAEMON_UNREACHABLE               0x0000000f /**< MC daemon not reachable */
+#define MC_DRV_ERR_INVALID_DEVICE_FILE              0x00000010 /**< The device file of the kernel module could not be opened. */
+#define MC_DRV_ERR_INVALID_PARAMETER                0x00000011 /**< Invalid parameter. */
+#define MC_DRV_ERR_KERNEL_MODULE                    0x00000012 /**< Error from Kernel Module, see DETAIL for errno. */
+#define MC_DRV_ERR_BULK_MAPPING                     0x00000013 /**< Error during mapping of additional bulk memory to session. */
+#define MC_DRV_ERR_BULK_UNMAPPING                   0x00000014 /**< Error during unmapping of additional bulk memory to session. */
+#define MC_DRV_INFO_NOTIFICATION                    0x00000015 /**< Notification received, exit code available. */
+#define MC_DRV_ERR_NQ_FAILED                        0x00000016 /**< Set up of NWd connection failed. */
+
+#define MC_DRV_ERR_DAEMON_VERSION                   0x00000017 /**< Wrong daemon version. */
+#define MC_DRV_ERR_CONTAINER_VERSION                0x00000018 /**< Wrong container version. */
+
+// those should become MCP or even detail codes on top of MC_DRV_ERR_MCP_ERROR
+#define MC_DRV_ERR_WRONG_PUBLIC_KEY                 0x00000019 /**< System Trustlet public key is wrong. */
+#define MC_DRV_ERR_CONTAINER_TYPE_MISMATCH          0x0000001a /**< Wrong container type(s). */
+#define MC_DRV_ERR_CONTAINER_LOCKED                 0x0000001b /**< Container is locked (or not activated). */
+#define MC_DRV_ERR_SP_NO_CHILD                      0x0000001c /**< SPID is not registered with root container. */
+#define MC_DRV_ERR_TL_NO_CHILD                      0x0000001d /**< UUID is not registered with sp container. */
+#define MC_DRV_ERR_UNWRAP_ROOT_FAILED               0x0000001e /**< Unwrapping of root container failed. */
+#define MC_DRV_ERR_UNWRAP_SP_FAILED                 0x0000001f /**< Unwrapping of service provider container failed. */
+#define MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED           0x00000020 /**< Unwrapping of Trustlet container failed. */
+
+// use separate numbers for those in the future
+#define MC_DRV_ERR_DEVICE_ALREADY_OPEN              MC_DRV_ERR_INVALID_OPERATION /** < Device is already open. */
+#define MC_DRV_ERR_SOCKET_CONNECT                   MC_DRV_ERR_DAEMON_UNREACHABLE /**< MC daemon socket not reachable. */
+#define MC_DRV_ERR_SOCKET_WRITE                     MC_DRV_ERR_DAEMON_UNREACHABLE /**< MC daemon socket write error. */
+#define MC_DRV_ERR_SOCKET_READ                      MC_DRV_ERR_DAEMON_UNREACHABLE /**< MC daemon socket read error. */
+#define MC_DRV_ERR_SOCKET_LENGTH                    MC_DRV_ERR_DAEMON_UNREACHABLE /**< MC daemon socket read error. */
+#define MC_DRV_ERR_DAEMON_SOCKET                    MC_DRV_ERR_DAEMON_UNREACHABLE /**< MC daemon had problems with socket. */
+#define MC_DRV_ERR_DEVICE_FILE_OPEN                 MC_DRV_ERR_INVALID_DEVICE_FILE /**< The device file of the kernel module could not be opened. */
+#define MC_DRV_ERR_NULL_POINTER                     MC_DRV_ERR_INVALID_PARAMETER /**< Null pointer passed as parameter. */
+#define MC_DRV_ERR_TCI_TOO_BIG                      MC_DRV_ERR_INVALID_PARAMETER /**< Requested TCI length is too high. */
+#define MC_DRV_ERR_WSM_NOT_FOUND                    MC_DRV_ERR_INVALID_PARAMETER /**< Requested TCI was not allocated with mallocWsm(). */
+#define MC_DRV_ERR_TCI_GREATER_THAN_WSM             MC_DRV_ERR_INVALID_PARAMETER /**< Requested TCI length is bigger than allocated WSM. */
+#define MC_DRV_ERR_TRUSTLET_NOT_FOUND               MC_DRV_ERR_INVALID_DEVICE_FILE /** < Trustlet could not be found. */
+#define MC_DRV_ERR_TRUSTED_APPLICATION_NOT_FOUND    MC_DRV_ERR_TRUSTLET_NOT_FOUND /** < Trusted Application could not be found. */
+#define MC_DRV_ERR_DAEMON_KMOD_ERROR                MC_DRV_ERR_DAEMON_UNREACHABLE /**< Daemon cannot use Kernel module as expected. */
+#define MC_DRV_ERR_DAEMON_MCI_ERROR                 MC_DRV_ERR_DAEMON_UNREACHABLE /**< Daemon cannot use MCI as expected. */
+#define MC_DRV_ERR_MCP_ERROR                        MC_DRV_ERR_DAEMON_UNREACHABLE /**< MobiCore Control Protocol error. See MC_DRV_ERROR_MCP(). */
+#define MC_DRV_ERR_INVALID_LENGTH                   MC_DRV_ERR_NO_FREE_MEMORY /**< Invalid length. */
+#define MC_DRV_ERR_KMOD_NOT_OPEN                    MC_DRV_ERR_NO_FREE_MEMORY /**< Device not open. */
+#define MC_DRV_ERR_BUFFER_ALREADY_MAPPED            MC_DRV_ERR_BULK_MAPPING /**< Buffer is already mapped to this Trusted Application. */
+#define MC_DRV_ERR_BLK_BUFF_NOT_FOUND               MC_DRV_ERR_BULK_UNMAPPING /**< Unable to find internal handle for buffer. */
+
+#define MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN           0x00000021 /**< No device associated with connection. */
+#define MC_DRV_ERR_DAEMON_WSM_HANDLE_NOT_FOUND      MC_DRV_ERR_WSM_NOT_FOUND /**< Daemon could not find WSM handle. */
+#define MC_DRV_ERR_DAEMON_UNKNOWN_SESSION           MC_DRV_ERR_UNKNOWN_SESSION /**< The specified session is unknown to Daemon. */
+
+#if TBASE_API_LEVEL >= 3
+// Installation errors
+#define MC_DRV_ERR_TA_ATTESTATION_ERROR             0x00000022 /**< TA blob attestation is incorrect. */
+#endif /* TBASE_API_LEVEL */
+
+#define MC_DRV_ERR_INTERRUPTED_BY_SIGNAL            0x00000023 /**< Interrupted system call. */
+
+#if TBASE_API_LEVEL >= 5
+/**
+ * Do we call these RESERVED_1, _2 etc? (as this file is public, or do we wash it?)
+ */
+#define MC_DRV_ERR_SERVICE_BLOCKED                  0x00000024 /**< Service is blocked and opensession is thus not allowed. */
+#define MC_DRV_ERR_SERVICE_LOCKED                   0x00000025 /**< Service is locked and opensession is thus not allowed. */
+#define MC_DRV_ERR_SERVICE_KILLED                   0x00000026 /**< Service was killed by the TEE (due to an administrative command). */
+#define MC_DRV_ERR_NO_FREE_INSTANCES                0x00000027 /**< All permitted instances to the service are used */
+
+#endif /* TBASE_API_LEVEL >= 5 */
+
+#if TBASE_API_LEVEL >= 3
+// Installation errors
+#define MC_DRV_ERR_TA_HEADER_ERROR                  0x00000028 /**< TA blob header is incorrect. */
+#endif /* TBASE_API_LEVEL */
+
+#define MAKE_MC_DRV_MCP_ERROR(mcpCode)              (MC_DRV_ERR_MCP_ERROR | ((mcpCode&0x000FFFFF)<<8))
+#define MAKE_MC_DRV_KMOD_WITH_ERRNO(theErrno)       (MC_DRV_ERR_KERNEL_MODULE| (((theErrno)&0x0000FFFF)<<16))
+
+/** 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 t-base communication.
+ * It will be passed to calls which address a communication end point in the t-base environment.
+ */
+typedef struct {
+    uint32_t sessionId; /**< t-base session ID */
+    uint32_t deviceId; /**< Device ID the session belongs to */
+} mcSessionHandle_t;
+
+/** Information structure about additional mapped Bulk buffer between the Client Application (NWd) and
+ * the Trusted Application (SWd). This structure is initialized from a Client Application by calling mcMap().
+ * In order to use the memory within a Trusted Application the Client Application has to inform the Trusted Application with
+ * the content of this structure via the TCI.
+ */
+
+typedef struct {
+#if ( __WORDSIZE == 64 )
+    uint32_t sVirtualAddr;         /**< The virtual address of the Bulk buffer regarding the address space of the Trusted Application, already includes a possible offset! */
+#else
+    void *sVirtualAddr;
+#endif
+    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_INFINITE_TIMEOUT_INTERRUPTIBLE ((int32_t)(-2)) /**< Wait infinite for a response of the MC, exit on signal. */
+#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 */
+
+#ifndef WIN32
+/* Mark only the following functions for export */
+#pragma GCC visibility push(default)
+#endif
+
+/** Open a new connection to a t-base device.
+ *
+ * mcOpenDevice() initializes all device specific resources required to communicate
+ * with an t-base 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 t-base 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
+ */
+__MC_CLIENT_LIB_API mcResult_t mcOpenDevice(
+    uint32_t deviceId
+);
+
+/** Close the connection to a t-base 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 t-base 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 Trusted Application. The Trusted Application with the given UUID has to be available in the flash filesystem.
+ *
+ * Write MCP open message to buffer and notify t-base about the availability of a new command.
+ * Waits till t-base responds 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 Trusted Application to be opened.
+ * @param [in] tci TCI buffer for communicating with the Trusted Application.
+ * @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.
+ * @return MC_DRV_ERR_TRUSTED_APPLICATION_NOT_FOUND when Trusted Application or driver cannot be loaded.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcOpenSession(
+    mcSessionHandle_t  *session,
+    const mcUuid_t       *uuid,
+    uint8_t            *tci,
+    uint32_t           tciLen
+);
+
+/** Open a new session to a Trusted Application(Trustlet). The Trusted Application will be loaded from the memory buffer.
+ *
+ * Write MCP open message to buffer and notify t-base about the availability of a new command.
+ * Waits till t-base responds 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] spid Service Provider ID(for Service provider trustlets otherwise ignored)
+ * @param [in] trustedapp memory buffer containing the Trusted Application binary
+ * @param [in] tlen length of the memory buffer containing the Trusted Application
+ * @param [in] tci TCI buffer for communicating with the Trusted Application.
+ * @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.
+ * @return MC_DRV_ERR_TRUSTED_APPLICATION_NOT_FOUND when Trusted Application cannot be loaded.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcOpenTrustlet(
+    mcSessionHandle_t  *session,
+    mcSpid_t           spid,
+    uint8_t            *trustedapp,
+    uint32_t           tLen,
+    uint8_t            *tci,
+    uint32_t           tciLen
+);
+
+
+/** Close a Trusted Application session.
+ *
+ * Closes the specified t-base 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.
+ */
+__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 t-base 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 indefinitely, MC_INFINITE_TIMEOUT_INTERRUPTIBLE : wait indefinitely except if signal received)
+ *
+ * @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 Client Application (CA) and the Trusted Application (TA) for a session.
+ * Memory allocated in user space of the CA can be mapped as additional communication channel
+ * (besides TCI) to the Trusted Application. Limitation of the Trusted Application 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 (CA) to inform the Trusted Application 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 CA) to be shared with the Trusted Application, 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 CA (NWd) and
+ * the TA (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.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcMap(
+    mcSessionHandle_t  *session,
+    void               *buf,
+    uint32_t           len,
+    mcBulkMap_t        *mapInfo
+);
+
+/**
+ * Remove additional mapped bulk buffer between Client Application (CA) and the Trusted Application (TA) for a session.
+ *
+ * @attention The bulk buffer will immediately be unmapped from the session context.
+ * @attention The application layer (CA) must inform the TA 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 CA) shared with the TA, already includes a possible offset!
+ * @param [in] mapInfo Information structure about the mapped Bulk buffer between the CA (NWd) and
+ * the TA (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.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcUnmap(
+    mcSessionHandle_t  *session,
+    void               *buf,
+    mcBulkMap_t        *mapInfo
+);
+
+/**
+ * Get additional error information of the last error that occurred 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 Trusted Application has terminated itself with this value, <0 Trusted Application is dead because of an error within t-base (e.g. Kernel exception).
+ * See also notificationPayload_t enum in MCI definition at "mcinq.h".
+ *
+ * @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 t-base version information of a device.
+ *
+ * @param [in] deviceId of an open device.
+ * @param [out] versionInfo t-base 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
+);
+#ifndef WIN32
+#pragma GCC visibility pop
+#endif
+#endif /** MCDRIVER_H_ */
+
diff --git a/mobicore/ClientLib/include/log.h b/mobicore/ClientLib/include/log.h
new file mode 100644 (file)
index 0000000..34f3e40
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** Log wrapper for Android.
+ * 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.
+ */
+#ifndef TLCWRAPPERANDROIDLOG_H_
+#define TLCWRAPPERANDROIDLOG_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#ifndef WIN32
+#include <errno.h>
+#include <unistd.h>
+#define GETPID getpid
+#else
+#include <process.h>
+#define GETPID _getpid
+#endif
+
+/** LOG_D(fmt, ...)
+ * Debug information logging, only shown in debug version
+ */
+
+/** LOG_I(fmt, ...)
+ * Important information logging
+ */
+
+/** LOG_W(fmt, ...)
+ * Warnings logging
+ */
+
+/** LOG_E(fmt, ...)
+ * Error logging
+ */
+
+/** LOG_D_BUF(szDescriptor, blob, sizeOfBlob)
+ * Binary logging, line-wise output to LOG_D
+ */
+
+#define DUMMY_FUNCTION()    do {} while(0)
+
+#ifdef LOG_ANDROID
+#include <android/log.h>
+// log to adb logcat
+#ifdef NDEBUG // no logging in debug version
+    #define LOG_D(fmt, ...) DUMMY_FUNCTION()
+#else
+    // add LINE
+    #define LOG_D(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt " [%s:%d]", ##__VA_ARGS__, __FILE__, __LINE__)
+#endif
+    #define LOG_I(fmt, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt " [%s:%d]", ##__VA_ARGS__, __FILE__, __LINE__)
+    #define LOG_W(fmt, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, fmt " [%s:%d]", ##__VA_ARGS__, __FILE__, __LINE__)
+    #define _LOG_E(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##__VA_ARGS__)
+#endif // defined(LOG_ANDROID)
+
+
+#ifdef LOG_TIZEN
+#include <dlog.h>
+#ifdef NDEBUG
+    #define LOG_D(...)  DUMMY_FUNCTION()
+#else
+    #define LOG_D(...)  SLOGD(__VA_ARGS__)
+#endif
+    #define LOG_I(...)  SLOGI(__VA_ARGS__)
+    #define LOG_W(...)  SLOGW(__VA_ARGS__)
+    #define _LOG_E(...) SLOGE(__VA_ARGS__)
+#endif // defined(LOG_TIZEN)
+
+
+#if !defined(_LOG_E)
+    // log using fprintf, by default to stdout
+#ifdef LOG_FPRINTF
+    extern FILE* mc_log_file_;
+    #define _LOG_x(_x_,...) \
+        do { \
+            fprintf(mc_log_file_, "%s/%s(%d): ",_x_,LOG_TAG,GETPID()); \
+            fprintf(mc_log_file_, __VA_ARGS__); \
+            fprintf(mc_log_file_, "\n"); \
+        } while(0)
+#else // LOG_FPRINTF
+    #define _LOG_x(_x_,...) \
+        do { \
+            printf("%s/%s(%d): ",_x_,LOG_TAG,GETPID()); \
+            printf(__VA_ARGS__); \
+            printf("\n"); \
+        } while(0)
+#endif // !LOG_FPRINTF
+
+#ifdef NDEBUG // no logging in debug version
+    #define LOG_D(fmt, ...) DUMMY_FUNCTION()
+#else
+    #define LOG_D(...)  _LOG_x("D",__VA_ARGS__)
+#endif
+    #define LOG_I(...)  _LOG_x("I",__VA_ARGS__)
+    #define LOG_W(...)  _LOG_x("W",__VA_ARGS__)
+    #define _LOG_E(...)  _LOG_x("E",__VA_ARGS__)
+#endif // !defined(_LOG_E): neither Android nor Tizen
+
+
+/** LOG_E() needs to be more prominent:
+ * Display "*********** ERROR ***********" before actual error message.
+ */
+#define LOG_E(...) \
+            do { \
+                _LOG_E("  *****************************"); \
+                _LOG_E("  *** ERROR: " __VA_ARGS__); \
+                _LOG_E("  *** Detected in %s:%u()", __FILE__, __LINE__); \
+                _LOG_E("  *****************************"); \
+            } while(0)
+
+#define LOG_ERRNO(MESSAGE) \
+    LOG_E("%s failed with \"%s\"(errno %i)", MESSAGE, strerror(errno), errno);
+
+#ifdef NDEBUG
+    #define LOG_D_BUF(...)      DUMMY_FUNCTION()
+#else
+    #define LOG_D_BUF(f, b, s)  LOG_x_BUF(f, b, s, true)
+#endif
+#define LOG_I_BUF(f, b, s)      LOG_x_BUF(f, b, s, false)
+
+#ifndef WIN32
+__attribute__ ((unused))
+#endif
+static void LOG_x_BUF(
+        const char*     szDescriptor,
+        const void*     blob,
+        size_t          sizeOfBlob,
+        bool            debug
+) {
+
+#define CPL         0x10  // chars per line
+#define OVERHEAD    20
+
+    char buffer[CPL * 4 + OVERHEAD];
+
+    int index = 0;
+
+    uint32_t moreThanOneLine = (sizeOfBlob > CPL);
+    size_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], " (%p, %zu bytes)", blob,sizeOfBlob);
+        LOG_D("%s", buffer);
+        index = 0;
+    }
+    else if (NULL == szDescriptor)
+    {
+        index += sprintf(&buffer[index], "Data at %p: ", blob);
+    }
+
+    if(sizeOfBlob == 0) {
+        LOG_D("%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 unsigned 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
+            if (debug) {
+                LOG_D("%s", buffer);
+            } else {
+                LOG_I("%s", buffer);
+            }
+            index = 0;
+        }
+    }
+}
+
+#endif /** TLCWRAPPERANDROIDLOG_H_ */
diff --git a/mobicore/ClientLib/include/mcContainer.h b/mobicore/ClientLib/include/mcContainer.h
new file mode 100644 (file)
index 0000000..c74f8f1
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef 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"
+
+/** Support for trustlet container 2.1 */
+#define CONTAINER_FORMAT_TL21 1
+
+#define CONTAINER_VERSION_MAJOR   2
+/** Support for the old format */
+#ifdef CONTAINER_FORMAT_TL21
+#define CONTAINER_VERSION_MINOR   1
+#else
+#define CONTAINER_VERSION_MINOR   0
+#endif
+
+#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 = 1,
+    /** Service provider container. */
+    CONT_TYPE_SP = 2,
+    /** Trustlet container. */
+    CONT_TYPE_TLCON = 3,
+    /** Service provider data. */
+    CONT_TYPE_SPDATA = 4,
+    /** Trustlet data. */
+    CONT_TYPE_TLDATA = 5
+} contType_t;
+
+/** SHA256 checksum. */
+typedef struct {
+    uint8_t data[32];
+} mcSha256_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;
+    mcContVersion_t version;
+    mcContainerAttribs_t attribs;
+    mcSuid_t suid;
+    // Secrets.
+    mcCoSocCont_t co;
+} mcSocCont_t;
+
+/** */
+typedef struct {
+    contType_t type;
+    mcContVersion_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;
+    mcContVersion_t version;
+    mcContainerAttribs_t attribs;
+    mcSpid_t spid;
+    mcUuidChild_t children;
+    // Secrets.
+    mcCoSpCont_t co;
+} mcSpCont_t;
+
+/** */
+typedef struct {
+    contType_t type;
+    mcContVersion_t version;
+    mcContainerAttribs_t attribs;
+    mcSpid_t parent;
+    mcUuid_t uuid;
+    // Secrets.
+    mcCoTltCont_t co;
+} mcTltContCommon_t;
+
+/** */
+typedef struct {
+    mcTltContCommon_t common;
+} mcTltCont_2_0_t;
+
+/** */
+typedef struct {
+    mcTltContCommon_t common;
+    mcSha256_t skSpTltEnc;
+    mcContVersion_t tltVersion;
+} mcTltCont_2_1_t;
+
+/** */
+typedef struct {
+    contType_t type;
+    mcContVersion_t version;
+    mcUuid_t uuid;
+    mcPid_t pid;
+    // Secrets.
+    mcCoDataCont_t co;
+} mcDataCont_t;
+
+/** Helper for finding maximum value */
+#define MC_MAX(x, y) (((x)<(y))?(y):(x))
+
+/** 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_MAX( MC_SO_SIZE_F21((contTotalSize) - (contCoSize), (contCoSize)) \
+           - sizeof(mcSoHeader_t) - (contTotalSize), \
+                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_2_0_t cont;
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcTltCont_2_0_t), sizeof(mcCoTltCont_t))];
+} mcSoTltCont_2_0_t;
+
+typedef struct {
+    mcSoHeader_t soHeader;
+    mcTltCont_2_1_t cont;
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcTltCont_2_1_t), sizeof(mcCoTltCont_t))];
+} mcSoTltCont_2_1_t;
+
+#ifdef CONTAINER_FORMAT_TL21
+typedef mcSoTltCont_2_0_t mcSoTltCont_t;
+#else
+typedef mcTltContCommon_t mcTltCont_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 ;
+#endif
+
+/** */
+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;
+
+/** Trustlet Blob length info */
+typedef struct {
+    uint32_t        magic;             /**< New blob format magic number*/
+    uint32_t        rootContBlobSize;  /**< Root container blob size */
+    uint32_t        spContBlobSize;    /**< SP container blob size */
+    uint32_t        tlContBlobSize;    /**< Tl container blob size */
+    uint32_t        reserved[4];       /**< Reserved for further Use */
+} mcBlobLenInfo_t, *mcBlobLenInfo_ptr;
+
+#define MC_TLBLOBLEN_MAGIC 0x7672746C
+
+#endif // MC_CONTAINER_H_
+
diff --git a/mobicore/ClientLib/include/mcDriverId.h b/mobicore/ClientLib/include/mcDriverId.h
new file mode 100644 (file)
index 0000000..65550d9
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef 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,
+    /** 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,
+    TB_DRV_NUMBER_TUI  = 0x101,
+    TB_DRV_NUMBER_SFS  = 0x104,
+    TB_DRV_NUMBER_TPLAY  = 0x600,
+} 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_SFS  = MC_DRV_VENDOR_ID_GD | TB_DRV_NUMBER_SFS,
+    /** 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,
+    TB_DRV_ID_TUI  = MC_DRV_VENDOR_ID_GD | TB_DRV_NUMBER_TUI,
+    TB_DRV_ID_TPLAY  = MC_DRV_VENDOR_ID_GD | TB_DRV_NUMBER_TPLAY,
+} mcDriverId_t;
+
+#endif /* RTMDRVID_H_ */
diff --git a/mobicore/ClientLib/include/mcLoadFormat.h b/mobicore/ClientLib/include/mcLoadFormat.h
new file mode 100644 (file)
index 0000000..bfa39d7
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCLOADFORMAT_H_
+#define MCLOADFORMAT_H_
+
+#include "mcUuid.h"
+#include "mcSuid.h"
+#include "mcDriverId.h"
+
+#define MCLF_VERSION_MAJOR   2
+#define MCLF_VERSION_MINOR   5
+#define MCLF_VERSION_MINOR_CURRENT   3
+
+#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. */
+#define MC_SERVICE_HEADER_FLAGS_EXTENDED_LAYOUT          (1U << 3) /**< New-layout trusted application or trusted driver. */
+
+
+/** 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. */
+    SERVICE_TYPE_MIDDLEWARE      = 4, /**< Service is a middleware. */
+    SERVICE_TYPE_LAST_ENTRY      = 5, /**< marker for last entry */
+} 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 {
+    uint32_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 2 /////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * @defgroup MCLF_VER_V2   MCLF Version 32
+ * @ingroup MCLF_VER
+ *
+ * @addtogroup MCLF_VER_V2
+ */
+
+/**
+ * Version 2.1/2.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. */
+    uint32_t                entry;          /**< Virtual start address of service code. */
+    uint32_t                serviceVersion; /**< Version of the interface the driver exports. */
+
+// These should be put on next MCLF update:
+//    mcSuid_t                permittedSuid;  /**< Starting 2.3: If nonzero, suid which is allowed to execute binary */
+//    uint32_t                permittedHwCf;  /**< Starting 2.3: If nonzero, hw configuration which is allowed to execute binary */
+
+} mclfHeaderV2_t, *mclfHeaderV2_ptr;
+
+
+/**
+ * Version 2.3 MCLF header.
+ */
+typedef struct {
+    mclfHeaderV2_t          mclfHeaderV2;
+    mcSuid_t                permittedSuid;  /**< Starting 2.3: If nonzero, suid which is allowed to execute binary */
+    uint32_t                permittedHwCfg; /**< Starting 2.3: If nonzero, hw configuration which is allowed to execute binary */
+} mclfHeaderV23_t, *mclfHeaderV23_ptr;
+
+
+/**
+ * Version 2.4 MCLF header.
+ */
+typedef struct {
+    mclfHeaderV23_t         mclfHeaderV2;
+    uint32_t                gp_level;           /**<Starting 2.4: 0 for legacy MobiCore trustlets and 1 for Potato TAs. */
+    uint32_t                attestationOffset;  /**<Starting 2.4: Offset of attestation data area. */
+
+} mclfHeaderV24_t, *mclfHeaderV24_ptr;
+
+
+
+/*
+ * HEAP parameters
+ */
+
+typedef struct {
+    uint32_t    init;
+    uint32_t    max;
+} heapSize_t, *heapSize_ptr;
+
+/*
+ * McLib Internal Management Data
+ * This structure defines the parameters of a buffer used internally by McLib for each TA/TDriver
+ * and it specifies default heap parameters (for MCLF header versions >=2.5)
+ *
+ * `mcLibData` field describes McLib work buffer
+ * and it is used for MCLF header versions <=2.4
+ * In this case the buffer is a part of TA BSS section
+ *
+ * For MCLF header versions >=2.5 `mcLibData` field is not used anymore and
+ * replaced by `mcLibData` field
+ * RTM itself determines actual address in this case and sets `mcLibData` field value
+ *
+ * `heapSize` field describes default heap parameters and
+ *  it is used only for MCLF header versions >=2.5
+ *
+ */
+typedef struct {
+    union {
+        segmentDescriptor_t     mcLibData;  /**< Segment for McLib data.
+                                                 Set at compile time.
+                                                 Required always. */
+        heapSize_t              heapSize;   /**< Initial and maximum heap sizes.
+                                                 Set by MobiConvert for extended-layout TAs */
+    } cfg;
+    uint32_t                    mcLibBase;  /**< McLib base address.
+                                                 Mobicore sets at load time for trustlets / drivers.
+                                                 Required always. */
+} mclfIMD_t, *mclfIMD_ptr;
+
+
+/*
+ * GP TA identity.
+ */
+typedef struct {
+    uint32_t loginType;                     /**< GP TA login type */
+    uint8_t  loginData[16];                 /**< GP TA login data */
+} mcIdentity_t;
+
+/**
+ * Version 2 MCLF text segment header.
+ * Required to be present in MobiCore 1.2 components at address (0x1080).
+ * This extension is initialized already at trustlet compile time,
+ * but may be modified later by configuration tools and by MobiCore at load time.
+ */
+typedef struct {
+    uint32_t                version;        /**< Version of the TextHeader structure. */
+    uint32_t                textHeaderLen;  /**< Size of this structure (fixed at compile time) */
+    uint32_t                requiredFeat;   /**< Flags to indicate features that Mobicore must understand/interprete when loading.
+                                                 Required always. */
+    uint32_t                mcLibEntry;     /**< Address for McLib entry.
+                                                 Mobicore sets at load time for trustlets / drivers.
+                                                 Required always. */
+    mclfIMD_t               mcIMD;          /**< McLib Internal Management Data */
+    uint32_t                tlApiVers;      /**< TlApi version used when building trustlet.
+                                                 Value set at compile time.
+                                                 Required always. */
+    uint32_t                drApiVers;      /**< DrApi version used when building trustlet.
+                                                 Value set at compile time for drivers. 0 for trustlets.
+                                                 Required always. */
+    uint32_t                ta_properties;  /**< address of _TA_Properties in the TA. */
+    mcIdentity_t            mcIdentity;     /**< Identity of GP TA */
+} mclfTextHeader_t, *mclfTextHeader_ptr;
+
+// Version 2 ///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * @addtogroup MCLF
+ */
+
+/** MCLF header */
+typedef union {
+    mclfIntro_t    intro;           /**< Intro for data structure identification. */
+    mclfHeaderV2_t mclfHeaderV2;    /**< Version 2 header */
+} mclfHeader_t, *mclfHeader_ptr;
+
+// Version 2.3 changes header definition
+// Above structure is hard-coded into many places.
+// So new changes are made into separate structure.
+#define MCLF_HEADER_SIZE_V23 (0x080)
+
+// Actual (known) length can be calculated using macro
+#define MCLF_HEADER_SIZE(version) ((version)>0x20002?(MCLF_HEADER_SIZE_V23):sizeof(mclfHeader_t))
+
+// This is only minimum size, so nothing below this makes sense.
+#define MCLF_BINARY_MIN_SIZE(version) (MCLF_HEADER_SIZE_V23+sizeof(mclfTextHeader_t))
+
+/** mclfTlHeader: layout of TA start */
+typedef struct {
+    mclfIntro_t        intro;
+    uint8_t            mclfHeader[0x80-sizeof(mclfIntro_t)];
+    mclfTextHeader_t   textHeader;
+} mclfTlHeader_t;
+
+#endif /* MCLOADFORMAT_H_ */
+
diff --git a/mobicore/ClientLib/include/mcRootid.h b/mobicore/ClientLib/include/mcRootid.h
new file mode 100644 (file)
index 0000000..d1a17b1
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MC_ROOTID_H_
+#define MC_ROOTID_H_
+
+#ifdef WIN32
+#define _UNUSED
+#else
+#define _UNUSED __attribute__((unused))
+#endif
+
+/** Root Identifier type. */
+typedef uint32_t mcRootid_t;
+
+/** Reserved root id value 1. */
+static _UNUSED const mcRootid_t MC_ROOTID_RESERVED1 = 0;
+
+/** Reserved root id value 2. */
+static _UNUSED const mcRootid_t MC_ROOTID_RESERVED2 = 0xFFFFFFFF;
+
+/** Root id for system applications. */
+static _UNUSED const mcRootid_t MC_ROOTID_SYSTEM = 0xFFFFFFFE;
+
+/** Yet another test ROOT ID */
+static _UNUSED const mcRootid_t MC_ROOTID_RESERVED3 = 0xFFFFFFFD;
+
+/** GP TAs - used in the Trusted storage */
+static _UNUSED const mcRootid_t MC_ROOTID_GP = 0xFFFFFFFC;
+
+/** RTM's Root ID */
+static _UNUSED const mcRootid_t MC_ROOTID_RTM = 0xFFFFFFFB;
+
+#endif // MC_ROOTID_H_
+
diff --git a/mobicore/ClientLib/include/mcSo.h b/mobicore/ClientLib/include/mcSo.h
new file mode 100644 (file)
index 0000000..d33f055
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MC_SO_H_
+#define MC_SO_H_
+
+#include "mcUuid.h"
+#include "mcSpid.h"
+#include "mcRootid.h"
+
+#define SO_USE_VERSION_22 1
+
+#define SO_VERSION_MAJOR   2
+#define SO_VERSION_MINOR   2
+
+#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;
+
+/** Service provider Trustlet id with specific RootId.
+ */
+typedef struct {
+    /** Service provider id. */
+    mcSpid_t spid;
+    /** Trustlet UUID. */
+    mcUuid_t uuid;
+    /** Trustlet RootId. */
+    mcRootid_t rootid;
+} tlApiSpTrustletIdEx_t;
+
+// The client identity (encoding its root ID, SPID and UUID).
+typedef tlApiSpTrustletIdEx_t client_identity_t;
+
+/** Secure object header v2.2.
+ * A secure object header introduces a secure object.
+ * Layout of a secure object:
+ * <pre>
+ * <code>
+ *
+ *     +--------+------------------+------------------+--------+--------+
+ *     | Header |   plain-data     |  encrypted-data  |  hash  | random |
+ *     +--------+------------------+------------------+--------+--------+
+ *
+ *     /--------/---- plainLen ----/-- encryptedLen --/-- 32 --/-- 16 --/
+ *
+ *     /----------------- toBeHashedLen --------------/
+ *
+ *                                 /-- toBeEncryptedLen --/
+ *
+ *     /--------------------------- totalSoSize ------------------------/
+ *
+ * </code>
+ * </pre>
+ */
+
+/** Secure object header v2.1.
+ * A secure object header introduces a secure object.
+ * Layout of a secure object:
+ * <pre>
+ * <code>
+ *
+ *     +--------+------------------+------------------+--------+--------+---------+
+ *     | Header |   plain-data     |  encrypted-data  |  hash  | random | padding |
+ *     +--------+------------------+------------------+--------+--------+---------+
+ *
+ *     /--------/---- plainLen ----/-- encryptedLen --/-- 24 --/--- 9 --/- 0..15 -/
+ *
+ *     /----------------- toBeHashedLen --------------/
+ *
+ *                                 /-- toBeEncryptedLen --/
+ *
+ *     /--------------------------- totalSoSize ----------------------------------/
+ *
+ * </code>
+ * </pre>
+ */
+
+/** Secure object header v2.0.
+ * 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 v2. */
+#define MC_SO_HASH_SIZE             32
+
+/** Size of hash used for secure object v2.1. */
+#define MC_SO21_HASH_SIZE            24
+/** Size of random used for secure objects v2.1. */
+#define MC_SO21_RND_SIZE             9
+
+/** Size of hash used for secure object v2.2. */
+#define MC_SO22_HASH_SIZE            32
+/** Size of random used for secure objects v2.2. */
+#define MC_SO22_RND_SIZE             16
+
+/** Hash size for current generated wrapping */
+#define MC_SO2X_HASH_SIZE MC_SO22_HASH_SIZE
+/** Random size for current generated wrapping */
+#define MC_SO2X_RND_SIZE MC_SO22_RND_SIZE
+
+#define MC_SO_ENCRYPT_PADDED_SIZE_F21(netsize) ( (netsize) + \
+    MC_SO_MAX_PADDING_SIZE - (netsize) % MC_SO_MAX_PADDING_SIZE )
+
+#if SO_USE_VERSION_22
+    // No encryption padding at all.
+#else
+    /** Calculates gross size of cryptogram within secure object including ISO padding bytes. */
+    #define MC_SO_ENCRYPT_PADDED_SIZE(netsize) MC_SO_ENCRYPT_PADDED_SIZE_F21(netsize)
+#endif
+
+
+/** 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_F22(plainLen, encryptedLen) ( \
+    ((plainLen) + (encryptedLen) < (encryptedLen) || (plainLen) + (encryptedLen) > MC_SO_PAYLOAD_MAX_SIZE) ? 0 : \
+            sizeof(mcSoHeader_t) + (plainLen) + (encryptedLen) +MC_SO22_HASH_SIZE +MC_SO22_RND_SIZE \
+    )
+#define MC_SO_SIZE_F21(plainLen, encryptedLen) ( \
+    ((plainLen) + (encryptedLen) < (encryptedLen) || (plainLen) + (encryptedLen) > MC_SO_PAYLOAD_MAX_SIZE) ? 0 : \
+            sizeof(mcSoHeader_t) +(plainLen) +MC_SO_ENCRYPT_PADDED_SIZE_F21((encryptedLen) +MC_SO_HASH_SIZE) \
+)
+
+#define MC_SO_SIZE(plainLen, encryptedLen) MC_SO_SIZE_F22(plainLen, encryptedLen)
+
+#endif // MC_SO_H_
+
diff --git a/mobicore/ClientLib/include/mcSpid.h b/mobicore/ClientLib/include/mcSpid.h
new file mode 100644 (file)
index 0000000..643e720
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MC_SPID_H_
+#define MC_SPID_H_
+
+#ifdef WIN32
+#define _UNUSED
+#else
+#define _UNUSED __attribute__((unused))
+#endif
+
+/** Service provider Identifier type. */
+typedef uint32_t mcSpid_t;
+
+/** SPID value used as free marker in root containers. */
+static _UNUSED const mcSpid_t MC_SPID_FREE = 0xFFFFFFFF;
+
+/** Reserved SPID value. */
+static _UNUSED const mcSpid_t MC_SPID_RESERVED = 0;
+
+/** SPID for system applications. */
+static _UNUSED const mcSpid_t MC_SPID_SYSTEM = 0xFFFFFFFE;
+
+/** SPID reserved for tests only */
+static _UNUSED const mcSpid_t MC_SPID_RESERVED_TEST = 0xFFFFFFFD;
+static _UNUSED const mcSpid_t MC_SPID_TRUSTONIC_TEST = 0x4;
+
+/** SPID reserved for OTA development */
+static _UNUSED const mcSpid_t MC_SPID_TRUSTONIC_OTA = 0x2A;
+
+/** GP TAs - stored in the trusted storage. They all share the same */
+static _UNUSED const mcSpid_t MC_SPID_GP = 0xFFFFFFFC;
+
+/** RTM's SPID */
+static _UNUSED const mcSpid_t MC_SPID_RTM = 0xFFFFFFFB;
+
+#endif // MC_SPID_H_
+
diff --git a/mobicore/ClientLib/include/mcSuid.h b/mobicore/ClientLib/include/mcSuid.h
new file mode 100644 (file)
index 0000000..b5bb983
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef 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/ClientLib/include/mcUuid.h b/mobicore/ClientLib/include/mcUuid.h
new file mode 100644 (file)
index 0000000..61ee94b
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MC_UUID_H_
+#define MC_UUID_H_
+
+#ifdef WIN32
+#define _UNUSED
+#else
+#define _UNUSED __attribute__((unused))
+#endif
+
+#define UUID_TYPE
+
+#define UUID_LENGTH 16
+/** Universally Unique Identifier (UUID) according to ISO/IEC 11578. */
+typedef struct {
+    uint8_t value[UUID_LENGTH]; /**< 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 _UNUSED 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 _UNUSED 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 _UNUSED const mcUuid_t MC_UUID_SYSTEM = {
+    MC_UUID_SYSTEM_DEFINE
+};
+
+#define MC_UUID_RTM_DEFINE \
+    { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34,       \
+      0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }
+
+static _UNUSED const mcUuid_t MC_UUID_RTM = {
+    MC_UUID_RTM_DEFINE
+};
+
+/**
+ * TODO: Replace with v5 UUID (milestone #3)
+ */
+#define LTA_UUID_DEFINE \
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,         \
+      0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}
+
+#endif // MC_UUID_H_
+
diff --git a/mobicore/ClientLib/include/mcVersionHelper.h b/mobicore/ClientLib/include/mcVersionHelper.h
new file mode 100644 (file)
index 0000000..7f89797
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MCVERSIONHELPER_H_
+#define MCVERSIONHELPER_H_
+
+#include <stdio.h>
+
+
+/** 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)
+#if !defined(TRUSTLET)
+#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; \
+        /* Check equality and superiority separately to avoid warning if minor == 0 */ \
+        if ((major == majorRequired) && ((minor == minorRequired) || (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 /* TRUSTLET */
+#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)) { \
+            tlDbgPrintf(#comp " version is %u.%u", major, minor); \
+            return 1; \
+        } else { \
+            tlDbgPrintf( \
+                #comp " version error. Got: %u.%u, want >= %u.%u", major, minor, majorRequired, minorRequired); \
+        } \
+        return 0; \
+    }
+#endif /* TRUSTLET */
+#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; \
+        /* Check equality and superiority separately to avoid warning if minor == 0 */ \
+        if ((major == majorRequired) && ((minor == minorRequired) || (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)
+#if !defined(TRUSTLET)
+#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, \
+                (uint32_t)majorRequired, (uint32_t)minorRequired); \
+        } \
+        msgBuf[sizeof(msgBuf) - 1] = '\0'; \
+        return ret; \
+    }
+#else /* TRUSTLET */
+#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)) { \
+            tlDbgPrintf(#comp " version is %u.%u", major, minor); \
+            return 1; \
+        } else { \
+            tlDbgPrintf( \
+                #comp " version error. Got: %u.%u, want <= %u.%u", major, minor, \
+                (uint32_t)majorRequired, (uint32_t)minorRequired); \
+        } \
+        return 0; \
+    }
+#endif /* TRUSTLET */
+#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
+
+#endif // MCVERSIONHELPER_H_
diff --git a/mobicore/ClientLib/include/mcVersionInfo.h b/mobicore/ClientLib/include/mcVersionInfo.h
new file mode 100644 (file)
index 0000000..5e2ae86
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef 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/ClientLib/include/proxy_server.h b/mobicore/ClientLib/include/proxy_server.h
new file mode 100644 (file)
index 0000000..0c5cae1
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PROXY_SERVER_H__
+#define __PROXY_SERVER_H__
+
+class ProxyServer {
+    struct Impl;
+    Impl* const pimpl_;
+    void run();
+public:
+    ProxyServer();
+    ~ProxyServer();
+    int open();
+    int close();
+};
+
+#endif // __PROXY_SERVER_H__
diff --git a/mobicore/ClientLib/include/uuid_attestation.h b/mobicore/ClientLib/include/uuid_attestation.h
new file mode 100644 (file)
index 0000000..4230572
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEE_UUID_ATTESTATION_H__
+#define __TEE_UUID_ATTESTATION_H__
+
+#ifndef __TEE_CLIENT_TYPES_H__
+#include "tee_type.h"
+#endif
+
+// Sizes of the fields of attestation structure
+#define AT_MAGIC_SIZE           8
+#define AT_SIZE_SIZE            sizeof(uint32_t)
+#define AT_VERSION_SIZE         sizeof(uint32_t)
+#define AT_UUID_SIZE            sizeof(TEE_UUID)
+
+// Sizes of the fields used to generate signature
+#define AT_TAG_SIZE             20
+#define AT_SHA1_HASH_SIZE       20
+
+// Max size of RSA modulus supported
+#define AT_MODULUS_MAX_SIZE     256
+// Max size of RSA public exponent supported
+#define AT_PUBLIC_EXPO_MAX_SIZE 4
+
+// Attestation version
+#define AT_VERSION              1
+
+// Name space ID (the UUID of the RSA OID)
+const uint8_t       RSA_OID_UUID[AT_UUID_SIZE] = {0x6b, 0x8e, 0x02, 0x6b, 0x63, 0xc1, 0x5d, 0x58, 0xb0, 0x64, 0x00, 0xd3, 0x51, 0x89, 0xce, 0x65};
+// Magic word
+const char          MAGIC[AT_MAGIC_SIZE] = "TAUUID\0";
+
+// Tag for signature generation
+const char          TAG[AT_TAG_SIZE]="Trusted Application";
+
+// Public key structure
+typedef struct uuid_public_key {
+    uint32_t    type;           // TEE_TYPE_RSA_PUBLIC_KEY: 0xA0000030
+    uint16_t    modulus_bytes;  // Length of the modulus in bytes
+    uint16_t    exponent_bytes; // Length of the exponent in bytes
+    uint8_t     data[];         // Key material
+} uuid_public_key;
+
+// Attestation structure
+typedef struct uuid_attestation {
+    uint8_t         magic[AT_MAGIC_SIZE];   // Magic word: "TAUUID\0\0"
+    uint32_t        size;                   // Attestation size (4 bytes)
+    uint32_t        version;                // Version number: 1 (4 bytes)
+    uint8_t         uuid[AT_UUID_SIZE];     // UUID
+    uuid_public_key key;                    // Public key
+} uuid_attestation;
+
+#endif /* __TEE_UUID_ATTESTATION_H__ */
diff --git a/mobicore/ClientLib/src/buildTag.h b/mobicore/ClientLib/src/buildTag.h
new file mode 100644 (file)
index 0000000..d8a4859
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICORE_COMPONENT_BUILD_TAG
+#define MOBICORE_COMPONENT_BUILD_TAG \
+       "t-base-EXYNOS64-Android-310B-V006-20160331_140301_7136"
+#endif
diff --git a/mobicore/ClientLib/src/common_client.cpp b/mobicore/ClientLib/src/common_client.cpp
new file mode 100644 (file)
index 0000000..90e5fd7
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <string.h>
+
+#undef LOG_TAG
+#define LOG_TAG "TeeCommonClient"
+#include "log.h"
+#include "mcVersionHelper.h"
+#include "driver_client.h"
+#ifndef WITHOUT_PROXY
+#include "proxy_client.h"
+#endif
+#include "common_client.h"
+
+#ifdef LOG_FPRINTF
+// Set default log destination (needs to be somewhere)
+FILE* mc_log_file_ = stdout;
+#endif
+
+struct CommonClient::Impl {
+    pthread_mutex_t mutex;
+    int open_count;
+    DriverClient driver;
+#ifndef WITHOUT_PROXY
+    ProxyClient proxy;
+#endif
+    IClient* client;
+    OpenMode open_mode;
+    Impl(): open_count(0), client(NULL), open_mode(AUTO) {
+        pthread_mutex_init(&mutex, NULL);
+    }
+};
+
+CommonClient::CommonClient(): pimpl_(new Impl) {
+}
+
+CommonClient::~CommonClient() {
+    delete pimpl_;
+}
+
+int CommonClient::open() {
+    int ret = 0;
+    pthread_mutex_lock(&pimpl_->mutex);
+    if (pimpl_->client && !pimpl_->client->isOpen()) {
+        pimpl_->open_count = 0;
+    }
+    if (pimpl_->open_count == 0) {
+        if ((pimpl_->open_mode != PROXY) && (pimpl_->driver.open() >= 0)) {
+            pimpl_->client = &pimpl_->driver;
+#ifndef WITHOUT_PROXY
+        } else if ((pimpl_->open_mode != DRIVER) &&
+                   (pimpl_->proxy.open() >= 0)) {
+            pimpl_->client = &pimpl_->proxy;
+#endif
+        } else {
+            LOG_E("Failed to open lower layers: %s", strerror(errno));
+            ret = -1;
+        }
+    }
+    if (pimpl_->client) {
+        pimpl_->open_count++;
+    }
+    pthread_mutex_unlock(&pimpl_->mutex);
+    LOG_D("%s ret=%d open_count=%d", __FUNCTION__, ret, pimpl_->open_count);
+    return ret;
+}
+
+int CommonClient::closeCheck() {
+    int ret;
+    pthread_mutex_lock(&pimpl_->mutex);
+    if (pimpl_->open_count > 1) {
+        pimpl_->open_count--;
+        ret = 0;
+    } else {
+        errno = EPERM;
+        ret = -1;
+    }
+    pthread_mutex_unlock(&pimpl_->mutex);
+    LOG_D("%s ret=%d open_count=%d", __FUNCTION__, ret, pimpl_->open_count);
+    return ret;
+}
+
+int CommonClient::close() {
+    int ret = -1;
+    pthread_mutex_lock(&pimpl_->mutex);
+    /* Not open */
+    if (!pimpl_->client) {
+        errno = EBADF;
+    } else {
+        /* Last token */
+        if (pimpl_->open_count == 1) {
+            ret = pimpl_->client->close();
+            pimpl_->client = NULL;
+        } else {
+            ret = 0;
+        }
+        pimpl_->open_count--;
+    }
+    pthread_mutex_unlock(&pimpl_->mutex);
+    LOG_D("%s ret=%d open_count=%d", __FUNCTION__, ret, pimpl_->open_count);
+    return ret;
+}
+
+bool CommonClient::isOpen() const {
+    return pimpl_->open_count > 0;
+}
+
+int CommonClient::hasOpenSessions() const {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->hasOpenSessions();
+}
+
+int CommonClient::openSession(struct mc_ioctl_open_session& session) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->openSession(session);
+}
+
+int CommonClient::openTrustlet(struct mc_ioctl_open_trustlet& trustlet) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->openTrustlet(trustlet);
+}
+
+int CommonClient::closeSession(uint32_t session_id) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->closeSession(session_id);
+}
+
+int CommonClient::notify(uint32_t session_id) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->notify(session_id);
+}
+
+int CommonClient::waitNotification(const struct mc_ioctl_wait& wait) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->waitNotification(wait);
+}
+
+int CommonClient::malloc(uint8_t** buffer, uint32_t length) {
+    // Check length here to make sure we are consistent, with or without proxy
+    if ((length == 0) || (length > BUFFER_LENGTH_MAX)) {
+        errno = EINVAL;
+        return -1;
+    }
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->malloc(buffer, length);
+}
+
+int CommonClient::free(uint8_t* buffer, uint32_t length) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->free(buffer, length);
+}
+
+int CommonClient::map(struct mc_ioctl_map& map) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->map(map);
+}
+
+int CommonClient::unmap(const struct mc_ioctl_map& map) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->unmap(map);
+}
+
+int CommonClient::getError(struct mc_ioctl_geterr& err) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->getError(err);
+}
+
+int CommonClient::getVersion(struct mc_version_info& version_info) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->getVersion(version_info);
+}
+
+int CommonClient::gpRequestCancellation(uint32_t session_id) {
+    if (!pimpl_->client) {
+        errno = EBADF;
+        return -1;
+    }
+    return pimpl_->client->gpRequestCancellation(session_id);
+}
+
+void CommonClient::setOpenMode(OpenMode open_mode) {
+#ifdef WITHOUT_PROXY
+    (void) open_mode;
+#else
+    pimpl_->open_mode = open_mode;
+#endif
+}
diff --git a/mobicore/ClientLib/src/common_client.h b/mobicore/ClientLib/src/common_client.h
new file mode 100644 (file)
index 0000000..0458999
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Common open/file device functions for Mobicore and GP */
+
+#ifndef __CLIENT_COMMON_H__
+#define __CLIENT_COMMON_H__
+
+#include "iclient.h"
+
+class CommonClient: public IClient {
+    struct Impl;
+    Impl* const pimpl_;
+    CommonClient();
+public:
+    ~CommonClient();
+    virtual int open();
+    int closeCheck();
+    virtual int close();
+    virtual bool isOpen() const;
+    virtual int hasOpenSessions() const;
+    virtual int openSession(struct mc_ioctl_open_session& session);
+    virtual int openTrustlet(struct mc_ioctl_open_trustlet& trustlet);
+    virtual int closeSession(uint32_t session_id);
+    virtual int notify(uint32_t session_id);
+    virtual int waitNotification(const struct mc_ioctl_wait& wait);
+    virtual int malloc(uint8_t** buffer, uint32_t length);
+    virtual int free(uint8_t* buffer, uint32_t length);
+    virtual int map(struct mc_ioctl_map& map);
+    virtual int unmap(const struct mc_ioctl_map& map);
+    virtual int getError(struct mc_ioctl_geterr& err);
+    virtual int getVersion(struct mc_version_info& version_info);
+    virtual int gpRequestCancellation(uint32_t session_id);
+    // Singleton
+    static CommonClient& getInstance() {
+        static CommonClient client;
+        return client;
+    }
+    // For test purpose
+    enum OpenMode {
+        AUTO,
+        DRIVER = 0x44525652,
+        PROXY = 0x50525859,
+    };
+    void setOpenMode(OpenMode open_mode);
+};
+
+#endif // __CLIENT_COMMON_H__
diff --git a/mobicore/ClientLib/src/driver_client.cpp b/mobicore/ClientLib/src/driver_client.cpp
new file mode 100644 (file)
index 0000000..e93a7a5
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <vector>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <pthread.h>
+
+#include <tee_client_api.h>     // TEEC_UUID
+#include <GpTci.h>              // _TEEC_TCI
+
+#undef LOG_TAG
+#define LOG_TAG "TeeDriverClient"
+#include "log.h"
+#include "mcVersionHelper.h"
+#include "driver_client.h"
+
+MC_CHECK_VERSION(MCDRVMODULEAPI, 2, 1);
+
+struct DriverClient::Impl {
+    struct GpSession {
+        uint32_t id;
+        _TEEC_TCI* tci;
+        GpSession(uint32_t i, uint64_t t): id(i) {
+            tci = reinterpret_cast<_TEEC_TCI*>(static_cast<uintptr_t>(t));
+        }
+    };
+    pthread_mutex_t gp_sessions_mutex;
+    std::vector<GpSession*> gp_sessions;
+    int fd;
+    Impl(): fd(-1) {
+        ::pthread_mutex_init(&gp_sessions_mutex, NULL);
+    }
+    ~Impl() {
+        ::pthread_mutex_destroy(&gp_sessions_mutex);
+    }
+};
+
+DriverClient::DriverClient(): pimpl_(new Impl) {
+}
+
+DriverClient::~DriverClient() {
+    delete pimpl_;
+}
+
+int DriverClient::open() {
+    int fd = ::open("/dev/" MC_USER_DEVNODE, O_RDWR | O_CLOEXEC);
+    if (fd < 0) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return -1;
+    }
+
+    struct mc_version_info version_info;
+    if (::ioctl(fd, MC_IO_VERSION, &version_info) < 0) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        (void)::close(fd);
+        return -1;
+    }
+
+    // Run-time check.
+    uint32_t version = version_info.version_nwd;
+    char* errmsg;
+    if (!checkVersionOkMCDRVMODULEAPI(version, &errmsg)) {
+        (void)::close(fd);
+        errno = EHOSTDOWN;
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return -1;
+    }
+
+    pimpl_->fd = fd;
+    LOG_I("driver client open");
+    return 0;
+}
+
+int DriverClient::close() {
+    int ret = ::close(pimpl_->fd);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+    }
+    pimpl_->fd = -1;
+    LOG_I("driver client closed");
+    return ret;
+}
+
+bool DriverClient::isOpen() const {
+    return pimpl_->fd != -1;
+}
+
+int DriverClient::hasOpenSessions() const {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_HAS_SESSIONS);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+    }
+    return ret;
+}
+
+int DriverClient::openSession(struct mc_ioctl_open_session& session) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_OPEN_SESSION, &session);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    if (session.is_gp_uuid) {
+        pthread_mutex_lock(&pimpl_->gp_sessions_mutex);
+        pimpl_->gp_sessions.push_back(
+            new Impl::GpSession(session.sid, session.tci));
+        pthread_mutex_unlock(&pimpl_->gp_sessions_mutex);
+    }
+    LOG_D("session %x open", session.sid);
+    return ret;
+}
+
+int DriverClient::openTrustlet(struct mc_ioctl_open_trustlet& trustlet) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_OPEN_TRUSTLET, &trustlet);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    LOG_D("session %x open", trustlet.sid);
+    return ret;
+}
+
+int DriverClient::closeSession(uint32_t session_id) {
+    LOG_D("session %x close", session_id);
+    int ret = ::ioctl(pimpl_->fd, MC_IO_CLOSE_SESSION, session_id);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    pthread_mutex_lock(&pimpl_->gp_sessions_mutex);
+    for (auto it = pimpl_->gp_sessions.begin();
+            it != pimpl_->gp_sessions.end(); it++) {
+        auto gp_session = *it;
+        if (gp_session->id == session_id) {
+            pimpl_->gp_sessions.erase(it);
+            delete gp_session;
+            break;
+        }
+    }
+    pthread_mutex_unlock(&pimpl_->gp_sessions_mutex);
+    LOG_D("session %x closed", session_id);
+    return ret;
+}
+
+int DriverClient::notify(uint32_t session_id) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_NOTIFY, session_id);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    LOG_D("session %x notification sent", session_id);
+    return ret;
+}
+
+int DriverClient::waitNotification(const struct mc_ioctl_wait& wait) {
+    LOG_D("session %x wait for notification", wait.sid);
+    int ret = ::ioctl(pimpl_->fd, MC_IO_WAIT, &wait);
+    if (ret && ((errno != ETIME) || !wait.partial)) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    LOG_D("session %x notification received", wait.sid);
+    return ret;
+}
+
+int DriverClient::malloc(uint8_t** buffer, uint32_t length) {
+    *buffer = static_cast<uint8_t*>(mmap(0, length, PROT_READ | PROT_WRITE,
+                                         MAP_SHARED, pimpl_->fd, 0));
+    if (*buffer == MAP_FAILED) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return -1;
+    }
+    return 0;
+}
+
+int DriverClient::free(uint8_t* buffer, uint32_t length) {
+    int ret = munmap(buffer, length);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+    }
+    return ret;
+}
+
+int DriverClient::map(struct mc_ioctl_map& map) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_MAP, &map);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    LOG_D("session %x buffer(s) mapped", map.sid);
+    return ret;
+}
+
+int DriverClient::unmap(const struct mc_ioctl_map& map) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_UNMAP, &map);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    LOG_D("session %x buffer(s) unmapped", map.sid);
+    return ret;
+}
+
+int DriverClient::getError(struct mc_ioctl_geterr& err) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_ERR, &err);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+        return ret;
+    }
+    LOG_D("session %x exit code %d", err.sid, err.value);
+    return ret;
+}
+
+int DriverClient::getVersion(struct mc_version_info& version_info) {
+    int ret = ::ioctl(pimpl_->fd, MC_IO_VERSION, &version_info);
+    if (ret) {
+        _LOG_E("%s in %s", strerror(errno), __FUNCTION__);
+    }
+    return ret;
+}
+
+// This class will need to handle the GP protocol at some point, but for now it
+// only deals with cancellation
+int DriverClient::gpRequestCancellation(uint32_t session_id) {
+    bool found = false;
+    pthread_mutex_lock(&pimpl_->gp_sessions_mutex);
+    for (auto it = pimpl_->gp_sessions.begin(); it != pimpl_->gp_sessions.end();
+            it++) {
+        auto gp_session = *it;
+        if (gp_session->id == session_id) {
+            // Will be reset by caller at next InvokeCommand
+            gp_session->tci->operation.isCancelled = true;
+            found = true;
+        }
+    }
+    pthread_mutex_unlock(&pimpl_->gp_sessions_mutex);
+    if (!found) {
+        errno = ENOENT;
+        return -1;
+    }
+    return notify(session_id);
+}
diff --git a/mobicore/ClientLib/src/driver_client.h b/mobicore/ClientLib/src/driver_client.h
new file mode 100644 (file)
index 0000000..6902714
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CLIENT_DRIVER_H__
+#define __CLIENT_DRIVER_H__
+
+#include "iclient.h"
+
+class DriverClient: public IClient {
+    struct Impl;
+    Impl* const pimpl_;
+public:
+    DriverClient();
+    ~DriverClient();
+    virtual int open();
+    virtual int close();
+    virtual bool isOpen() const;
+    virtual int hasOpenSessions() const;
+    virtual int openSession(struct mc_ioctl_open_session& session);
+    virtual int openTrustlet(struct mc_ioctl_open_trustlet& trustlet);
+    virtual int closeSession(uint32_t session_id);
+    virtual int notify(uint32_t session_id);
+    virtual int waitNotification(const struct mc_ioctl_wait& wait);
+    virtual int malloc(uint8_t** buffer, uint32_t length);
+    virtual int free(uint8_t* buffer, uint32_t length);
+    virtual int map(struct mc_ioctl_map& map);
+    virtual int unmap(const struct mc_ioctl_map& map);
+    virtual int getError(struct mc_ioctl_geterr& err);
+    virtual int getVersion(struct mc_version_info& version_info);
+    virtual int gpRequestCancellation(uint32_t session_id);
+};
+
+#endif // __CLIENT_DRIVER_H__
diff --git a/mobicore/ClientLib/src/iclient.h b/mobicore/ClientLib/src/iclient.h
new file mode 100644 (file)
index 0000000..f95186c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CLIENT_INTERFACE_H__
+#define __CLIENT_INTERFACE_H__
+
+#include <stdint.h>     // *int*_t
+#include <sys/types.h>  // uid_t git_t
+#include "mc_user.h"    // ioctl structures
+
+class IClient {
+public:
+    virtual ~IClient() {}
+    virtual int open() = 0;
+    virtual int close() = 0;
+    virtual bool isOpen() const = 0;
+    // MC protocol, also used by GP for now
+    virtual int hasOpenSessions() const = 0;
+    virtual int openSession(struct mc_ioctl_open_session& session) = 0;
+    virtual int openTrustlet(struct mc_ioctl_open_trustlet& trustlet) = 0;
+    virtual int closeSession(uint32_t session_id) = 0;
+    virtual int notify(uint32_t session_id) = 0;
+    virtual int waitNotification(const struct mc_ioctl_wait& wait) = 0;
+    virtual int malloc(uint8_t** buffer, uint32_t length) = 0;
+    virtual int free(uint8_t* buffer, uint32_t length) = 0;
+    virtual int map(struct mc_ioctl_map& map) = 0;
+    virtual int unmap(const struct mc_ioctl_map& map) = 0;
+    virtual int getError(struct mc_ioctl_geterr& err) = 0;
+    virtual int getVersion(struct mc_version_info& version_info) = 0;
+    // GP protocol only
+    virtual int gpRequestCancellation(uint32_t session_id) = 0;
+};
+
+#endif // __CLIENT_INTERFACE_H__
diff --git a/mobicore/ClientLib/src/mc.pb.cpp b/mobicore/ClientLib/src/mc.pb.cpp
new file mode 100644 (file)
index 0000000..a36a527
--- /dev/null
@@ -0,0 +1,5695 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: mc.proto
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "mc.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace trustonic {
+namespace tee_proxy {
+
+void protobuf_ShutdownFile_mc_2eproto() {
+  delete OpenSessionRequest::default_instance_;
+  delete OpenSessionResponse::default_instance_;
+  delete OpenTrustletRequest::default_instance_;
+  delete OpenTrustletResponse::default_instance_;
+  delete CloseSessionRequest::default_instance_;
+  delete CloseSessionResponse::default_instance_;
+  delete NotifyRequest::default_instance_;
+  delete NotifyRequest_Buffers::default_instance_;
+  delete NotifyResponse::default_instance_;
+  delete WaitNotificationRequest::default_instance_;
+  delete WaitNotificationResponse::default_instance_;
+  delete WaitNotificationResponse_Buffers::default_instance_;
+  delete MapRequest::default_instance_;
+  delete MapRequest_Buffers::default_instance_;
+  delete MapResponse::default_instance_;
+  delete MapResponse_Buffers::default_instance_;
+  delete UnmapRequest::default_instance_;
+  delete UnmapRequest_Buffers::default_instance_;
+  delete UnmapResponse::default_instance_;
+  delete GetErrorRequest::default_instance_;
+  delete GetErrorResponse::default_instance_;
+  delete GetVersionRequest::default_instance_;
+  delete GetVersionResponse::default_instance_;
+  delete GpRequestCancellationRequest::default_instance_;
+  delete GpRequestCancellationResponse::default_instance_;
+}
+
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+void protobuf_AddDesc_mc_2eproto_impl() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#else
+void protobuf_AddDesc_mc_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+#endif
+  OpenSessionRequest::default_instance_ = new OpenSessionRequest();
+  OpenSessionResponse::default_instance_ = new OpenSessionResponse();
+  OpenTrustletRequest::default_instance_ = new OpenTrustletRequest();
+  OpenTrustletResponse::default_instance_ = new OpenTrustletResponse();
+  CloseSessionRequest::default_instance_ = new CloseSessionRequest();
+  CloseSessionResponse::default_instance_ = new CloseSessionResponse();
+  NotifyRequest::default_instance_ = new NotifyRequest();
+  NotifyRequest_Buffers::default_instance_ = new NotifyRequest_Buffers();
+  NotifyResponse::default_instance_ = new NotifyResponse();
+  WaitNotificationRequest::default_instance_ = new WaitNotificationRequest();
+  WaitNotificationResponse::default_instance_ = new WaitNotificationResponse();
+  WaitNotificationResponse_Buffers::default_instance_ = new WaitNotificationResponse_Buffers();
+  MapRequest::default_instance_ = new MapRequest();
+  MapRequest_Buffers::default_instance_ = new MapRequest_Buffers();
+  MapResponse::default_instance_ = new MapResponse();
+  MapResponse_Buffers::default_instance_ = new MapResponse_Buffers();
+  UnmapRequest::default_instance_ = new UnmapRequest();
+  UnmapRequest_Buffers::default_instance_ = new UnmapRequest_Buffers();
+  UnmapResponse::default_instance_ = new UnmapResponse();
+  GetErrorRequest::default_instance_ = new GetErrorRequest();
+  GetErrorResponse::default_instance_ = new GetErrorResponse();
+  GetVersionRequest::default_instance_ = new GetVersionRequest();
+  GetVersionResponse::default_instance_ = new GetVersionResponse();
+  GpRequestCancellationRequest::default_instance_ = new GpRequestCancellationRequest();
+  GpRequestCancellationResponse::default_instance_ = new GpRequestCancellationResponse();
+  OpenSessionRequest::default_instance_->InitAsDefaultInstance();
+  OpenSessionResponse::default_instance_->InitAsDefaultInstance();
+  OpenTrustletRequest::default_instance_->InitAsDefaultInstance();
+  OpenTrustletResponse::default_instance_->InitAsDefaultInstance();
+  CloseSessionRequest::default_instance_->InitAsDefaultInstance();
+  CloseSessionResponse::default_instance_->InitAsDefaultInstance();
+  NotifyRequest::default_instance_->InitAsDefaultInstance();
+  NotifyRequest_Buffers::default_instance_->InitAsDefaultInstance();
+  NotifyResponse::default_instance_->InitAsDefaultInstance();
+  WaitNotificationRequest::default_instance_->InitAsDefaultInstance();
+  WaitNotificationResponse::default_instance_->InitAsDefaultInstance();
+  WaitNotificationResponse_Buffers::default_instance_->InitAsDefaultInstance();
+  MapRequest::default_instance_->InitAsDefaultInstance();
+  MapRequest_Buffers::default_instance_->InitAsDefaultInstance();
+  MapResponse::default_instance_->InitAsDefaultInstance();
+  MapResponse_Buffers::default_instance_->InitAsDefaultInstance();
+  UnmapRequest::default_instance_->InitAsDefaultInstance();
+  UnmapRequest_Buffers::default_instance_->InitAsDefaultInstance();
+  UnmapResponse::default_instance_->InitAsDefaultInstance();
+  GetErrorRequest::default_instance_->InitAsDefaultInstance();
+  GetErrorResponse::default_instance_->InitAsDefaultInstance();
+  GetVersionRequest::default_instance_->InitAsDefaultInstance();
+  GetVersionResponse::default_instance_->InitAsDefaultInstance();
+  GpRequestCancellationRequest::default_instance_->InitAsDefaultInstance();
+  GpRequestCancellationResponse::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_mc_2eproto);
+}
+
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_mc_2eproto_once_);
+void protobuf_AddDesc_mc_2eproto() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_mc_2eproto_once_,
+                 &protobuf_AddDesc_mc_2eproto_impl);
+}
+#else
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_mc_2eproto {
+  StaticDescriptorInitializer_mc_2eproto() {
+    protobuf_AddDesc_mc_2eproto();
+  }
+} static_descriptor_initializer_mc_2eproto_;
+#endif
+bool LoginType_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 4:
+    case 5:
+    case 6:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int OpenSessionRequest::kUuidFieldNumber;
+const int OpenSessionRequest::kIsGpUuidFieldNumber;
+const int OpenSessionRequest::kTciFieldNumber;
+const int OpenSessionRequest::kLoginTypeFieldNumber;
+const int OpenSessionRequest::kLoginDataFieldNumber;
+#endif  // !_MSC_VER
+
+OpenSessionRequest::OpenSessionRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.OpenSessionRequest)
+}
+
+void OpenSessionRequest::InitAsDefaultInstance() {
+}
+
+OpenSessionRequest::OpenSessionRequest(const OpenSessionRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.OpenSessionRequest)
+}
+
+void OpenSessionRequest::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  uuid_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  is_gp_uuid_ = false;
+  tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  login_type_ = 0;
+  login_data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+OpenSessionRequest::~OpenSessionRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.OpenSessionRequest)
+  SharedDtor();
+}
+
+void OpenSessionRequest::SharedDtor() {
+  if (uuid_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete uuid_;
+  }
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  if (login_data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete login_data_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void OpenSessionRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const OpenSessionRequest& OpenSessionRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+OpenSessionRequest* OpenSessionRequest::default_instance_ = NULL;
+
+OpenSessionRequest* OpenSessionRequest::New() const {
+  return new OpenSessionRequest;
+}
+
+void OpenSessionRequest::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<OpenSessionRequest*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  if (_has_bits_[0 / 32] & 31) {
+    ZR_(is_gp_uuid_, login_type_);
+    if (has_uuid()) {
+      if (uuid_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        uuid_->clear();
+      }
+    }
+    if (has_tci()) {
+      if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        tci_->clear();
+      }
+    }
+    if (has_login_data()) {
+      if (login_data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        login_data_->clear();
+      }
+    }
+  }
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool OpenSessionRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.OpenSessionRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required bytes uuid = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_is_gp_uuid;
+        break;
+      }
+
+      // required bool is_gp_uuid = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_is_gp_uuid:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is_gp_uuid_)));
+          set_has_is_gp_uuid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_tci;
+        break;
+      }
+
+      // optional bytes tci = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_tci:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_tci()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(32)) goto parse_login_type;
+        break;
+      }
+
+      // required .com.trustonic.tee_proxy.LoginType login_type = 4;
+      case 4: {
+        if (tag == 32) {
+         parse_login_type:
+          int value;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          if (::com::trustonic::tee_proxy::LoginType_IsValid(value)) {
+            set_login_type(static_cast< ::com::trustonic::tee_proxy::LoginType >(value));
+          } else {
+            unknown_fields_stream.WriteVarint32(tag);
+            unknown_fields_stream.WriteVarint32(value);
+          }
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(42)) goto parse_login_data;
+        break;
+      }
+
+      // required bytes login_data = 5;
+      case 5: {
+        if (tag == 42) {
+         parse_login_data:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_login_data()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.OpenSessionRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.OpenSessionRequest)
+  return false;
+#undef DO_
+}
+
+void OpenSessionRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.OpenSessionRequest)
+  // required bytes uuid = 1;
+  if (has_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      1, this->uuid(), output);
+  }
+
+  // required bool is_gp_uuid = 2;
+  if (has_is_gp_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_gp_uuid(), output);
+  }
+
+  // optional bytes tci = 3;
+  if (has_tci()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      3, this->tci(), output);
+  }
+
+  // required .com.trustonic.tee_proxy.LoginType login_type = 4;
+  if (has_login_type()) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      4, this->login_type(), output);
+  }
+
+  // required bytes login_data = 5;
+  if (has_login_data()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      5, this->login_data(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.OpenSessionRequest)
+}
+
+int OpenSessionRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required bytes uuid = 1;
+    if (has_uuid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->uuid());
+    }
+
+    // required bool is_gp_uuid = 2;
+    if (has_is_gp_uuid()) {
+      total_size += 1 + 1;
+    }
+
+    // optional bytes tci = 3;
+    if (has_tci()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->tci());
+    }
+
+    // required .com.trustonic.tee_proxy.LoginType login_type = 4;
+    if (has_login_type()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->login_type());
+    }
+
+    // required bytes login_data = 5;
+    if (has_login_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->login_data());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void OpenSessionRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const OpenSessionRequest*>(&from));
+}
+
+void OpenSessionRequest::MergeFrom(const OpenSessionRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_uuid()) {
+      set_uuid(from.uuid());
+    }
+    if (from.has_is_gp_uuid()) {
+      set_is_gp_uuid(from.is_gp_uuid());
+    }
+    if (from.has_tci()) {
+      set_tci(from.tci());
+    }
+    if (from.has_login_type()) {
+      set_login_type(from.login_type());
+    }
+    if (from.has_login_data()) {
+      set_login_data(from.login_data());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void OpenSessionRequest::CopyFrom(const OpenSessionRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool OpenSessionRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x0000001b) != 0x0000001b) return false;
+
+  return true;
+}
+
+void OpenSessionRequest::Swap(OpenSessionRequest* other) {
+  if (other != this) {
+    std::swap(uuid_, other->uuid_);
+    std::swap(is_gp_uuid_, other->is_gp_uuid_);
+    std::swap(tci_, other->tci_);
+    std::swap(login_type_, other->login_type_);
+    std::swap(login_data_, other->login_data_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string OpenSessionRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.OpenSessionRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int OpenSessionResponse::kIdFieldNumber;
+#endif  // !_MSC_VER
+
+OpenSessionResponse::OpenSessionResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.OpenSessionResponse)
+}
+
+void OpenSessionResponse::InitAsDefaultInstance() {
+}
+
+OpenSessionResponse::OpenSessionResponse(const OpenSessionResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.OpenSessionResponse)
+}
+
+void OpenSessionResponse::SharedCtor() {
+  _cached_size_ = 0;
+  id_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+OpenSessionResponse::~OpenSessionResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.OpenSessionResponse)
+  SharedDtor();
+}
+
+void OpenSessionResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void OpenSessionResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const OpenSessionResponse& OpenSessionResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+OpenSessionResponse* OpenSessionResponse::default_instance_ = NULL;
+
+OpenSessionResponse* OpenSessionResponse::New() const {
+  return new OpenSessionResponse;
+}
+
+void OpenSessionResponse::Clear() {
+  id_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool OpenSessionResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.OpenSessionResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 id = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &id_)));
+          set_has_id();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.OpenSessionResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.OpenSessionResponse)
+  return false;
+#undef DO_
+}
+
+void OpenSessionResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.OpenSessionResponse)
+  // required uint32 id = 1;
+  if (has_id()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->id(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.OpenSessionResponse)
+}
+
+int OpenSessionResponse::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 id = 1;
+    if (has_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->id());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void OpenSessionResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const OpenSessionResponse*>(&from));
+}
+
+void OpenSessionResponse::MergeFrom(const OpenSessionResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_id()) {
+      set_id(from.id());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void OpenSessionResponse::CopyFrom(const OpenSessionResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool OpenSessionResponse::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void OpenSessionResponse::Swap(OpenSessionResponse* other) {
+  if (other != this) {
+    std::swap(id_, other->id_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string OpenSessionResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.OpenSessionResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int OpenTrustletRequest::kSpidFieldNumber;
+const int OpenTrustletRequest::kTrustappFieldNumber;
+const int OpenTrustletRequest::kTciFieldNumber;
+#endif  // !_MSC_VER
+
+OpenTrustletRequest::OpenTrustletRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.OpenTrustletRequest)
+}
+
+void OpenTrustletRequest::InitAsDefaultInstance() {
+}
+
+OpenTrustletRequest::OpenTrustletRequest(const OpenTrustletRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.OpenTrustletRequest)
+}
+
+void OpenTrustletRequest::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  spid_ = 0u;
+  trustapp_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+OpenTrustletRequest::~OpenTrustletRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.OpenTrustletRequest)
+  SharedDtor();
+}
+
+void OpenTrustletRequest::SharedDtor() {
+  if (trustapp_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete trustapp_;
+  }
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void OpenTrustletRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const OpenTrustletRequest& OpenTrustletRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+OpenTrustletRequest* OpenTrustletRequest::default_instance_ = NULL;
+
+OpenTrustletRequest* OpenTrustletRequest::New() const {
+  return new OpenTrustletRequest;
+}
+
+void OpenTrustletRequest::Clear() {
+  if (_has_bits_[0 / 32] & 7) {
+    spid_ = 0u;
+    if (has_trustapp()) {
+      if (trustapp_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        trustapp_->clear();
+      }
+    }
+    if (has_tci()) {
+      if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        tci_->clear();
+      }
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool OpenTrustletRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.OpenTrustletRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 spid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &spid_)));
+          set_has_spid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_trustapp;
+        break;
+      }
+
+      // required bytes trustapp = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_trustapp:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_trustapp()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_tci;
+        break;
+      }
+
+      // optional bytes tci = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_tci:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_tci()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.OpenTrustletRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.OpenTrustletRequest)
+  return false;
+#undef DO_
+}
+
+void OpenTrustletRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.OpenTrustletRequest)
+  // required uint32 spid = 1;
+  if (has_spid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->spid(), output);
+  }
+
+  // required bytes trustapp = 2;
+  if (has_trustapp()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      2, this->trustapp(), output);
+  }
+
+  // optional bytes tci = 3;
+  if (has_tci()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      3, this->tci(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.OpenTrustletRequest)
+}
+
+int OpenTrustletRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 spid = 1;
+    if (has_spid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->spid());
+    }
+
+    // required bytes trustapp = 2;
+    if (has_trustapp()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->trustapp());
+    }
+
+    // optional bytes tci = 3;
+    if (has_tci()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->tci());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void OpenTrustletRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const OpenTrustletRequest*>(&from));
+}
+
+void OpenTrustletRequest::MergeFrom(const OpenTrustletRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_spid()) {
+      set_spid(from.spid());
+    }
+    if (from.has_trustapp()) {
+      set_trustapp(from.trustapp());
+    }
+    if (from.has_tci()) {
+      set_tci(from.tci());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void OpenTrustletRequest::CopyFrom(const OpenTrustletRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool OpenTrustletRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+  return true;
+}
+
+void OpenTrustletRequest::Swap(OpenTrustletRequest* other) {
+  if (other != this) {
+    std::swap(spid_, other->spid_);
+    std::swap(trustapp_, other->trustapp_);
+    std::swap(tci_, other->tci_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string OpenTrustletRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.OpenTrustletRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int OpenTrustletResponse::kIdFieldNumber;
+#endif  // !_MSC_VER
+
+OpenTrustletResponse::OpenTrustletResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.OpenTrustletResponse)
+}
+
+void OpenTrustletResponse::InitAsDefaultInstance() {
+}
+
+OpenTrustletResponse::OpenTrustletResponse(const OpenTrustletResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.OpenTrustletResponse)
+}
+
+void OpenTrustletResponse::SharedCtor() {
+  _cached_size_ = 0;
+  id_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+OpenTrustletResponse::~OpenTrustletResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.OpenTrustletResponse)
+  SharedDtor();
+}
+
+void OpenTrustletResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void OpenTrustletResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const OpenTrustletResponse& OpenTrustletResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+OpenTrustletResponse* OpenTrustletResponse::default_instance_ = NULL;
+
+OpenTrustletResponse* OpenTrustletResponse::New() const {
+  return new OpenTrustletResponse;
+}
+
+void OpenTrustletResponse::Clear() {
+  id_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool OpenTrustletResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.OpenTrustletResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 id = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &id_)));
+          set_has_id();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.OpenTrustletResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.OpenTrustletResponse)
+  return false;
+#undef DO_
+}
+
+void OpenTrustletResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.OpenTrustletResponse)
+  // required uint32 id = 1;
+  if (has_id()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->id(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.OpenTrustletResponse)
+}
+
+int OpenTrustletResponse::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 id = 1;
+    if (has_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->id());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void OpenTrustletResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const OpenTrustletResponse*>(&from));
+}
+
+void OpenTrustletResponse::MergeFrom(const OpenTrustletResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_id()) {
+      set_id(from.id());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void OpenTrustletResponse::CopyFrom(const OpenTrustletResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool OpenTrustletResponse::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void OpenTrustletResponse::Swap(OpenTrustletResponse* other) {
+  if (other != this) {
+    std::swap(id_, other->id_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string OpenTrustletResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.OpenTrustletResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int CloseSessionRequest::kIdFieldNumber;
+#endif  // !_MSC_VER
+
+CloseSessionRequest::CloseSessionRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.CloseSessionRequest)
+}
+
+void CloseSessionRequest::InitAsDefaultInstance() {
+}
+
+CloseSessionRequest::CloseSessionRequest(const CloseSessionRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.CloseSessionRequest)
+}
+
+void CloseSessionRequest::SharedCtor() {
+  _cached_size_ = 0;
+  id_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CloseSessionRequest::~CloseSessionRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.CloseSessionRequest)
+  SharedDtor();
+}
+
+void CloseSessionRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void CloseSessionRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const CloseSessionRequest& CloseSessionRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+CloseSessionRequest* CloseSessionRequest::default_instance_ = NULL;
+
+CloseSessionRequest* CloseSessionRequest::New() const {
+  return new CloseSessionRequest;
+}
+
+void CloseSessionRequest::Clear() {
+  id_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool CloseSessionRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.CloseSessionRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 id = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &id_)));
+          set_has_id();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.CloseSessionRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.CloseSessionRequest)
+  return false;
+#undef DO_
+}
+
+void CloseSessionRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.CloseSessionRequest)
+  // required uint32 id = 1;
+  if (has_id()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->id(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.CloseSessionRequest)
+}
+
+int CloseSessionRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 id = 1;
+    if (has_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->id());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CloseSessionRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const CloseSessionRequest*>(&from));
+}
+
+void CloseSessionRequest::MergeFrom(const CloseSessionRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_id()) {
+      set_id(from.id());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void CloseSessionRequest::CopyFrom(const CloseSessionRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CloseSessionRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void CloseSessionRequest::Swap(CloseSessionRequest* other) {
+  if (other != this) {
+    std::swap(id_, other->id_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string CloseSessionRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.CloseSessionRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+#endif  // !_MSC_VER
+
+CloseSessionResponse::CloseSessionResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.CloseSessionResponse)
+}
+
+void CloseSessionResponse::InitAsDefaultInstance() {
+}
+
+CloseSessionResponse::CloseSessionResponse(const CloseSessionResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.CloseSessionResponse)
+}
+
+void CloseSessionResponse::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CloseSessionResponse::~CloseSessionResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.CloseSessionResponse)
+  SharedDtor();
+}
+
+void CloseSessionResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void CloseSessionResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const CloseSessionResponse& CloseSessionResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+CloseSessionResponse* CloseSessionResponse::default_instance_ = NULL;
+
+CloseSessionResponse* CloseSessionResponse::New() const {
+  return new CloseSessionResponse;
+}
+
+void CloseSessionResponse::Clear() {
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool CloseSessionResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.CloseSessionResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+  handle_unusual:
+    if (tag == 0 ||
+        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+      goto success;
+    }
+    DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+        input, tag, &unknown_fields_stream));
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.CloseSessionResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.CloseSessionResponse)
+  return false;
+#undef DO_
+}
+
+void CloseSessionResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.CloseSessionResponse)
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.CloseSessionResponse)
+}
+
+int CloseSessionResponse::ByteSize() const {
+  int total_size = 0;
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CloseSessionResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const CloseSessionResponse*>(&from));
+}
+
+void CloseSessionResponse::MergeFrom(const CloseSessionResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void CloseSessionResponse::CopyFrom(const CloseSessionResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CloseSessionResponse::IsInitialized() const {
+
+  return true;
+}
+
+void CloseSessionResponse::Swap(CloseSessionResponse* other) {
+  if (other != this) {
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string CloseSessionResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.CloseSessionResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int NotifyRequest_Buffers::kSvaFieldNumber;
+const int NotifyRequest_Buffers::kDataFieldNumber;
+#endif  // !_MSC_VER
+
+NotifyRequest_Buffers::NotifyRequest_Buffers()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+}
+
+void NotifyRequest_Buffers::InitAsDefaultInstance() {
+}
+
+NotifyRequest_Buffers::NotifyRequest_Buffers(const NotifyRequest_Buffers& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+}
+
+void NotifyRequest_Buffers::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  sva_ = GOOGLE_ULONGLONG(0);
+  data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+NotifyRequest_Buffers::~NotifyRequest_Buffers() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+  SharedDtor();
+}
+
+void NotifyRequest_Buffers::SharedDtor() {
+  if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete data_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void NotifyRequest_Buffers::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const NotifyRequest_Buffers& NotifyRequest_Buffers::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+NotifyRequest_Buffers* NotifyRequest_Buffers::default_instance_ = NULL;
+
+NotifyRequest_Buffers* NotifyRequest_Buffers::New() const {
+  return new NotifyRequest_Buffers;
+}
+
+void NotifyRequest_Buffers::Clear() {
+  if (_has_bits_[0 / 32] & 3) {
+    sva_ = GOOGLE_ULONGLONG(0);
+    if (has_data()) {
+      if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        data_->clear();
+      }
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool NotifyRequest_Buffers::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint64 sva = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &sva_)));
+          set_has_sva();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_data;
+        break;
+      }
+
+      // required bytes data = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_data:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_data()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+  return false;
+#undef DO_
+}
+
+void NotifyRequest_Buffers::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+  // required uint64 sva = 1;
+  if (has_sva()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->sva(), output);
+  }
+
+  // required bytes data = 2;
+  if (has_data()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      2, this->data(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+}
+
+int NotifyRequest_Buffers::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint64 sva = 1;
+    if (has_sva()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->sva());
+    }
+
+    // required bytes data = 2;
+    if (has_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->data());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void NotifyRequest_Buffers::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const NotifyRequest_Buffers*>(&from));
+}
+
+void NotifyRequest_Buffers::MergeFrom(const NotifyRequest_Buffers& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sva()) {
+      set_sva(from.sva());
+    }
+    if (from.has_data()) {
+      set_data(from.data());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void NotifyRequest_Buffers::CopyFrom(const NotifyRequest_Buffers& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool NotifyRequest_Buffers::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+  return true;
+}
+
+void NotifyRequest_Buffers::Swap(NotifyRequest_Buffers* other) {
+  if (other != this) {
+    std::swap(sva_, other->sva_);
+    std::swap(data_, other->data_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string NotifyRequest_Buffers::GetTypeName() const {
+  return "com.trustonic.tee_proxy.NotifyRequest.Buffers";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int NotifyRequest::kSidFieldNumber;
+const int NotifyRequest::kTciFieldNumber;
+const int NotifyRequest::kBuffersFieldNumber;
+#endif  // !_MSC_VER
+
+NotifyRequest::NotifyRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.NotifyRequest)
+}
+
+void NotifyRequest::InitAsDefaultInstance() {
+}
+
+NotifyRequest::NotifyRequest(const NotifyRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.NotifyRequest)
+}
+
+void NotifyRequest::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  sid_ = 0u;
+  tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+NotifyRequest::~NotifyRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.NotifyRequest)
+  SharedDtor();
+}
+
+void NotifyRequest::SharedDtor() {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void NotifyRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const NotifyRequest& NotifyRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+NotifyRequest* NotifyRequest::default_instance_ = NULL;
+
+NotifyRequest* NotifyRequest::New() const {
+  return new NotifyRequest;
+}
+
+void NotifyRequest::Clear() {
+  if (_has_bits_[0 / 32] & 3) {
+    sid_ = 0u;
+    if (has_tci()) {
+      if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        tci_->clear();
+      }
+    }
+  }
+  buffers_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool NotifyRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.NotifyRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 sid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &sid_)));
+          set_has_sid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_tci;
+        break;
+      }
+
+      // optional bytes tci = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_tci:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_tci()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_buffers;
+        break;
+      }
+
+      // repeated .com.trustonic.tee_proxy.NotifyRequest.Buffers buffers = 3;
+      case 3: {
+        if (tag == 26) {
+         parse_buffers:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_buffers()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(26)) goto parse_buffers;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.NotifyRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.NotifyRequest)
+  return false;
+#undef DO_
+}
+
+void NotifyRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.NotifyRequest)
+  // required uint32 sid = 1;
+  if (has_sid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->sid(), output);
+  }
+
+  // optional bytes tci = 2;
+  if (has_tci()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      2, this->tci(), output);
+  }
+
+  // repeated .com.trustonic.tee_proxy.NotifyRequest.Buffers buffers = 3;
+  for (int i = 0; i < this->buffers_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      3, this->buffers(i), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.NotifyRequest)
+}
+
+int NotifyRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 sid = 1;
+    if (has_sid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->sid());
+    }
+
+    // optional bytes tci = 2;
+    if (has_tci()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->tci());
+    }
+
+  }
+  // repeated .com.trustonic.tee_proxy.NotifyRequest.Buffers buffers = 3;
+  total_size += 1 * this->buffers_size();
+  for (int i = 0; i < this->buffers_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->buffers(i));
+  }
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void NotifyRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const NotifyRequest*>(&from));
+}
+
+void NotifyRequest::MergeFrom(const NotifyRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  buffers_.MergeFrom(from.buffers_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sid()) {
+      set_sid(from.sid());
+    }
+    if (from.has_tci()) {
+      set_tci(from.tci());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void NotifyRequest::CopyFrom(const NotifyRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool NotifyRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->buffers())) return false;
+  return true;
+}
+
+void NotifyRequest::Swap(NotifyRequest* other) {
+  if (other != this) {
+    std::swap(sid_, other->sid_);
+    std::swap(tci_, other->tci_);
+    buffers_.Swap(&other->buffers_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string NotifyRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.NotifyRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+#endif  // !_MSC_VER
+
+NotifyResponse::NotifyResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.NotifyResponse)
+}
+
+void NotifyResponse::InitAsDefaultInstance() {
+}
+
+NotifyResponse::NotifyResponse(const NotifyResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.NotifyResponse)
+}
+
+void NotifyResponse::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+NotifyResponse::~NotifyResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.NotifyResponse)
+  SharedDtor();
+}
+
+void NotifyResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void NotifyResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const NotifyResponse& NotifyResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+NotifyResponse* NotifyResponse::default_instance_ = NULL;
+
+NotifyResponse* NotifyResponse::New() const {
+  return new NotifyResponse;
+}
+
+void NotifyResponse::Clear() {
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool NotifyResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.NotifyResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+  handle_unusual:
+    if (tag == 0 ||
+        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+      goto success;
+    }
+    DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+        input, tag, &unknown_fields_stream));
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.NotifyResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.NotifyResponse)
+  return false;
+#undef DO_
+}
+
+void NotifyResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.NotifyResponse)
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.NotifyResponse)
+}
+
+int NotifyResponse::ByteSize() const {
+  int total_size = 0;
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void NotifyResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const NotifyResponse*>(&from));
+}
+
+void NotifyResponse::MergeFrom(const NotifyResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void NotifyResponse::CopyFrom(const NotifyResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool NotifyResponse::IsInitialized() const {
+
+  return true;
+}
+
+void NotifyResponse::Swap(NotifyResponse* other) {
+  if (other != this) {
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string NotifyResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.NotifyResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int WaitNotificationRequest::kSidFieldNumber;
+const int WaitNotificationRequest::kTimeoutFieldNumber;
+const int WaitNotificationRequest::kPartialFieldNumber;
+#endif  // !_MSC_VER
+
+WaitNotificationRequest::WaitNotificationRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.WaitNotificationRequest)
+}
+
+void WaitNotificationRequest::InitAsDefaultInstance() {
+}
+
+WaitNotificationRequest::WaitNotificationRequest(const WaitNotificationRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.WaitNotificationRequest)
+}
+
+void WaitNotificationRequest::SharedCtor() {
+  _cached_size_ = 0;
+  sid_ = 0u;
+  timeout_ = 0;
+  partial_ = false;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+WaitNotificationRequest::~WaitNotificationRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.WaitNotificationRequest)
+  SharedDtor();
+}
+
+void WaitNotificationRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void WaitNotificationRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const WaitNotificationRequest& WaitNotificationRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+WaitNotificationRequest* WaitNotificationRequest::default_instance_ = NULL;
+
+WaitNotificationRequest* WaitNotificationRequest::New() const {
+  return new WaitNotificationRequest;
+}
+
+void WaitNotificationRequest::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<WaitNotificationRequest*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  ZR_(sid_, partial_);
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool WaitNotificationRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.WaitNotificationRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 sid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &sid_)));
+          set_has_sid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_timeout;
+        break;
+      }
+
+      // required sint32 timeout = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_timeout:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_SINT32>(
+                 input, &timeout_)));
+          set_has_timeout();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_partial;
+        break;
+      }
+
+      // required bool partial = 3;
+      case 3: {
+        if (tag == 24) {
+         parse_partial:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &partial_)));
+          set_has_partial();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.WaitNotificationRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.WaitNotificationRequest)
+  return false;
+#undef DO_
+}
+
+void WaitNotificationRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.WaitNotificationRequest)
+  // required uint32 sid = 1;
+  if (has_sid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->sid(), output);
+  }
+
+  // required sint32 timeout = 2;
+  if (has_timeout()) {
+    ::google::protobuf::internal::WireFormatLite::WriteSInt32(2, this->timeout(), output);
+  }
+
+  // required bool partial = 3;
+  if (has_partial()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->partial(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.WaitNotificationRequest)
+}
+
+int WaitNotificationRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 sid = 1;
+    if (has_sid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->sid());
+    }
+
+    // required sint32 timeout = 2;
+    if (has_timeout()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::SInt32Size(
+          this->timeout());
+    }
+
+    // required bool partial = 3;
+    if (has_partial()) {
+      total_size += 1 + 1;
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void WaitNotificationRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const WaitNotificationRequest*>(&from));
+}
+
+void WaitNotificationRequest::MergeFrom(const WaitNotificationRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sid()) {
+      set_sid(from.sid());
+    }
+    if (from.has_timeout()) {
+      set_timeout(from.timeout());
+    }
+    if (from.has_partial()) {
+      set_partial(from.partial());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void WaitNotificationRequest::CopyFrom(const WaitNotificationRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool WaitNotificationRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false;
+
+  return true;
+}
+
+void WaitNotificationRequest::Swap(WaitNotificationRequest* other) {
+  if (other != this) {
+    std::swap(sid_, other->sid_);
+    std::swap(timeout_, other->timeout_);
+    std::swap(partial_, other->partial_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string WaitNotificationRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.WaitNotificationRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int WaitNotificationResponse_Buffers::kSvaFieldNumber;
+const int WaitNotificationResponse_Buffers::kDataFieldNumber;
+#endif  // !_MSC_VER
+
+WaitNotificationResponse_Buffers::WaitNotificationResponse_Buffers()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+}
+
+void WaitNotificationResponse_Buffers::InitAsDefaultInstance() {
+}
+
+WaitNotificationResponse_Buffers::WaitNotificationResponse_Buffers(const WaitNotificationResponse_Buffers& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+}
+
+void WaitNotificationResponse_Buffers::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  sva_ = GOOGLE_ULONGLONG(0);
+  data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+WaitNotificationResponse_Buffers::~WaitNotificationResponse_Buffers() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+  SharedDtor();
+}
+
+void WaitNotificationResponse_Buffers::SharedDtor() {
+  if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete data_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void WaitNotificationResponse_Buffers::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const WaitNotificationResponse_Buffers& WaitNotificationResponse_Buffers::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+WaitNotificationResponse_Buffers* WaitNotificationResponse_Buffers::default_instance_ = NULL;
+
+WaitNotificationResponse_Buffers* WaitNotificationResponse_Buffers::New() const {
+  return new WaitNotificationResponse_Buffers;
+}
+
+void WaitNotificationResponse_Buffers::Clear() {
+  if (_has_bits_[0 / 32] & 3) {
+    sva_ = GOOGLE_ULONGLONG(0);
+    if (has_data()) {
+      if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        data_->clear();
+      }
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool WaitNotificationResponse_Buffers::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint64 sva = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &sva_)));
+          set_has_sva();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_data;
+        break;
+      }
+
+      // required bytes data = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_data:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_data()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+  return false;
+#undef DO_
+}
+
+void WaitNotificationResponse_Buffers::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+  // required uint64 sva = 1;
+  if (has_sva()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->sva(), output);
+  }
+
+  // required bytes data = 2;
+  if (has_data()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      2, this->data(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+}
+
+int WaitNotificationResponse_Buffers::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint64 sva = 1;
+    if (has_sva()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->sva());
+    }
+
+    // required bytes data = 2;
+    if (has_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->data());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void WaitNotificationResponse_Buffers::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const WaitNotificationResponse_Buffers*>(&from));
+}
+
+void WaitNotificationResponse_Buffers::MergeFrom(const WaitNotificationResponse_Buffers& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sva()) {
+      set_sva(from.sva());
+    }
+    if (from.has_data()) {
+      set_data(from.data());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void WaitNotificationResponse_Buffers::CopyFrom(const WaitNotificationResponse_Buffers& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool WaitNotificationResponse_Buffers::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+  return true;
+}
+
+void WaitNotificationResponse_Buffers::Swap(WaitNotificationResponse_Buffers* other) {
+  if (other != this) {
+    std::swap(sva_, other->sva_);
+    std::swap(data_, other->data_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string WaitNotificationResponse_Buffers::GetTypeName() const {
+  return "com.trustonic.tee_proxy.WaitNotificationResponse.Buffers";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int WaitNotificationResponse::kTciFieldNumber;
+const int WaitNotificationResponse::kBuffersFieldNumber;
+#endif  // !_MSC_VER
+
+WaitNotificationResponse::WaitNotificationResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.WaitNotificationResponse)
+}
+
+void WaitNotificationResponse::InitAsDefaultInstance() {
+}
+
+WaitNotificationResponse::WaitNotificationResponse(const WaitNotificationResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.WaitNotificationResponse)
+}
+
+void WaitNotificationResponse::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+WaitNotificationResponse::~WaitNotificationResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.WaitNotificationResponse)
+  SharedDtor();
+}
+
+void WaitNotificationResponse::SharedDtor() {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void WaitNotificationResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const WaitNotificationResponse& WaitNotificationResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+WaitNotificationResponse* WaitNotificationResponse::default_instance_ = NULL;
+
+WaitNotificationResponse* WaitNotificationResponse::New() const {
+  return new WaitNotificationResponse;
+}
+
+void WaitNotificationResponse::Clear() {
+  if (has_tci()) {
+    if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+      tci_->clear();
+    }
+  }
+  buffers_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool WaitNotificationResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.WaitNotificationResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional bytes tci = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+                input, this->mutable_tci()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_buffers;
+        break;
+      }
+
+      // repeated .com.trustonic.tee_proxy.WaitNotificationResponse.Buffers buffers = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_buffers:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_buffers()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_buffers;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.WaitNotificationResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.WaitNotificationResponse)
+  return false;
+#undef DO_
+}
+
+void WaitNotificationResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.WaitNotificationResponse)
+  // optional bytes tci = 1;
+  if (has_tci()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
+      1, this->tci(), output);
+  }
+
+  // repeated .com.trustonic.tee_proxy.WaitNotificationResponse.Buffers buffers = 2;
+  for (int i = 0; i < this->buffers_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      2, this->buffers(i), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.WaitNotificationResponse)
+}
+
+int WaitNotificationResponse::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional bytes tci = 1;
+    if (has_tci()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->tci());
+    }
+
+  }
+  // repeated .com.trustonic.tee_proxy.WaitNotificationResponse.Buffers buffers = 2;
+  total_size += 1 * this->buffers_size();
+  for (int i = 0; i < this->buffers_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->buffers(i));
+  }
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void WaitNotificationResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const WaitNotificationResponse*>(&from));
+}
+
+void WaitNotificationResponse::MergeFrom(const WaitNotificationResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  buffers_.MergeFrom(from.buffers_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_tci()) {
+      set_tci(from.tci());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void WaitNotificationResponse::CopyFrom(const WaitNotificationResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool WaitNotificationResponse::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->buffers())) return false;
+  return true;
+}
+
+void WaitNotificationResponse::Swap(WaitNotificationResponse* other) {
+  if (other != this) {
+    std::swap(tci_, other->tci_);
+    buffers_.Swap(&other->buffers_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string WaitNotificationResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.WaitNotificationResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int MapRequest_Buffers::kLenFieldNumber;
+const int MapRequest_Buffers::kFlagsFieldNumber;
+#endif  // !_MSC_VER
+
+MapRequest_Buffers::MapRequest_Buffers()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.MapRequest.Buffers)
+}
+
+void MapRequest_Buffers::InitAsDefaultInstance() {
+}
+
+MapRequest_Buffers::MapRequest_Buffers(const MapRequest_Buffers& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.MapRequest.Buffers)
+}
+
+void MapRequest_Buffers::SharedCtor() {
+  _cached_size_ = 0;
+  len_ = 0u;
+  flags_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MapRequest_Buffers::~MapRequest_Buffers() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.MapRequest.Buffers)
+  SharedDtor();
+}
+
+void MapRequest_Buffers::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void MapRequest_Buffers::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const MapRequest_Buffers& MapRequest_Buffers::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+MapRequest_Buffers* MapRequest_Buffers::default_instance_ = NULL;
+
+MapRequest_Buffers* MapRequest_Buffers::New() const {
+  return new MapRequest_Buffers;
+}
+
+void MapRequest_Buffers::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<MapRequest_Buffers*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  ZR_(len_, flags_);
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool MapRequest_Buffers::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.MapRequest.Buffers)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 len = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &len_)));
+          set_has_len();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_flags;
+        break;
+      }
+
+      // required uint32 flags = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_flags:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &flags_)));
+          set_has_flags();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.MapRequest.Buffers)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.MapRequest.Buffers)
+  return false;
+#undef DO_
+}
+
+void MapRequest_Buffers::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.MapRequest.Buffers)
+  // required uint32 len = 1;
+  if (has_len()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->len(), output);
+  }
+
+  // required uint32 flags = 2;
+  if (has_flags()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->flags(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.MapRequest.Buffers)
+}
+
+int MapRequest_Buffers::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 len = 1;
+    if (has_len()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->len());
+    }
+
+    // required uint32 flags = 2;
+    if (has_flags()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->flags());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MapRequest_Buffers::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const MapRequest_Buffers*>(&from));
+}
+
+void MapRequest_Buffers::MergeFrom(const MapRequest_Buffers& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_len()) {
+      set_len(from.len());
+    }
+    if (from.has_flags()) {
+      set_flags(from.flags());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void MapRequest_Buffers::CopyFrom(const MapRequest_Buffers& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MapRequest_Buffers::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false;
+
+  return true;
+}
+
+void MapRequest_Buffers::Swap(MapRequest_Buffers* other) {
+  if (other != this) {
+    std::swap(len_, other->len_);
+    std::swap(flags_, other->flags_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string MapRequest_Buffers::GetTypeName() const {
+  return "com.trustonic.tee_proxy.MapRequest.Buffers";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int MapRequest::kSidFieldNumber;
+const int MapRequest::kBuffersFieldNumber;
+#endif  // !_MSC_VER
+
+MapRequest::MapRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.MapRequest)
+}
+
+void MapRequest::InitAsDefaultInstance() {
+}
+
+MapRequest::MapRequest(const MapRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.MapRequest)
+}
+
+void MapRequest::SharedCtor() {
+  _cached_size_ = 0;
+  sid_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MapRequest::~MapRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.MapRequest)
+  SharedDtor();
+}
+
+void MapRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void MapRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const MapRequest& MapRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+MapRequest* MapRequest::default_instance_ = NULL;
+
+MapRequest* MapRequest::New() const {
+  return new MapRequest;
+}
+
+void MapRequest::Clear() {
+  sid_ = 0u;
+  buffers_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool MapRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.MapRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 sid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &sid_)));
+          set_has_sid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_buffers;
+        break;
+      }
+
+      // repeated .com.trustonic.tee_proxy.MapRequest.Buffers buffers = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_buffers:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_buffers()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_buffers;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.MapRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.MapRequest)
+  return false;
+#undef DO_
+}
+
+void MapRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.MapRequest)
+  // required uint32 sid = 1;
+  if (has_sid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->sid(), output);
+  }
+
+  // repeated .com.trustonic.tee_proxy.MapRequest.Buffers buffers = 2;
+  for (int i = 0; i < this->buffers_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      2, this->buffers(i), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.MapRequest)
+}
+
+int MapRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 sid = 1;
+    if (has_sid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->sid());
+    }
+
+  }
+  // repeated .com.trustonic.tee_proxy.MapRequest.Buffers buffers = 2;
+  total_size += 1 * this->buffers_size();
+  for (int i = 0; i < this->buffers_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->buffers(i));
+  }
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MapRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const MapRequest*>(&from));
+}
+
+void MapRequest::MergeFrom(const MapRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  buffers_.MergeFrom(from.buffers_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sid()) {
+      set_sid(from.sid());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void MapRequest::CopyFrom(const MapRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MapRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->buffers())) return false;
+  return true;
+}
+
+void MapRequest::Swap(MapRequest* other) {
+  if (other != this) {
+    std::swap(sid_, other->sid_);
+    buffers_.Swap(&other->buffers_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string MapRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.MapRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int MapResponse_Buffers::kSvaFieldNumber;
+#endif  // !_MSC_VER
+
+MapResponse_Buffers::MapResponse_Buffers()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.MapResponse.Buffers)
+}
+
+void MapResponse_Buffers::InitAsDefaultInstance() {
+}
+
+MapResponse_Buffers::MapResponse_Buffers(const MapResponse_Buffers& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.MapResponse.Buffers)
+}
+
+void MapResponse_Buffers::SharedCtor() {
+  _cached_size_ = 0;
+  sva_ = GOOGLE_ULONGLONG(0);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MapResponse_Buffers::~MapResponse_Buffers() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.MapResponse.Buffers)
+  SharedDtor();
+}
+
+void MapResponse_Buffers::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void MapResponse_Buffers::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const MapResponse_Buffers& MapResponse_Buffers::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+MapResponse_Buffers* MapResponse_Buffers::default_instance_ = NULL;
+
+MapResponse_Buffers* MapResponse_Buffers::New() const {
+  return new MapResponse_Buffers;
+}
+
+void MapResponse_Buffers::Clear() {
+  sva_ = GOOGLE_ULONGLONG(0);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool MapResponse_Buffers::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.MapResponse.Buffers)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint64 sva = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &sva_)));
+          set_has_sva();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.MapResponse.Buffers)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.MapResponse.Buffers)
+  return false;
+#undef DO_
+}
+
+void MapResponse_Buffers::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.MapResponse.Buffers)
+  // required uint64 sva = 1;
+  if (has_sva()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->sva(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.MapResponse.Buffers)
+}
+
+int MapResponse_Buffers::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint64 sva = 1;
+    if (has_sva()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->sva());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MapResponse_Buffers::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const MapResponse_Buffers*>(&from));
+}
+
+void MapResponse_Buffers::MergeFrom(const MapResponse_Buffers& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sva()) {
+      set_sva(from.sva());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void MapResponse_Buffers::CopyFrom(const MapResponse_Buffers& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MapResponse_Buffers::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void MapResponse_Buffers::Swap(MapResponse_Buffers* other) {
+  if (other != this) {
+    std::swap(sva_, other->sva_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string MapResponse_Buffers::GetTypeName() const {
+  return "com.trustonic.tee_proxy.MapResponse.Buffers";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int MapResponse::kBuffersFieldNumber;
+#endif  // !_MSC_VER
+
+MapResponse::MapResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.MapResponse)
+}
+
+void MapResponse::InitAsDefaultInstance() {
+}
+
+MapResponse::MapResponse(const MapResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.MapResponse)
+}
+
+void MapResponse::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+MapResponse::~MapResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.MapResponse)
+  SharedDtor();
+}
+
+void MapResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void MapResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const MapResponse& MapResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+MapResponse* MapResponse::default_instance_ = NULL;
+
+MapResponse* MapResponse::New() const {
+  return new MapResponse;
+}
+
+void MapResponse::Clear() {
+  buffers_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool MapResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.MapResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .com.trustonic.tee_proxy.MapResponse.Buffers buffers = 1;
+      case 1: {
+        if (tag == 10) {
+         parse_buffers:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_buffers()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(10)) goto parse_buffers;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.MapResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.MapResponse)
+  return false;
+#undef DO_
+}
+
+void MapResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.MapResponse)
+  // repeated .com.trustonic.tee_proxy.MapResponse.Buffers buffers = 1;
+  for (int i = 0; i < this->buffers_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      1, this->buffers(i), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.MapResponse)
+}
+
+int MapResponse::ByteSize() const {
+  int total_size = 0;
+
+  // repeated .com.trustonic.tee_proxy.MapResponse.Buffers buffers = 1;
+  total_size += 1 * this->buffers_size();
+  for (int i = 0; i < this->buffers_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->buffers(i));
+  }
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void MapResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const MapResponse*>(&from));
+}
+
+void MapResponse::MergeFrom(const MapResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  buffers_.MergeFrom(from.buffers_);
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void MapResponse::CopyFrom(const MapResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MapResponse::IsInitialized() const {
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->buffers())) return false;
+  return true;
+}
+
+void MapResponse::Swap(MapResponse* other) {
+  if (other != this) {
+    buffers_.Swap(&other->buffers_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string MapResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.MapResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int UnmapRequest_Buffers::kSvaFieldNumber;
+#endif  // !_MSC_VER
+
+UnmapRequest_Buffers::UnmapRequest_Buffers()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+}
+
+void UnmapRequest_Buffers::InitAsDefaultInstance() {
+}
+
+UnmapRequest_Buffers::UnmapRequest_Buffers(const UnmapRequest_Buffers& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+}
+
+void UnmapRequest_Buffers::SharedCtor() {
+  _cached_size_ = 0;
+  sva_ = GOOGLE_ULONGLONG(0);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+UnmapRequest_Buffers::~UnmapRequest_Buffers() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+  SharedDtor();
+}
+
+void UnmapRequest_Buffers::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void UnmapRequest_Buffers::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const UnmapRequest_Buffers& UnmapRequest_Buffers::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+UnmapRequest_Buffers* UnmapRequest_Buffers::default_instance_ = NULL;
+
+UnmapRequest_Buffers* UnmapRequest_Buffers::New() const {
+  return new UnmapRequest_Buffers;
+}
+
+void UnmapRequest_Buffers::Clear() {
+  sva_ = GOOGLE_ULONGLONG(0);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool UnmapRequest_Buffers::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint64 sva = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &sva_)));
+          set_has_sva();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+  return false;
+#undef DO_
+}
+
+void UnmapRequest_Buffers::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+  // required uint64 sva = 1;
+  if (has_sva()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->sva(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+}
+
+int UnmapRequest_Buffers::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint64 sva = 1;
+    if (has_sva()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->sva());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UnmapRequest_Buffers::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const UnmapRequest_Buffers*>(&from));
+}
+
+void UnmapRequest_Buffers::MergeFrom(const UnmapRequest_Buffers& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sva()) {
+      set_sva(from.sva());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void UnmapRequest_Buffers::CopyFrom(const UnmapRequest_Buffers& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UnmapRequest_Buffers::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void UnmapRequest_Buffers::Swap(UnmapRequest_Buffers* other) {
+  if (other != this) {
+    std::swap(sva_, other->sva_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string UnmapRequest_Buffers::GetTypeName() const {
+  return "com.trustonic.tee_proxy.UnmapRequest.Buffers";
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
+const int UnmapRequest::kSidFieldNumber;
+const int UnmapRequest::kBuffersFieldNumber;
+#endif  // !_MSC_VER
+
+UnmapRequest::UnmapRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.UnmapRequest)
+}
+
+void UnmapRequest::InitAsDefaultInstance() {
+}
+
+UnmapRequest::UnmapRequest(const UnmapRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.UnmapRequest)
+}
+
+void UnmapRequest::SharedCtor() {
+  _cached_size_ = 0;
+  sid_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+UnmapRequest::~UnmapRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.UnmapRequest)
+  SharedDtor();
+}
+
+void UnmapRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void UnmapRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const UnmapRequest& UnmapRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+UnmapRequest* UnmapRequest::default_instance_ = NULL;
+
+UnmapRequest* UnmapRequest::New() const {
+  return new UnmapRequest;
+}
+
+void UnmapRequest::Clear() {
+  sid_ = 0u;
+  buffers_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool UnmapRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.UnmapRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 sid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &sid_)));
+          set_has_sid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_buffers;
+        break;
+      }
+
+      // repeated .com.trustonic.tee_proxy.UnmapRequest.Buffers buffers = 2;
+      case 2: {
+        if (tag == 18) {
+         parse_buffers:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_buffers()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(18)) goto parse_buffers;
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.UnmapRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.UnmapRequest)
+  return false;
+#undef DO_
+}
+
+void UnmapRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.UnmapRequest)
+  // required uint32 sid = 1;
+  if (has_sid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->sid(), output);
+  }
+
+  // repeated .com.trustonic.tee_proxy.UnmapRequest.Buffers buffers = 2;
+  for (int i = 0; i < this->buffers_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessage(
+      2, this->buffers(i), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.UnmapRequest)
+}
+
+int UnmapRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 sid = 1;
+    if (has_sid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->sid());
+    }
+
+  }
+  // repeated .com.trustonic.tee_proxy.UnmapRequest.Buffers buffers = 2;
+  total_size += 1 * this->buffers_size();
+  for (int i = 0; i < this->buffers_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->buffers(i));
+  }
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UnmapRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const UnmapRequest*>(&from));
+}
+
+void UnmapRequest::MergeFrom(const UnmapRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  buffers_.MergeFrom(from.buffers_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sid()) {
+      set_sid(from.sid());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void UnmapRequest::CopyFrom(const UnmapRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UnmapRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->buffers())) return false;
+  return true;
+}
+
+void UnmapRequest::Swap(UnmapRequest* other) {
+  if (other != this) {
+    std::swap(sid_, other->sid_);
+    buffers_.Swap(&other->buffers_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string UnmapRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.UnmapRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+#endif  // !_MSC_VER
+
+UnmapResponse::UnmapResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.UnmapResponse)
+}
+
+void UnmapResponse::InitAsDefaultInstance() {
+}
+
+UnmapResponse::UnmapResponse(const UnmapResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.UnmapResponse)
+}
+
+void UnmapResponse::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+UnmapResponse::~UnmapResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.UnmapResponse)
+  SharedDtor();
+}
+
+void UnmapResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void UnmapResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const UnmapResponse& UnmapResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+UnmapResponse* UnmapResponse::default_instance_ = NULL;
+
+UnmapResponse* UnmapResponse::New() const {
+  return new UnmapResponse;
+}
+
+void UnmapResponse::Clear() {
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool UnmapResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.UnmapResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+  handle_unusual:
+    if (tag == 0 ||
+        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+      goto success;
+    }
+    DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+        input, tag, &unknown_fields_stream));
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.UnmapResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.UnmapResponse)
+  return false;
+#undef DO_
+}
+
+void UnmapResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.UnmapResponse)
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.UnmapResponse)
+}
+
+int UnmapResponse::ByteSize() const {
+  int total_size = 0;
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void UnmapResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const UnmapResponse*>(&from));
+}
+
+void UnmapResponse::MergeFrom(const UnmapResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void UnmapResponse::CopyFrom(const UnmapResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UnmapResponse::IsInitialized() const {
+
+  return true;
+}
+
+void UnmapResponse::Swap(UnmapResponse* other) {
+  if (other != this) {
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string UnmapResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.UnmapResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int GetErrorRequest::kSidFieldNumber;
+#endif  // !_MSC_VER
+
+GetErrorRequest::GetErrorRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.GetErrorRequest)
+}
+
+void GetErrorRequest::InitAsDefaultInstance() {
+}
+
+GetErrorRequest::GetErrorRequest(const GetErrorRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.GetErrorRequest)
+}
+
+void GetErrorRequest::SharedCtor() {
+  _cached_size_ = 0;
+  sid_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GetErrorRequest::~GetErrorRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.GetErrorRequest)
+  SharedDtor();
+}
+
+void GetErrorRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void GetErrorRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GetErrorRequest& GetErrorRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+GetErrorRequest* GetErrorRequest::default_instance_ = NULL;
+
+GetErrorRequest* GetErrorRequest::New() const {
+  return new GetErrorRequest;
+}
+
+void GetErrorRequest::Clear() {
+  sid_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool GetErrorRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.GetErrorRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 sid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &sid_)));
+          set_has_sid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.GetErrorRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.GetErrorRequest)
+  return false;
+#undef DO_
+}
+
+void GetErrorRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.GetErrorRequest)
+  // required uint32 sid = 1;
+  if (has_sid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->sid(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.GetErrorRequest)
+}
+
+int GetErrorRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 sid = 1;
+    if (has_sid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->sid());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GetErrorRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const GetErrorRequest*>(&from));
+}
+
+void GetErrorRequest::MergeFrom(const GetErrorRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sid()) {
+      set_sid(from.sid());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void GetErrorRequest::CopyFrom(const GetErrorRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetErrorRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void GetErrorRequest::Swap(GetErrorRequest* other) {
+  if (other != this) {
+    std::swap(sid_, other->sid_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string GetErrorRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.GetErrorRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int GetErrorResponse::kExitCodeFieldNumber;
+#endif  // !_MSC_VER
+
+GetErrorResponse::GetErrorResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.GetErrorResponse)
+}
+
+void GetErrorResponse::InitAsDefaultInstance() {
+}
+
+GetErrorResponse::GetErrorResponse(const GetErrorResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.GetErrorResponse)
+}
+
+void GetErrorResponse::SharedCtor() {
+  _cached_size_ = 0;
+  exit_code_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GetErrorResponse::~GetErrorResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.GetErrorResponse)
+  SharedDtor();
+}
+
+void GetErrorResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void GetErrorResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GetErrorResponse& GetErrorResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+GetErrorResponse* GetErrorResponse::default_instance_ = NULL;
+
+GetErrorResponse* GetErrorResponse::New() const {
+  return new GetErrorResponse;
+}
+
+void GetErrorResponse::Clear() {
+  exit_code_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool GetErrorResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.GetErrorResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required sint32 exit_code = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_SINT32>(
+                 input, &exit_code_)));
+          set_has_exit_code();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.GetErrorResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.GetErrorResponse)
+  return false;
+#undef DO_
+}
+
+void GetErrorResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.GetErrorResponse)
+  // required sint32 exit_code = 1;
+  if (has_exit_code()) {
+    ::google::protobuf::internal::WireFormatLite::WriteSInt32(1, this->exit_code(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.GetErrorResponse)
+}
+
+int GetErrorResponse::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required sint32 exit_code = 1;
+    if (has_exit_code()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::SInt32Size(
+          this->exit_code());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GetErrorResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const GetErrorResponse*>(&from));
+}
+
+void GetErrorResponse::MergeFrom(const GetErrorResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_exit_code()) {
+      set_exit_code(from.exit_code());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void GetErrorResponse::CopyFrom(const GetErrorResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetErrorResponse::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void GetErrorResponse::Swap(GetErrorResponse* other) {
+  if (other != this) {
+    std::swap(exit_code_, other->exit_code_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string GetErrorResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.GetErrorResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+#endif  // !_MSC_VER
+
+GetVersionRequest::GetVersionRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.GetVersionRequest)
+}
+
+void GetVersionRequest::InitAsDefaultInstance() {
+}
+
+GetVersionRequest::GetVersionRequest(const GetVersionRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.GetVersionRequest)
+}
+
+void GetVersionRequest::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GetVersionRequest::~GetVersionRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.GetVersionRequest)
+  SharedDtor();
+}
+
+void GetVersionRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void GetVersionRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GetVersionRequest& GetVersionRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+GetVersionRequest* GetVersionRequest::default_instance_ = NULL;
+
+GetVersionRequest* GetVersionRequest::New() const {
+  return new GetVersionRequest;
+}
+
+void GetVersionRequest::Clear() {
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool GetVersionRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.GetVersionRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+  handle_unusual:
+    if (tag == 0 ||
+        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+      goto success;
+    }
+    DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+        input, tag, &unknown_fields_stream));
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.GetVersionRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.GetVersionRequest)
+  return false;
+#undef DO_
+}
+
+void GetVersionRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.GetVersionRequest)
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.GetVersionRequest)
+}
+
+int GetVersionRequest::ByteSize() const {
+  int total_size = 0;
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GetVersionRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const GetVersionRequest*>(&from));
+}
+
+void GetVersionRequest::MergeFrom(const GetVersionRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void GetVersionRequest::CopyFrom(const GetVersionRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetVersionRequest::IsInitialized() const {
+
+  return true;
+}
+
+void GetVersionRequest::Swap(GetVersionRequest* other) {
+  if (other != this) {
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string GetVersionRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.GetVersionRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int GetVersionResponse::kProductIdFieldNumber;
+const int GetVersionResponse::kMciFieldNumber;
+const int GetVersionResponse::kSoFieldNumber;
+const int GetVersionResponse::kMclfFieldNumber;
+const int GetVersionResponse::kContainerFieldNumber;
+const int GetVersionResponse::kMcConfigFieldNumber;
+const int GetVersionResponse::kTlApiFieldNumber;
+const int GetVersionResponse::kDrApiFieldNumber;
+const int GetVersionResponse::kNwdFieldNumber;
+#endif  // !_MSC_VER
+
+GetVersionResponse::GetVersionResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.GetVersionResponse)
+}
+
+void GetVersionResponse::InitAsDefaultInstance() {
+}
+
+GetVersionResponse::GetVersionResponse(const GetVersionResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.GetVersionResponse)
+}
+
+void GetVersionResponse::SharedCtor() {
+  ::google::protobuf::internal::GetEmptyString();
+  _cached_size_ = 0;
+  product_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  mci_ = 0u;
+  so_ = 0u;
+  mclf_ = 0u;
+  container_ = 0u;
+  mc_config_ = 0u;
+  tl_api_ = 0u;
+  dr_api_ = 0u;
+  nwd_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GetVersionResponse::~GetVersionResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.GetVersionResponse)
+  SharedDtor();
+}
+
+void GetVersionResponse::SharedDtor() {
+  if (product_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete product_id_;
+  }
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void GetVersionResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GetVersionResponse& GetVersionResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+GetVersionResponse* GetVersionResponse::default_instance_ = NULL;
+
+GetVersionResponse* GetVersionResponse::New() const {
+  return new GetVersionResponse;
+}
+
+void GetVersionResponse::Clear() {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>(      \
+  &reinterpret_cast<GetVersionResponse*>(16)->f) - \
+   reinterpret_cast<char*>(16))
+
+#define ZR_(first, last) do {                              \
+    size_t f = OFFSET_OF_FIELD_(first);                    \
+    size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last);  \
+    ::memset(&first, 0, n);                                \
+  } while (0)
+
+  if (_has_bits_[0 / 32] & 255) {
+    ZR_(mci_, dr_api_);
+    if (has_product_id()) {
+      if (product_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+        product_id_->clear();
+      }
+    }
+  }
+  nwd_ = 0u;
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool GetVersionResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.GetVersionResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required string product_id = 1;
+      case 1: {
+        if (tag == 10) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_product_id()));
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(16)) goto parse_mci;
+        break;
+      }
+
+      // required uint32 mci = 2;
+      case 2: {
+        if (tag == 16) {
+         parse_mci:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &mci_)));
+          set_has_mci();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(24)) goto parse_so;
+        break;
+      }
+
+      // required uint32 so = 3;
+      case 3: {
+        if (tag == 24) {
+         parse_so:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &so_)));
+          set_has_so();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(32)) goto parse_mclf;
+        break;
+      }
+
+      // required uint32 mclf = 4;
+      case 4: {
+        if (tag == 32) {
+         parse_mclf:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &mclf_)));
+          set_has_mclf();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(40)) goto parse_container;
+        break;
+      }
+
+      // required uint32 container = 5;
+      case 5: {
+        if (tag == 40) {
+         parse_container:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &container_)));
+          set_has_container();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(48)) goto parse_mc_config;
+        break;
+      }
+
+      // required uint32 mc_config = 6;
+      case 6: {
+        if (tag == 48) {
+         parse_mc_config:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &mc_config_)));
+          set_has_mc_config();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(56)) goto parse_tl_api;
+        break;
+      }
+
+      // required uint32 tl_api = 7;
+      case 7: {
+        if (tag == 56) {
+         parse_tl_api:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &tl_api_)));
+          set_has_tl_api();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(64)) goto parse_dr_api;
+        break;
+      }
+
+      // required uint32 dr_api = 8;
+      case 8: {
+        if (tag == 64) {
+         parse_dr_api:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &dr_api_)));
+          set_has_dr_api();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectTag(72)) goto parse_nwd;
+        break;
+      }
+
+      // required uint32 nwd = 9;
+      case 9: {
+        if (tag == 72) {
+         parse_nwd:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &nwd_)));
+          set_has_nwd();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.GetVersionResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.GetVersionResponse)
+  return false;
+#undef DO_
+}
+
+void GetVersionResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.GetVersionResponse)
+  // required string product_id = 1;
+  if (has_product_id()) {
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->product_id(), output);
+  }
+
+  // required uint32 mci = 2;
+  if (has_mci()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(2, this->mci(), output);
+  }
+
+  // required uint32 so = 3;
+  if (has_so()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->so(), output);
+  }
+
+  // required uint32 mclf = 4;
+  if (has_mclf()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->mclf(), output);
+  }
+
+  // required uint32 container = 5;
+  if (has_container()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(5, this->container(), output);
+  }
+
+  // required uint32 mc_config = 6;
+  if (has_mc_config()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(6, this->mc_config(), output);
+  }
+
+  // required uint32 tl_api = 7;
+  if (has_tl_api()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(7, this->tl_api(), output);
+  }
+
+  // required uint32 dr_api = 8;
+  if (has_dr_api()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(8, this->dr_api(), output);
+  }
+
+  // required uint32 nwd = 9;
+  if (has_nwd()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(9, this->nwd(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.GetVersionResponse)
+}
+
+int GetVersionResponse::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required string product_id = 1;
+    if (has_product_id()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->product_id());
+    }
+
+    // required uint32 mci = 2;
+    if (has_mci()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->mci());
+    }
+
+    // required uint32 so = 3;
+    if (has_so()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->so());
+    }
+
+    // required uint32 mclf = 4;
+    if (has_mclf()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->mclf());
+    }
+
+    // required uint32 container = 5;
+    if (has_container()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->container());
+    }
+
+    // required uint32 mc_config = 6;
+    if (has_mc_config()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->mc_config());
+    }
+
+    // required uint32 tl_api = 7;
+    if (has_tl_api()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->tl_api());
+    }
+
+    // required uint32 dr_api = 8;
+    if (has_dr_api()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->dr_api());
+    }
+
+  }
+  if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    // required uint32 nwd = 9;
+    if (has_nwd()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->nwd());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GetVersionResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const GetVersionResponse*>(&from));
+}
+
+void GetVersionResponse::MergeFrom(const GetVersionResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_product_id()) {
+      set_product_id(from.product_id());
+    }
+    if (from.has_mci()) {
+      set_mci(from.mci());
+    }
+    if (from.has_so()) {
+      set_so(from.so());
+    }
+    if (from.has_mclf()) {
+      set_mclf(from.mclf());
+    }
+    if (from.has_container()) {
+      set_container(from.container());
+    }
+    if (from.has_mc_config()) {
+      set_mc_config(from.mc_config());
+    }
+    if (from.has_tl_api()) {
+      set_tl_api(from.tl_api());
+    }
+    if (from.has_dr_api()) {
+      set_dr_api(from.dr_api());
+    }
+  }
+  if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+    if (from.has_nwd()) {
+      set_nwd(from.nwd());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void GetVersionResponse::CopyFrom(const GetVersionResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetVersionResponse::IsInitialized() const {
+  if ((_has_bits_[0] & 0x000001ff) != 0x000001ff) return false;
+
+  return true;
+}
+
+void GetVersionResponse::Swap(GetVersionResponse* other) {
+  if (other != this) {
+    std::swap(product_id_, other->product_id_);
+    std::swap(mci_, other->mci_);
+    std::swap(so_, other->so_);
+    std::swap(mclf_, other->mclf_);
+    std::swap(container_, other->container_);
+    std::swap(mc_config_, other->mc_config_);
+    std::swap(tl_api_, other->tl_api_);
+    std::swap(dr_api_, other->dr_api_);
+    std::swap(nwd_, other->nwd_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string GetVersionResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.GetVersionResponse";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+const int GpRequestCancellationRequest::kSidFieldNumber;
+#endif  // !_MSC_VER
+
+GpRequestCancellationRequest::GpRequestCancellationRequest()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+}
+
+void GpRequestCancellationRequest::InitAsDefaultInstance() {
+}
+
+GpRequestCancellationRequest::GpRequestCancellationRequest(const GpRequestCancellationRequest& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+}
+
+void GpRequestCancellationRequest::SharedCtor() {
+  _cached_size_ = 0;
+  sid_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GpRequestCancellationRequest::~GpRequestCancellationRequest() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+  SharedDtor();
+}
+
+void GpRequestCancellationRequest::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void GpRequestCancellationRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GpRequestCancellationRequest& GpRequestCancellationRequest::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+GpRequestCancellationRequest* GpRequestCancellationRequest::default_instance_ = NULL;
+
+GpRequestCancellationRequest* GpRequestCancellationRequest::New() const {
+  return new GpRequestCancellationRequest;
+}
+
+void GpRequestCancellationRequest::Clear() {
+  sid_ = 0u;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool GpRequestCancellationRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 sid = 1;
+      case 1: {
+        if (tag == 8) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &sid_)));
+          set_has_sid();
+        } else {
+          goto handle_unusual;
+        }
+        if (input->ExpectAtEnd()) goto success;
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0 ||
+            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+            input, tag, &unknown_fields_stream));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+  return false;
+#undef DO_
+}
+
+void GpRequestCancellationRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+  // required uint32 sid = 1;
+  if (has_sid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->sid(), output);
+  }
+
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+}
+
+int GpRequestCancellationRequest::ByteSize() const {
+  int total_size = 0;
+
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 sid = 1;
+    if (has_sid()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->sid());
+    }
+
+  }
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GpRequestCancellationRequest::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const GpRequestCancellationRequest*>(&from));
+}
+
+void GpRequestCancellationRequest::MergeFrom(const GpRequestCancellationRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from.has_sid()) {
+      set_sid(from.sid());
+    }
+  }
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void GpRequestCancellationRequest::CopyFrom(const GpRequestCancellationRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GpRequestCancellationRequest::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+
+  return true;
+}
+
+void GpRequestCancellationRequest::Swap(GpRequestCancellationRequest* other) {
+  if (other != this) {
+    std::swap(sid_, other->sid_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string GpRequestCancellationRequest::GetTypeName() const {
+  return "com.trustonic.tee_proxy.GpRequestCancellationRequest";
+}
+
+
+// ===================================================================
+
+#ifndef _MSC_VER
+#endif  // !_MSC_VER
+
+GpRequestCancellationResponse::GpRequestCancellationResponse()
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+}
+
+void GpRequestCancellationResponse::InitAsDefaultInstance() {
+}
+
+GpRequestCancellationResponse::GpRequestCancellationResponse(const GpRequestCancellationResponse& from)
+  : ::google::protobuf::MessageLite() {
+  SharedCtor();
+  MergeFrom(from);
+  // @@protoc_insertion_point(copy_constructor:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+}
+
+void GpRequestCancellationResponse::SharedCtor() {
+  _cached_size_ = 0;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+GpRequestCancellationResponse::~GpRequestCancellationResponse() {
+  // @@protoc_insertion_point(destructor:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+  SharedDtor();
+}
+
+void GpRequestCancellationResponse::SharedDtor() {
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  if (this != &default_instance()) {
+  #else
+  if (this != default_instance_) {
+  #endif
+  }
+}
+
+void GpRequestCancellationResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const GpRequestCancellationResponse& GpRequestCancellationResponse::default_instance() {
+#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  protobuf_AddDesc_mc_2eproto();
+#else
+  if (default_instance_ == NULL) protobuf_AddDesc_mc_2eproto();
+#endif
+  return *default_instance_;
+}
+
+GpRequestCancellationResponse* GpRequestCancellationResponse::default_instance_ = NULL;
+
+GpRequestCancellationResponse* GpRequestCancellationResponse::New() const {
+  return new GpRequestCancellationResponse;
+}
+
+void GpRequestCancellationResponse::Clear() {
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->clear();
+}
+
+bool GpRequestCancellationResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::io::StringOutputStream unknown_fields_string(
+      mutable_unknown_fields());
+  ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+      &unknown_fields_string);
+  // @@protoc_insertion_point(parse_start:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+  handle_unusual:
+    if (tag == 0 ||
+        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+      goto success;
+    }
+    DO_(::google::protobuf::internal::WireFormatLite::SkipField(
+        input, tag, &unknown_fields_stream));
+  }
+success:
+  // @@protoc_insertion_point(parse_success:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+  return false;
+#undef DO_
+}
+
+void GpRequestCancellationResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+  output->WriteRaw(unknown_fields().data(),
+                   unknown_fields().size());
+  // @@protoc_insertion_point(serialize_end:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+}
+
+int GpRequestCancellationResponse::ByteSize() const {
+  int total_size = 0;
+
+  total_size += unknown_fields().size();
+
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void GpRequestCancellationResponse::CheckTypeAndMergeFrom(
+    const ::google::protobuf::MessageLite& from) {
+  MergeFrom(*::google::protobuf::down_cast<const GpRequestCancellationResponse*>(&from));
+}
+
+void GpRequestCancellationResponse::MergeFrom(const GpRequestCancellationResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  mutable_unknown_fields()->append(from.unknown_fields());
+}
+
+void GpRequestCancellationResponse::CopyFrom(const GpRequestCancellationResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GpRequestCancellationResponse::IsInitialized() const {
+
+  return true;
+}
+
+void GpRequestCancellationResponse::Swap(GpRequestCancellationResponse* other) {
+  if (other != this) {
+    _unknown_fields_.swap(other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::std::string GpRequestCancellationResponse::GetTypeName() const {
+  return "com.trustonic.tee_proxy.GpRequestCancellationResponse";
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace tee_proxy
+}  // namespace trustonic
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
diff --git a/mobicore/ClientLib/src/mc.pb.h b/mobicore/ClientLib/src/mc.pb.h
new file mode 100644 (file)
index 0000000..c74bdab
--- /dev/null
@@ -0,0 +1,4365 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: mc.proto
+
+#ifndef PROTOBUF_mc_2eproto__INCLUDED
+#define PROTOBUF_mc_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2006000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 2006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+// @@protoc_insertion_point(includes)
+
+namespace com {
+namespace trustonic {
+namespace tee_proxy {
+
+// Internal implementation detail -- do not call these.
+void  protobuf_AddDesc_mc_2eproto();
+void protobuf_AssignDesc_mc_2eproto();
+void protobuf_ShutdownFile_mc_2eproto();
+
+class OpenSessionRequest;
+class OpenSessionResponse;
+class OpenTrustletRequest;
+class OpenTrustletResponse;
+class CloseSessionRequest;
+class CloseSessionResponse;
+class NotifyRequest;
+class NotifyRequest_Buffers;
+class NotifyResponse;
+class WaitNotificationRequest;
+class WaitNotificationResponse;
+class WaitNotificationResponse_Buffers;
+class MapRequest;
+class MapRequest_Buffers;
+class MapResponse;
+class MapResponse_Buffers;
+class UnmapRequest;
+class UnmapRequest_Buffers;
+class UnmapResponse;
+class GetErrorRequest;
+class GetErrorResponse;
+class GetVersionRequest;
+class GetVersionResponse;
+class GpRequestCancellationRequest;
+class GpRequestCancellationResponse;
+
+enum LoginType {
+  TEEC_LOGIN_PUBLIC = 0,
+  TEEC_LOGIN_USER = 1,
+  TEEC_LOGIN_GROUP = 2,
+  TEEC_LOGIN_APPLICATION = 4,
+  TEEC_LOGIN_USER_APPLICATION = 5,
+  TEEC_LOGIN_GROUP_APPLICATION = 6
+};
+bool LoginType_IsValid(int value);
+const LoginType LoginType_MIN = TEEC_LOGIN_PUBLIC;
+const LoginType LoginType_MAX = TEEC_LOGIN_GROUP_APPLICATION;
+const int LoginType_ARRAYSIZE = LoginType_MAX + 1;
+
+// ===================================================================
+
+class OpenSessionRequest : public ::google::protobuf::MessageLite {
+ public:
+  OpenSessionRequest();
+  virtual ~OpenSessionRequest();
+
+  OpenSessionRequest(const OpenSessionRequest& from);
+
+  inline OpenSessionRequest& operator=(const OpenSessionRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const OpenSessionRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const OpenSessionRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(OpenSessionRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  OpenSessionRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const OpenSessionRequest& from);
+  void MergeFrom(const OpenSessionRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required bytes uuid = 1;
+  inline bool has_uuid() const;
+  inline void clear_uuid();
+  static const int kUuidFieldNumber = 1;
+  inline const ::std::string& uuid() const;
+  inline void set_uuid(const ::std::string& value);
+  inline void set_uuid(const char* value);
+  inline void set_uuid(const void* value, size_t size);
+  inline ::std::string* mutable_uuid();
+  inline ::std::string* release_uuid();
+  inline void set_allocated_uuid(::std::string* uuid);
+
+  // required bool is_gp_uuid = 2;
+  inline bool has_is_gp_uuid() const;
+  inline void clear_is_gp_uuid();
+  static const int kIsGpUuidFieldNumber = 2;
+  inline bool is_gp_uuid() const;
+  inline void set_is_gp_uuid(bool value);
+
+  // optional bytes tci = 3;
+  inline bool has_tci() const;
+  inline void clear_tci();
+  static const int kTciFieldNumber = 3;
+  inline const ::std::string& tci() const;
+  inline void set_tci(const ::std::string& value);
+  inline void set_tci(const char* value);
+  inline void set_tci(const void* value, size_t size);
+  inline ::std::string* mutable_tci();
+  inline ::std::string* release_tci();
+  inline void set_allocated_tci(::std::string* tci);
+
+  // required .com.trustonic.tee_proxy.LoginType login_type = 4;
+  inline bool has_login_type() const;
+  inline void clear_login_type();
+  static const int kLoginTypeFieldNumber = 4;
+  inline ::com::trustonic::tee_proxy::LoginType login_type() const;
+  inline void set_login_type(::com::trustonic::tee_proxy::LoginType value);
+
+  // required bytes login_data = 5;
+  inline bool has_login_data() const;
+  inline void clear_login_data();
+  static const int kLoginDataFieldNumber = 5;
+  inline const ::std::string& login_data() const;
+  inline void set_login_data(const ::std::string& value);
+  inline void set_login_data(const char* value);
+  inline void set_login_data(const void* value, size_t size);
+  inline ::std::string* mutable_login_data();
+  inline ::std::string* release_login_data();
+  inline void set_allocated_login_data(::std::string* login_data);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.OpenSessionRequest)
+ private:
+  inline void set_has_uuid();
+  inline void clear_has_uuid();
+  inline void set_has_is_gp_uuid();
+  inline void clear_has_is_gp_uuid();
+  inline void set_has_tci();
+  inline void clear_has_tci();
+  inline void set_has_login_type();
+  inline void clear_has_login_type();
+  inline void set_has_login_data();
+  inline void clear_has_login_data();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::std::string* uuid_;
+  ::std::string* tci_;
+  bool is_gp_uuid_;
+  int login_type_;
+  ::std::string* login_data_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static OpenSessionRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class OpenSessionResponse : public ::google::protobuf::MessageLite {
+ public:
+  OpenSessionResponse();
+  virtual ~OpenSessionResponse();
+
+  OpenSessionResponse(const OpenSessionResponse& from);
+
+  inline OpenSessionResponse& operator=(const OpenSessionResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const OpenSessionResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const OpenSessionResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(OpenSessionResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  OpenSessionResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const OpenSessionResponse& from);
+  void MergeFrom(const OpenSessionResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 id = 1;
+  inline bool has_id() const;
+  inline void clear_id();
+  static const int kIdFieldNumber = 1;
+  inline ::google::protobuf::uint32 id() const;
+  inline void set_id(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.OpenSessionResponse)
+ private:
+  inline void set_has_id();
+  inline void clear_has_id();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 id_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static OpenSessionResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class OpenTrustletRequest : public ::google::protobuf::MessageLite {
+ public:
+  OpenTrustletRequest();
+  virtual ~OpenTrustletRequest();
+
+  OpenTrustletRequest(const OpenTrustletRequest& from);
+
+  inline OpenTrustletRequest& operator=(const OpenTrustletRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const OpenTrustletRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const OpenTrustletRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(OpenTrustletRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  OpenTrustletRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const OpenTrustletRequest& from);
+  void MergeFrom(const OpenTrustletRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 spid = 1;
+  inline bool has_spid() const;
+  inline void clear_spid();
+  static const int kSpidFieldNumber = 1;
+  inline ::google::protobuf::uint32 spid() const;
+  inline void set_spid(::google::protobuf::uint32 value);
+
+  // required bytes trustapp = 2;
+  inline bool has_trustapp() const;
+  inline void clear_trustapp();
+  static const int kTrustappFieldNumber = 2;
+  inline const ::std::string& trustapp() const;
+  inline void set_trustapp(const ::std::string& value);
+  inline void set_trustapp(const char* value);
+  inline void set_trustapp(const void* value, size_t size);
+  inline ::std::string* mutable_trustapp();
+  inline ::std::string* release_trustapp();
+  inline void set_allocated_trustapp(::std::string* trustapp);
+
+  // optional bytes tci = 3;
+  inline bool has_tci() const;
+  inline void clear_tci();
+  static const int kTciFieldNumber = 3;
+  inline const ::std::string& tci() const;
+  inline void set_tci(const ::std::string& value);
+  inline void set_tci(const char* value);
+  inline void set_tci(const void* value, size_t size);
+  inline ::std::string* mutable_tci();
+  inline ::std::string* release_tci();
+  inline void set_allocated_tci(::std::string* tci);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.OpenTrustletRequest)
+ private:
+  inline void set_has_spid();
+  inline void clear_has_spid();
+  inline void set_has_trustapp();
+  inline void clear_has_trustapp();
+  inline void set_has_tci();
+  inline void clear_has_tci();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::std::string* trustapp_;
+  ::std::string* tci_;
+  ::google::protobuf::uint32 spid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static OpenTrustletRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class OpenTrustletResponse : public ::google::protobuf::MessageLite {
+ public:
+  OpenTrustletResponse();
+  virtual ~OpenTrustletResponse();
+
+  OpenTrustletResponse(const OpenTrustletResponse& from);
+
+  inline OpenTrustletResponse& operator=(const OpenTrustletResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const OpenTrustletResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const OpenTrustletResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(OpenTrustletResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  OpenTrustletResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const OpenTrustletResponse& from);
+  void MergeFrom(const OpenTrustletResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 id = 1;
+  inline bool has_id() const;
+  inline void clear_id();
+  static const int kIdFieldNumber = 1;
+  inline ::google::protobuf::uint32 id() const;
+  inline void set_id(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.OpenTrustletResponse)
+ private:
+  inline void set_has_id();
+  inline void clear_has_id();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 id_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static OpenTrustletResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class CloseSessionRequest : public ::google::protobuf::MessageLite {
+ public:
+  CloseSessionRequest();
+  virtual ~CloseSessionRequest();
+
+  CloseSessionRequest(const CloseSessionRequest& from);
+
+  inline CloseSessionRequest& operator=(const CloseSessionRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const CloseSessionRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const CloseSessionRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(CloseSessionRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  CloseSessionRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const CloseSessionRequest& from);
+  void MergeFrom(const CloseSessionRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 id = 1;
+  inline bool has_id() const;
+  inline void clear_id();
+  static const int kIdFieldNumber = 1;
+  inline ::google::protobuf::uint32 id() const;
+  inline void set_id(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.CloseSessionRequest)
+ private:
+  inline void set_has_id();
+  inline void clear_has_id();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 id_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static CloseSessionRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class CloseSessionResponse : public ::google::protobuf::MessageLite {
+ public:
+  CloseSessionResponse();
+  virtual ~CloseSessionResponse();
+
+  CloseSessionResponse(const CloseSessionResponse& from);
+
+  inline CloseSessionResponse& operator=(const CloseSessionResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const CloseSessionResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const CloseSessionResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(CloseSessionResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  CloseSessionResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const CloseSessionResponse& from);
+  void MergeFrom(const CloseSessionResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.CloseSessionResponse)
+ private:
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static CloseSessionResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class NotifyRequest_Buffers : public ::google::protobuf::MessageLite {
+ public:
+  NotifyRequest_Buffers();
+  virtual ~NotifyRequest_Buffers();
+
+  NotifyRequest_Buffers(const NotifyRequest_Buffers& from);
+
+  inline NotifyRequest_Buffers& operator=(const NotifyRequest_Buffers& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const NotifyRequest_Buffers& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const NotifyRequest_Buffers* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(NotifyRequest_Buffers* other);
+
+  // implements Message ----------------------------------------------
+
+  NotifyRequest_Buffers* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const NotifyRequest_Buffers& from);
+  void MergeFrom(const NotifyRequest_Buffers& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint64 sva = 1;
+  inline bool has_sva() const;
+  inline void clear_sva();
+  static const int kSvaFieldNumber = 1;
+  inline ::google::protobuf::uint64 sva() const;
+  inline void set_sva(::google::protobuf::uint64 value);
+
+  // required bytes data = 2;
+  inline bool has_data() const;
+  inline void clear_data();
+  static const int kDataFieldNumber = 2;
+  inline const ::std::string& data() const;
+  inline void set_data(const ::std::string& value);
+  inline void set_data(const char* value);
+  inline void set_data(const void* value, size_t size);
+  inline ::std::string* mutable_data();
+  inline ::std::string* release_data();
+  inline void set_allocated_data(::std::string* data);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.NotifyRequest.Buffers)
+ private:
+  inline void set_has_sva();
+  inline void clear_has_sva();
+  inline void set_has_data();
+  inline void clear_has_data();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint64 sva_;
+  ::std::string* data_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static NotifyRequest_Buffers* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class NotifyRequest : public ::google::protobuf::MessageLite {
+ public:
+  NotifyRequest();
+  virtual ~NotifyRequest();
+
+  NotifyRequest(const NotifyRequest& from);
+
+  inline NotifyRequest& operator=(const NotifyRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const NotifyRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const NotifyRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(NotifyRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  NotifyRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const NotifyRequest& from);
+  void MergeFrom(const NotifyRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef NotifyRequest_Buffers Buffers;
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 sid = 1;
+  inline bool has_sid() const;
+  inline void clear_sid();
+  static const int kSidFieldNumber = 1;
+  inline ::google::protobuf::uint32 sid() const;
+  inline void set_sid(::google::protobuf::uint32 value);
+
+  // optional bytes tci = 2;
+  inline bool has_tci() const;
+  inline void clear_tci();
+  static const int kTciFieldNumber = 2;
+  inline const ::std::string& tci() const;
+  inline void set_tci(const ::std::string& value);
+  inline void set_tci(const char* value);
+  inline void set_tci(const void* value, size_t size);
+  inline ::std::string* mutable_tci();
+  inline ::std::string* release_tci();
+  inline void set_allocated_tci(::std::string* tci);
+
+  // repeated .com.trustonic.tee_proxy.NotifyRequest.Buffers buffers = 3;
+  inline int buffers_size() const;
+  inline void clear_buffers();
+  static const int kBuffersFieldNumber = 3;
+  inline const ::com::trustonic::tee_proxy::NotifyRequest_Buffers& buffers(int index) const;
+  inline ::com::trustonic::tee_proxy::NotifyRequest_Buffers* mutable_buffers(int index);
+  inline ::com::trustonic::tee_proxy::NotifyRequest_Buffers* add_buffers();
+  inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::NotifyRequest_Buffers >&
+      buffers() const;
+  inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::NotifyRequest_Buffers >*
+      mutable_buffers();
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.NotifyRequest)
+ private:
+  inline void set_has_sid();
+  inline void clear_has_sid();
+  inline void set_has_tci();
+  inline void clear_has_tci();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::std::string* tci_;
+  ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::NotifyRequest_Buffers > buffers_;
+  ::google::protobuf::uint32 sid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static NotifyRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class NotifyResponse : public ::google::protobuf::MessageLite {
+ public:
+  NotifyResponse();
+  virtual ~NotifyResponse();
+
+  NotifyResponse(const NotifyResponse& from);
+
+  inline NotifyResponse& operator=(const NotifyResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const NotifyResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const NotifyResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(NotifyResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  NotifyResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const NotifyResponse& from);
+  void MergeFrom(const NotifyResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.NotifyResponse)
+ private:
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static NotifyResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class WaitNotificationRequest : public ::google::protobuf::MessageLite {
+ public:
+  WaitNotificationRequest();
+  virtual ~WaitNotificationRequest();
+
+  WaitNotificationRequest(const WaitNotificationRequest& from);
+
+  inline WaitNotificationRequest& operator=(const WaitNotificationRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const WaitNotificationRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const WaitNotificationRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(WaitNotificationRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  WaitNotificationRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const WaitNotificationRequest& from);
+  void MergeFrom(const WaitNotificationRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 sid = 1;
+  inline bool has_sid() const;
+  inline void clear_sid();
+  static const int kSidFieldNumber = 1;
+  inline ::google::protobuf::uint32 sid() const;
+  inline void set_sid(::google::protobuf::uint32 value);
+
+  // required sint32 timeout = 2;
+  inline bool has_timeout() const;
+  inline void clear_timeout();
+  static const int kTimeoutFieldNumber = 2;
+  inline ::google::protobuf::int32 timeout() const;
+  inline void set_timeout(::google::protobuf::int32 value);
+
+  // required bool partial = 3;
+  inline bool has_partial() const;
+  inline void clear_partial();
+  static const int kPartialFieldNumber = 3;
+  inline bool partial() const;
+  inline void set_partial(bool value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.WaitNotificationRequest)
+ private:
+  inline void set_has_sid();
+  inline void clear_has_sid();
+  inline void set_has_timeout();
+  inline void clear_has_timeout();
+  inline void set_has_partial();
+  inline void clear_has_partial();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 sid_;
+  ::google::protobuf::int32 timeout_;
+  bool partial_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static WaitNotificationRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class WaitNotificationResponse_Buffers : public ::google::protobuf::MessageLite {
+ public:
+  WaitNotificationResponse_Buffers();
+  virtual ~WaitNotificationResponse_Buffers();
+
+  WaitNotificationResponse_Buffers(const WaitNotificationResponse_Buffers& from);
+
+  inline WaitNotificationResponse_Buffers& operator=(const WaitNotificationResponse_Buffers& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const WaitNotificationResponse_Buffers& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const WaitNotificationResponse_Buffers* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(WaitNotificationResponse_Buffers* other);
+
+  // implements Message ----------------------------------------------
+
+  WaitNotificationResponse_Buffers* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const WaitNotificationResponse_Buffers& from);
+  void MergeFrom(const WaitNotificationResponse_Buffers& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint64 sva = 1;
+  inline bool has_sva() const;
+  inline void clear_sva();
+  static const int kSvaFieldNumber = 1;
+  inline ::google::protobuf::uint64 sva() const;
+  inline void set_sva(::google::protobuf::uint64 value);
+
+  // required bytes data = 2;
+  inline bool has_data() const;
+  inline void clear_data();
+  static const int kDataFieldNumber = 2;
+  inline const ::std::string& data() const;
+  inline void set_data(const ::std::string& value);
+  inline void set_data(const char* value);
+  inline void set_data(const void* value, size_t size);
+  inline ::std::string* mutable_data();
+  inline ::std::string* release_data();
+  inline void set_allocated_data(::std::string* data);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers)
+ private:
+  inline void set_has_sva();
+  inline void clear_has_sva();
+  inline void set_has_data();
+  inline void clear_has_data();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint64 sva_;
+  ::std::string* data_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static WaitNotificationResponse_Buffers* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class WaitNotificationResponse : public ::google::protobuf::MessageLite {
+ public:
+  WaitNotificationResponse();
+  virtual ~WaitNotificationResponse();
+
+  WaitNotificationResponse(const WaitNotificationResponse& from);
+
+  inline WaitNotificationResponse& operator=(const WaitNotificationResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const WaitNotificationResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const WaitNotificationResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(WaitNotificationResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  WaitNotificationResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const WaitNotificationResponse& from);
+  void MergeFrom(const WaitNotificationResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef WaitNotificationResponse_Buffers Buffers;
+
+  // accessors -------------------------------------------------------
+
+  // optional bytes tci = 1;
+  inline bool has_tci() const;
+  inline void clear_tci();
+  static const int kTciFieldNumber = 1;
+  inline const ::std::string& tci() const;
+  inline void set_tci(const ::std::string& value);
+  inline void set_tci(const char* value);
+  inline void set_tci(const void* value, size_t size);
+  inline ::std::string* mutable_tci();
+  inline ::std::string* release_tci();
+  inline void set_allocated_tci(::std::string* tci);
+
+  // repeated .com.trustonic.tee_proxy.WaitNotificationResponse.Buffers buffers = 2;
+  inline int buffers_size() const;
+  inline void clear_buffers();
+  static const int kBuffersFieldNumber = 2;
+  inline const ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers& buffers(int index) const;
+  inline ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers* mutable_buffers(int index);
+  inline ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers* add_buffers();
+  inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers >&
+      buffers() const;
+  inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers >*
+      mutable_buffers();
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.WaitNotificationResponse)
+ private:
+  inline void set_has_tci();
+  inline void clear_has_tci();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::std::string* tci_;
+  ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers > buffers_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static WaitNotificationResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class MapRequest_Buffers : public ::google::protobuf::MessageLite {
+ public:
+  MapRequest_Buffers();
+  virtual ~MapRequest_Buffers();
+
+  MapRequest_Buffers(const MapRequest_Buffers& from);
+
+  inline MapRequest_Buffers& operator=(const MapRequest_Buffers& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const MapRequest_Buffers& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const MapRequest_Buffers* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(MapRequest_Buffers* other);
+
+  // implements Message ----------------------------------------------
+
+  MapRequest_Buffers* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const MapRequest_Buffers& from);
+  void MergeFrom(const MapRequest_Buffers& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 len = 1;
+  inline bool has_len() const;
+  inline void clear_len();
+  static const int kLenFieldNumber = 1;
+  inline ::google::protobuf::uint32 len() const;
+  inline void set_len(::google::protobuf::uint32 value);
+
+  // required uint32 flags = 2;
+  inline bool has_flags() const;
+  inline void clear_flags();
+  static const int kFlagsFieldNumber = 2;
+  inline ::google::protobuf::uint32 flags() const;
+  inline void set_flags(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.MapRequest.Buffers)
+ private:
+  inline void set_has_len();
+  inline void clear_has_len();
+  inline void set_has_flags();
+  inline void clear_has_flags();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 len_;
+  ::google::protobuf::uint32 flags_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static MapRequest_Buffers* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class MapRequest : public ::google::protobuf::MessageLite {
+ public:
+  MapRequest();
+  virtual ~MapRequest();
+
+  MapRequest(const MapRequest& from);
+
+  inline MapRequest& operator=(const MapRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const MapRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const MapRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(MapRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  MapRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const MapRequest& from);
+  void MergeFrom(const MapRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef MapRequest_Buffers Buffers;
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 sid = 1;
+  inline bool has_sid() const;
+  inline void clear_sid();
+  static const int kSidFieldNumber = 1;
+  inline ::google::protobuf::uint32 sid() const;
+  inline void set_sid(::google::protobuf::uint32 value);
+
+  // repeated .com.trustonic.tee_proxy.MapRequest.Buffers buffers = 2;
+  inline int buffers_size() const;
+  inline void clear_buffers();
+  static const int kBuffersFieldNumber = 2;
+  inline const ::com::trustonic::tee_proxy::MapRequest_Buffers& buffers(int index) const;
+  inline ::com::trustonic::tee_proxy::MapRequest_Buffers* mutable_buffers(int index);
+  inline ::com::trustonic::tee_proxy::MapRequest_Buffers* add_buffers();
+  inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapRequest_Buffers >&
+      buffers() const;
+  inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapRequest_Buffers >*
+      mutable_buffers();
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.MapRequest)
+ private:
+  inline void set_has_sid();
+  inline void clear_has_sid();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapRequest_Buffers > buffers_;
+  ::google::protobuf::uint32 sid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static MapRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class MapResponse_Buffers : public ::google::protobuf::MessageLite {
+ public:
+  MapResponse_Buffers();
+  virtual ~MapResponse_Buffers();
+
+  MapResponse_Buffers(const MapResponse_Buffers& from);
+
+  inline MapResponse_Buffers& operator=(const MapResponse_Buffers& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const MapResponse_Buffers& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const MapResponse_Buffers* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(MapResponse_Buffers* other);
+
+  // implements Message ----------------------------------------------
+
+  MapResponse_Buffers* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const MapResponse_Buffers& from);
+  void MergeFrom(const MapResponse_Buffers& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint64 sva = 1;
+  inline bool has_sva() const;
+  inline void clear_sva();
+  static const int kSvaFieldNumber = 1;
+  inline ::google::protobuf::uint64 sva() const;
+  inline void set_sva(::google::protobuf::uint64 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.MapResponse.Buffers)
+ private:
+  inline void set_has_sva();
+  inline void clear_has_sva();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint64 sva_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static MapResponse_Buffers* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class MapResponse : public ::google::protobuf::MessageLite {
+ public:
+  MapResponse();
+  virtual ~MapResponse();
+
+  MapResponse(const MapResponse& from);
+
+  inline MapResponse& operator=(const MapResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const MapResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const MapResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(MapResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  MapResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const MapResponse& from);
+  void MergeFrom(const MapResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef MapResponse_Buffers Buffers;
+
+  // accessors -------------------------------------------------------
+
+  // repeated .com.trustonic.tee_proxy.MapResponse.Buffers buffers = 1;
+  inline int buffers_size() const;
+  inline void clear_buffers();
+  static const int kBuffersFieldNumber = 1;
+  inline const ::com::trustonic::tee_proxy::MapResponse_Buffers& buffers(int index) const;
+  inline ::com::trustonic::tee_proxy::MapResponse_Buffers* mutable_buffers(int index);
+  inline ::com::trustonic::tee_proxy::MapResponse_Buffers* add_buffers();
+  inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapResponse_Buffers >&
+      buffers() const;
+  inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapResponse_Buffers >*
+      mutable_buffers();
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.MapResponse)
+ private:
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapResponse_Buffers > buffers_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static MapResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class UnmapRequest_Buffers : public ::google::protobuf::MessageLite {
+ public:
+  UnmapRequest_Buffers();
+  virtual ~UnmapRequest_Buffers();
+
+  UnmapRequest_Buffers(const UnmapRequest_Buffers& from);
+
+  inline UnmapRequest_Buffers& operator=(const UnmapRequest_Buffers& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const UnmapRequest_Buffers& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const UnmapRequest_Buffers* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(UnmapRequest_Buffers* other);
+
+  // implements Message ----------------------------------------------
+
+  UnmapRequest_Buffers* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const UnmapRequest_Buffers& from);
+  void MergeFrom(const UnmapRequest_Buffers& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint64 sva = 1;
+  inline bool has_sva() const;
+  inline void clear_sva();
+  static const int kSvaFieldNumber = 1;
+  inline ::google::protobuf::uint64 sva() const;
+  inline void set_sva(::google::protobuf::uint64 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.UnmapRequest.Buffers)
+ private:
+  inline void set_has_sva();
+  inline void clear_has_sva();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint64 sva_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static UnmapRequest_Buffers* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class UnmapRequest : public ::google::protobuf::MessageLite {
+ public:
+  UnmapRequest();
+  virtual ~UnmapRequest();
+
+  UnmapRequest(const UnmapRequest& from);
+
+  inline UnmapRequest& operator=(const UnmapRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const UnmapRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const UnmapRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(UnmapRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  UnmapRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const UnmapRequest& from);
+  void MergeFrom(const UnmapRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  typedef UnmapRequest_Buffers Buffers;
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 sid = 1;
+  inline bool has_sid() const;
+  inline void clear_sid();
+  static const int kSidFieldNumber = 1;
+  inline ::google::protobuf::uint32 sid() const;
+  inline void set_sid(::google::protobuf::uint32 value);
+
+  // repeated .com.trustonic.tee_proxy.UnmapRequest.Buffers buffers = 2;
+  inline int buffers_size() const;
+  inline void clear_buffers();
+  static const int kBuffersFieldNumber = 2;
+  inline const ::com::trustonic::tee_proxy::UnmapRequest_Buffers& buffers(int index) const;
+  inline ::com::trustonic::tee_proxy::UnmapRequest_Buffers* mutable_buffers(int index);
+  inline ::com::trustonic::tee_proxy::UnmapRequest_Buffers* add_buffers();
+  inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::UnmapRequest_Buffers >&
+      buffers() const;
+  inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::UnmapRequest_Buffers >*
+      mutable_buffers();
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.UnmapRequest)
+ private:
+  inline void set_has_sid();
+  inline void clear_has_sid();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::UnmapRequest_Buffers > buffers_;
+  ::google::protobuf::uint32 sid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static UnmapRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class UnmapResponse : public ::google::protobuf::MessageLite {
+ public:
+  UnmapResponse();
+  virtual ~UnmapResponse();
+
+  UnmapResponse(const UnmapResponse& from);
+
+  inline UnmapResponse& operator=(const UnmapResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const UnmapResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const UnmapResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(UnmapResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  UnmapResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const UnmapResponse& from);
+  void MergeFrom(const UnmapResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.UnmapResponse)
+ private:
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static UnmapResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class GetErrorRequest : public ::google::protobuf::MessageLite {
+ public:
+  GetErrorRequest();
+  virtual ~GetErrorRequest();
+
+  GetErrorRequest(const GetErrorRequest& from);
+
+  inline GetErrorRequest& operator=(const GetErrorRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const GetErrorRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const GetErrorRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(GetErrorRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  GetErrorRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const GetErrorRequest& from);
+  void MergeFrom(const GetErrorRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 sid = 1;
+  inline bool has_sid() const;
+  inline void clear_sid();
+  static const int kSidFieldNumber = 1;
+  inline ::google::protobuf::uint32 sid() const;
+  inline void set_sid(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.GetErrorRequest)
+ private:
+  inline void set_has_sid();
+  inline void clear_has_sid();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 sid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static GetErrorRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class GetErrorResponse : public ::google::protobuf::MessageLite {
+ public:
+  GetErrorResponse();
+  virtual ~GetErrorResponse();
+
+  GetErrorResponse(const GetErrorResponse& from);
+
+  inline GetErrorResponse& operator=(const GetErrorResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const GetErrorResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const GetErrorResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(GetErrorResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  GetErrorResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const GetErrorResponse& from);
+  void MergeFrom(const GetErrorResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required sint32 exit_code = 1;
+  inline bool has_exit_code() const;
+  inline void clear_exit_code();
+  static const int kExitCodeFieldNumber = 1;
+  inline ::google::protobuf::int32 exit_code() const;
+  inline void set_exit_code(::google::protobuf::int32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.GetErrorResponse)
+ private:
+  inline void set_has_exit_code();
+  inline void clear_has_exit_code();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::int32 exit_code_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static GetErrorResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class GetVersionRequest : public ::google::protobuf::MessageLite {
+ public:
+  GetVersionRequest();
+  virtual ~GetVersionRequest();
+
+  GetVersionRequest(const GetVersionRequest& from);
+
+  inline GetVersionRequest& operator=(const GetVersionRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const GetVersionRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const GetVersionRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(GetVersionRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  GetVersionRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const GetVersionRequest& from);
+  void MergeFrom(const GetVersionRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.GetVersionRequest)
+ private:
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static GetVersionRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class GetVersionResponse : public ::google::protobuf::MessageLite {
+ public:
+  GetVersionResponse();
+  virtual ~GetVersionResponse();
+
+  GetVersionResponse(const GetVersionResponse& from);
+
+  inline GetVersionResponse& operator=(const GetVersionResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const GetVersionResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const GetVersionResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(GetVersionResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  GetVersionResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const GetVersionResponse& from);
+  void MergeFrom(const GetVersionResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required string product_id = 1;
+  inline bool has_product_id() const;
+  inline void clear_product_id();
+  static const int kProductIdFieldNumber = 1;
+  inline const ::std::string& product_id() const;
+  inline void set_product_id(const ::std::string& value);
+  inline void set_product_id(const char* value);
+  inline void set_product_id(const char* value, size_t size);
+  inline ::std::string* mutable_product_id();
+  inline ::std::string* release_product_id();
+  inline void set_allocated_product_id(::std::string* product_id);
+
+  // required uint32 mci = 2;
+  inline bool has_mci() const;
+  inline void clear_mci();
+  static const int kMciFieldNumber = 2;
+  inline ::google::protobuf::uint32 mci() const;
+  inline void set_mci(::google::protobuf::uint32 value);
+
+  // required uint32 so = 3;
+  inline bool has_so() const;
+  inline void clear_so();
+  static const int kSoFieldNumber = 3;
+  inline ::google::protobuf::uint32 so() const;
+  inline void set_so(::google::protobuf::uint32 value);
+
+  // required uint32 mclf = 4;
+  inline bool has_mclf() const;
+  inline void clear_mclf();
+  static const int kMclfFieldNumber = 4;
+  inline ::google::protobuf::uint32 mclf() const;
+  inline void set_mclf(::google::protobuf::uint32 value);
+
+  // required uint32 container = 5;
+  inline bool has_container() const;
+  inline void clear_container();
+  static const int kContainerFieldNumber = 5;
+  inline ::google::protobuf::uint32 container() const;
+  inline void set_container(::google::protobuf::uint32 value);
+
+  // required uint32 mc_config = 6;
+  inline bool has_mc_config() const;
+  inline void clear_mc_config();
+  static const int kMcConfigFieldNumber = 6;
+  inline ::google::protobuf::uint32 mc_config() const;
+  inline void set_mc_config(::google::protobuf::uint32 value);
+
+  // required uint32 tl_api = 7;
+  inline bool has_tl_api() const;
+  inline void clear_tl_api();
+  static const int kTlApiFieldNumber = 7;
+  inline ::google::protobuf::uint32 tl_api() const;
+  inline void set_tl_api(::google::protobuf::uint32 value);
+
+  // required uint32 dr_api = 8;
+  inline bool has_dr_api() const;
+  inline void clear_dr_api();
+  static const int kDrApiFieldNumber = 8;
+  inline ::google::protobuf::uint32 dr_api() const;
+  inline void set_dr_api(::google::protobuf::uint32 value);
+
+  // required uint32 nwd = 9;
+  inline bool has_nwd() const;
+  inline void clear_nwd();
+  static const int kNwdFieldNumber = 9;
+  inline ::google::protobuf::uint32 nwd() const;
+  inline void set_nwd(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.GetVersionResponse)
+ private:
+  inline void set_has_product_id();
+  inline void clear_has_product_id();
+  inline void set_has_mci();
+  inline void clear_has_mci();
+  inline void set_has_so();
+  inline void clear_has_so();
+  inline void set_has_mclf();
+  inline void clear_has_mclf();
+  inline void set_has_container();
+  inline void clear_has_container();
+  inline void set_has_mc_config();
+  inline void clear_has_mc_config();
+  inline void set_has_tl_api();
+  inline void clear_has_tl_api();
+  inline void set_has_dr_api();
+  inline void clear_has_dr_api();
+  inline void set_has_nwd();
+  inline void clear_has_nwd();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::std::string* product_id_;
+  ::google::protobuf::uint32 mci_;
+  ::google::protobuf::uint32 so_;
+  ::google::protobuf::uint32 mclf_;
+  ::google::protobuf::uint32 container_;
+  ::google::protobuf::uint32 mc_config_;
+  ::google::protobuf::uint32 tl_api_;
+  ::google::protobuf::uint32 dr_api_;
+  ::google::protobuf::uint32 nwd_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static GetVersionResponse* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class GpRequestCancellationRequest : public ::google::protobuf::MessageLite {
+ public:
+  GpRequestCancellationRequest();
+  virtual ~GpRequestCancellationRequest();
+
+  GpRequestCancellationRequest(const GpRequestCancellationRequest& from);
+
+  inline GpRequestCancellationRequest& operator=(const GpRequestCancellationRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const GpRequestCancellationRequest& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const GpRequestCancellationRequest* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(GpRequestCancellationRequest* other);
+
+  // implements Message ----------------------------------------------
+
+  GpRequestCancellationRequest* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const GpRequestCancellationRequest& from);
+  void MergeFrom(const GpRequestCancellationRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // required uint32 sid = 1;
+  inline bool has_sid() const;
+  inline void clear_sid();
+  static const int kSidFieldNumber = 1;
+  inline ::google::protobuf::uint32 sid() const;
+  inline void set_sid(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.GpRequestCancellationRequest)
+ private:
+  inline void set_has_sid();
+  inline void clear_has_sid();
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  ::google::protobuf::uint32 sid_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static GpRequestCancellationRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class GpRequestCancellationResponse : public ::google::protobuf::MessageLite {
+ public:
+  GpRequestCancellationResponse();
+  virtual ~GpRequestCancellationResponse();
+
+  GpRequestCancellationResponse(const GpRequestCancellationResponse& from);
+
+  inline GpRequestCancellationResponse& operator=(const GpRequestCancellationResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+
+  inline const ::std::string& unknown_fields() const {
+    return _unknown_fields_;
+  }
+
+  inline ::std::string* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+
+  static const GpRequestCancellationResponse& default_instance();
+
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  // Returns the internal default instance pointer. This function can
+  // return NULL thus should not be used by the user. This is intended
+  // for Protobuf internal code. Please use default_instance() declared
+  // above instead.
+  static inline const GpRequestCancellationResponse* internal_default_instance() {
+    return default_instance_;
+  }
+  #endif
+
+  void Swap(GpRequestCancellationResponse* other);
+
+  // implements Message ----------------------------------------------
+
+  GpRequestCancellationResponse* New() const;
+  void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
+  void CopyFrom(const GpRequestCancellationResponse& from);
+  void MergeFrom(const GpRequestCancellationResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  void DiscardUnknownFields();
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  ::std::string GetTypeName() const;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:com.trustonic.tee_proxy.GpRequestCancellationResponse)
+ private:
+
+  ::std::string _unknown_fields_;
+
+  ::google::protobuf::uint32 _has_bits_[1];
+  mutable int _cached_size_;
+  #ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
+  friend void  protobuf_AddDesc_mc_2eproto_impl();
+  #else
+  friend void  protobuf_AddDesc_mc_2eproto();
+  #endif
+  friend void protobuf_AssignDesc_mc_2eproto();
+  friend void protobuf_ShutdownFile_mc_2eproto();
+
+  void InitAsDefaultInstance();
+  static GpRequestCancellationResponse* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+// OpenSessionRequest
+
+// required bytes uuid = 1;
+inline bool OpenSessionRequest::has_uuid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void OpenSessionRequest::set_has_uuid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void OpenSessionRequest::clear_has_uuid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void OpenSessionRequest::clear_uuid() {
+  if (uuid_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    uuid_->clear();
+  }
+  clear_has_uuid();
+}
+inline const ::std::string& OpenSessionRequest::uuid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenSessionRequest.uuid)
+  return *uuid_;
+}
+inline void OpenSessionRequest::set_uuid(const ::std::string& value) {
+  set_has_uuid();
+  if (uuid_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    uuid_ = new ::std::string;
+  }
+  uuid_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenSessionRequest.uuid)
+}
+inline void OpenSessionRequest::set_uuid(const char* value) {
+  set_has_uuid();
+  if (uuid_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    uuid_ = new ::std::string;
+  }
+  uuid_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.OpenSessionRequest.uuid)
+}
+inline void OpenSessionRequest::set_uuid(const void* value, size_t size) {
+  set_has_uuid();
+  if (uuid_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    uuid_ = new ::std::string;
+  }
+  uuid_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.OpenSessionRequest.uuid)
+}
+inline ::std::string* OpenSessionRequest::mutable_uuid() {
+  set_has_uuid();
+  if (uuid_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    uuid_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.OpenSessionRequest.uuid)
+  return uuid_;
+}
+inline ::std::string* OpenSessionRequest::release_uuid() {
+  clear_has_uuid();
+  if (uuid_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = uuid_;
+    uuid_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void OpenSessionRequest::set_allocated_uuid(::std::string* uuid) {
+  if (uuid_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete uuid_;
+  }
+  if (uuid) {
+    set_has_uuid();
+    uuid_ = uuid;
+  } else {
+    clear_has_uuid();
+    uuid_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.OpenSessionRequest.uuid)
+}
+
+// required bool is_gp_uuid = 2;
+inline bool OpenSessionRequest::has_is_gp_uuid() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void OpenSessionRequest::set_has_is_gp_uuid() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void OpenSessionRequest::clear_has_is_gp_uuid() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void OpenSessionRequest::clear_is_gp_uuid() {
+  is_gp_uuid_ = false;
+  clear_has_is_gp_uuid();
+}
+inline bool OpenSessionRequest::is_gp_uuid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenSessionRequest.is_gp_uuid)
+  return is_gp_uuid_;
+}
+inline void OpenSessionRequest::set_is_gp_uuid(bool value) {
+  set_has_is_gp_uuid();
+  is_gp_uuid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenSessionRequest.is_gp_uuid)
+}
+
+// optional bytes tci = 3;
+inline bool OpenSessionRequest::has_tci() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void OpenSessionRequest::set_has_tci() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void OpenSessionRequest::clear_has_tci() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void OpenSessionRequest::clear_tci() {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_->clear();
+  }
+  clear_has_tci();
+}
+inline const ::std::string& OpenSessionRequest::tci() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenSessionRequest.tci)
+  return *tci_;
+}
+inline void OpenSessionRequest::set_tci(const ::std::string& value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenSessionRequest.tci)
+}
+inline void OpenSessionRequest::set_tci(const char* value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.OpenSessionRequest.tci)
+}
+inline void OpenSessionRequest::set_tci(const void* value, size_t size) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.OpenSessionRequest.tci)
+}
+inline ::std::string* OpenSessionRequest::mutable_tci() {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.OpenSessionRequest.tci)
+  return tci_;
+}
+inline ::std::string* OpenSessionRequest::release_tci() {
+  clear_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = tci_;
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void OpenSessionRequest::set_allocated_tci(::std::string* tci) {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  if (tci) {
+    set_has_tci();
+    tci_ = tci;
+  } else {
+    clear_has_tci();
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.OpenSessionRequest.tci)
+}
+
+// required .com.trustonic.tee_proxy.LoginType login_type = 4;
+inline bool OpenSessionRequest::has_login_type() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void OpenSessionRequest::set_has_login_type() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void OpenSessionRequest::clear_has_login_type() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void OpenSessionRequest::clear_login_type() {
+  login_type_ = 0;
+  clear_has_login_type();
+}
+inline ::com::trustonic::tee_proxy::LoginType OpenSessionRequest::login_type() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenSessionRequest.login_type)
+  return static_cast< ::com::trustonic::tee_proxy::LoginType >(login_type_);
+}
+inline void OpenSessionRequest::set_login_type(::com::trustonic::tee_proxy::LoginType value) {
+  assert(::com::trustonic::tee_proxy::LoginType_IsValid(value));
+  set_has_login_type();
+  login_type_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenSessionRequest.login_type)
+}
+
+// required bytes login_data = 5;
+inline bool OpenSessionRequest::has_login_data() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void OpenSessionRequest::set_has_login_data() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void OpenSessionRequest::clear_has_login_data() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void OpenSessionRequest::clear_login_data() {
+  if (login_data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    login_data_->clear();
+  }
+  clear_has_login_data();
+}
+inline const ::std::string& OpenSessionRequest::login_data() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenSessionRequest.login_data)
+  return *login_data_;
+}
+inline void OpenSessionRequest::set_login_data(const ::std::string& value) {
+  set_has_login_data();
+  if (login_data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    login_data_ = new ::std::string;
+  }
+  login_data_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenSessionRequest.login_data)
+}
+inline void OpenSessionRequest::set_login_data(const char* value) {
+  set_has_login_data();
+  if (login_data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    login_data_ = new ::std::string;
+  }
+  login_data_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.OpenSessionRequest.login_data)
+}
+inline void OpenSessionRequest::set_login_data(const void* value, size_t size) {
+  set_has_login_data();
+  if (login_data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    login_data_ = new ::std::string;
+  }
+  login_data_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.OpenSessionRequest.login_data)
+}
+inline ::std::string* OpenSessionRequest::mutable_login_data() {
+  set_has_login_data();
+  if (login_data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    login_data_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.OpenSessionRequest.login_data)
+  return login_data_;
+}
+inline ::std::string* OpenSessionRequest::release_login_data() {
+  clear_has_login_data();
+  if (login_data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = login_data_;
+    login_data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void OpenSessionRequest::set_allocated_login_data(::std::string* login_data) {
+  if (login_data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete login_data_;
+  }
+  if (login_data) {
+    set_has_login_data();
+    login_data_ = login_data;
+  } else {
+    clear_has_login_data();
+    login_data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.OpenSessionRequest.login_data)
+}
+
+// -------------------------------------------------------------------
+
+// OpenSessionResponse
+
+// required uint32 id = 1;
+inline bool OpenSessionResponse::has_id() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void OpenSessionResponse::set_has_id() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void OpenSessionResponse::clear_has_id() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void OpenSessionResponse::clear_id() {
+  id_ = 0u;
+  clear_has_id();
+}
+inline ::google::protobuf::uint32 OpenSessionResponse::id() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenSessionResponse.id)
+  return id_;
+}
+inline void OpenSessionResponse::set_id(::google::protobuf::uint32 value) {
+  set_has_id();
+  id_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenSessionResponse.id)
+}
+
+// -------------------------------------------------------------------
+
+// OpenTrustletRequest
+
+// required uint32 spid = 1;
+inline bool OpenTrustletRequest::has_spid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void OpenTrustletRequest::set_has_spid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void OpenTrustletRequest::clear_has_spid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void OpenTrustletRequest::clear_spid() {
+  spid_ = 0u;
+  clear_has_spid();
+}
+inline ::google::protobuf::uint32 OpenTrustletRequest::spid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenTrustletRequest.spid)
+  return spid_;
+}
+inline void OpenTrustletRequest::set_spid(::google::protobuf::uint32 value) {
+  set_has_spid();
+  spid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenTrustletRequest.spid)
+}
+
+// required bytes trustapp = 2;
+inline bool OpenTrustletRequest::has_trustapp() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void OpenTrustletRequest::set_has_trustapp() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void OpenTrustletRequest::clear_has_trustapp() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void OpenTrustletRequest::clear_trustapp() {
+  if (trustapp_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    trustapp_->clear();
+  }
+  clear_has_trustapp();
+}
+inline const ::std::string& OpenTrustletRequest::trustapp() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenTrustletRequest.trustapp)
+  return *trustapp_;
+}
+inline void OpenTrustletRequest::set_trustapp(const ::std::string& value) {
+  set_has_trustapp();
+  if (trustapp_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    trustapp_ = new ::std::string;
+  }
+  trustapp_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenTrustletRequest.trustapp)
+}
+inline void OpenTrustletRequest::set_trustapp(const char* value) {
+  set_has_trustapp();
+  if (trustapp_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    trustapp_ = new ::std::string;
+  }
+  trustapp_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.OpenTrustletRequest.trustapp)
+}
+inline void OpenTrustletRequest::set_trustapp(const void* value, size_t size) {
+  set_has_trustapp();
+  if (trustapp_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    trustapp_ = new ::std::string;
+  }
+  trustapp_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.OpenTrustletRequest.trustapp)
+}
+inline ::std::string* OpenTrustletRequest::mutable_trustapp() {
+  set_has_trustapp();
+  if (trustapp_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    trustapp_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.OpenTrustletRequest.trustapp)
+  return trustapp_;
+}
+inline ::std::string* OpenTrustletRequest::release_trustapp() {
+  clear_has_trustapp();
+  if (trustapp_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = trustapp_;
+    trustapp_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void OpenTrustletRequest::set_allocated_trustapp(::std::string* trustapp) {
+  if (trustapp_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete trustapp_;
+  }
+  if (trustapp) {
+    set_has_trustapp();
+    trustapp_ = trustapp;
+  } else {
+    clear_has_trustapp();
+    trustapp_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.OpenTrustletRequest.trustapp)
+}
+
+// optional bytes tci = 3;
+inline bool OpenTrustletRequest::has_tci() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void OpenTrustletRequest::set_has_tci() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void OpenTrustletRequest::clear_has_tci() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void OpenTrustletRequest::clear_tci() {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_->clear();
+  }
+  clear_has_tci();
+}
+inline const ::std::string& OpenTrustletRequest::tci() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenTrustletRequest.tci)
+  return *tci_;
+}
+inline void OpenTrustletRequest::set_tci(const ::std::string& value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenTrustletRequest.tci)
+}
+inline void OpenTrustletRequest::set_tci(const char* value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.OpenTrustletRequest.tci)
+}
+inline void OpenTrustletRequest::set_tci(const void* value, size_t size) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.OpenTrustletRequest.tci)
+}
+inline ::std::string* OpenTrustletRequest::mutable_tci() {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.OpenTrustletRequest.tci)
+  return tci_;
+}
+inline ::std::string* OpenTrustletRequest::release_tci() {
+  clear_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = tci_;
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void OpenTrustletRequest::set_allocated_tci(::std::string* tci) {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  if (tci) {
+    set_has_tci();
+    tci_ = tci;
+  } else {
+    clear_has_tci();
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.OpenTrustletRequest.tci)
+}
+
+// -------------------------------------------------------------------
+
+// OpenTrustletResponse
+
+// required uint32 id = 1;
+inline bool OpenTrustletResponse::has_id() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void OpenTrustletResponse::set_has_id() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void OpenTrustletResponse::clear_has_id() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void OpenTrustletResponse::clear_id() {
+  id_ = 0u;
+  clear_has_id();
+}
+inline ::google::protobuf::uint32 OpenTrustletResponse::id() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.OpenTrustletResponse.id)
+  return id_;
+}
+inline void OpenTrustletResponse::set_id(::google::protobuf::uint32 value) {
+  set_has_id();
+  id_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.OpenTrustletResponse.id)
+}
+
+// -------------------------------------------------------------------
+
+// CloseSessionRequest
+
+// required uint32 id = 1;
+inline bool CloseSessionRequest::has_id() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void CloseSessionRequest::set_has_id() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void CloseSessionRequest::clear_has_id() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void CloseSessionRequest::clear_id() {
+  id_ = 0u;
+  clear_has_id();
+}
+inline ::google::protobuf::uint32 CloseSessionRequest::id() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.CloseSessionRequest.id)
+  return id_;
+}
+inline void CloseSessionRequest::set_id(::google::protobuf::uint32 value) {
+  set_has_id();
+  id_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.CloseSessionRequest.id)
+}
+
+// -------------------------------------------------------------------
+
+// CloseSessionResponse
+
+// -------------------------------------------------------------------
+
+// NotifyRequest_Buffers
+
+// required uint64 sva = 1;
+inline bool NotifyRequest_Buffers::has_sva() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void NotifyRequest_Buffers::set_has_sva() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void NotifyRequest_Buffers::clear_has_sva() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void NotifyRequest_Buffers::clear_sva() {
+  sva_ = GOOGLE_ULONGLONG(0);
+  clear_has_sva();
+}
+inline ::google::protobuf::uint64 NotifyRequest_Buffers::sva() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.NotifyRequest.Buffers.sva)
+  return sva_;
+}
+inline void NotifyRequest_Buffers::set_sva(::google::protobuf::uint64 value) {
+  set_has_sva();
+  sva_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.NotifyRequest.Buffers.sva)
+}
+
+// required bytes data = 2;
+inline bool NotifyRequest_Buffers::has_data() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void NotifyRequest_Buffers::set_has_data() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void NotifyRequest_Buffers::clear_has_data() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void NotifyRequest_Buffers::clear_data() {
+  if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_->clear();
+  }
+  clear_has_data();
+}
+inline const ::std::string& NotifyRequest_Buffers::data() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.NotifyRequest.Buffers.data)
+  return *data_;
+}
+inline void NotifyRequest_Buffers::set_data(const ::std::string& value) {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.NotifyRequest.Buffers.data)
+}
+inline void NotifyRequest_Buffers::set_data(const char* value) {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.NotifyRequest.Buffers.data)
+}
+inline void NotifyRequest_Buffers::set_data(const void* value, size_t size) {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  data_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.NotifyRequest.Buffers.data)
+}
+inline ::std::string* NotifyRequest_Buffers::mutable_data() {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.NotifyRequest.Buffers.data)
+  return data_;
+}
+inline ::std::string* NotifyRequest_Buffers::release_data() {
+  clear_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = data_;
+    data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void NotifyRequest_Buffers::set_allocated_data(::std::string* data) {
+  if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete data_;
+  }
+  if (data) {
+    set_has_data();
+    data_ = data;
+  } else {
+    clear_has_data();
+    data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.NotifyRequest.Buffers.data)
+}
+
+// -------------------------------------------------------------------
+
+// NotifyRequest
+
+// required uint32 sid = 1;
+inline bool NotifyRequest::has_sid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void NotifyRequest::set_has_sid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void NotifyRequest::clear_has_sid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void NotifyRequest::clear_sid() {
+  sid_ = 0u;
+  clear_has_sid();
+}
+inline ::google::protobuf::uint32 NotifyRequest::sid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.NotifyRequest.sid)
+  return sid_;
+}
+inline void NotifyRequest::set_sid(::google::protobuf::uint32 value) {
+  set_has_sid();
+  sid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.NotifyRequest.sid)
+}
+
+// optional bytes tci = 2;
+inline bool NotifyRequest::has_tci() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void NotifyRequest::set_has_tci() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void NotifyRequest::clear_has_tci() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void NotifyRequest::clear_tci() {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_->clear();
+  }
+  clear_has_tci();
+}
+inline const ::std::string& NotifyRequest::tci() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.NotifyRequest.tci)
+  return *tci_;
+}
+inline void NotifyRequest::set_tci(const ::std::string& value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.NotifyRequest.tci)
+}
+inline void NotifyRequest::set_tci(const char* value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.NotifyRequest.tci)
+}
+inline void NotifyRequest::set_tci(const void* value, size_t size) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.NotifyRequest.tci)
+}
+inline ::std::string* NotifyRequest::mutable_tci() {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.NotifyRequest.tci)
+  return tci_;
+}
+inline ::std::string* NotifyRequest::release_tci() {
+  clear_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = tci_;
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void NotifyRequest::set_allocated_tci(::std::string* tci) {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  if (tci) {
+    set_has_tci();
+    tci_ = tci;
+  } else {
+    clear_has_tci();
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.NotifyRequest.tci)
+}
+
+// repeated .com.trustonic.tee_proxy.NotifyRequest.Buffers buffers = 3;
+inline int NotifyRequest::buffers_size() const {
+  return buffers_.size();
+}
+inline void NotifyRequest::clear_buffers() {
+  buffers_.Clear();
+}
+inline const ::com::trustonic::tee_proxy::NotifyRequest_Buffers& NotifyRequest::buffers(int index) const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.NotifyRequest.buffers)
+  return buffers_.Get(index);
+}
+inline ::com::trustonic::tee_proxy::NotifyRequest_Buffers* NotifyRequest::mutable_buffers(int index) {
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.NotifyRequest.buffers)
+  return buffers_.Mutable(index);
+}
+inline ::com::trustonic::tee_proxy::NotifyRequest_Buffers* NotifyRequest::add_buffers() {
+  // @@protoc_insertion_point(field_add:com.trustonic.tee_proxy.NotifyRequest.buffers)
+  return buffers_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::NotifyRequest_Buffers >&
+NotifyRequest::buffers() const {
+  // @@protoc_insertion_point(field_list:com.trustonic.tee_proxy.NotifyRequest.buffers)
+  return buffers_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::NotifyRequest_Buffers >*
+NotifyRequest::mutable_buffers() {
+  // @@protoc_insertion_point(field_mutable_list:com.trustonic.tee_proxy.NotifyRequest.buffers)
+  return &buffers_;
+}
+
+// -------------------------------------------------------------------
+
+// NotifyResponse
+
+// -------------------------------------------------------------------
+
+// WaitNotificationRequest
+
+// required uint32 sid = 1;
+inline bool WaitNotificationRequest::has_sid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void WaitNotificationRequest::set_has_sid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void WaitNotificationRequest::clear_has_sid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void WaitNotificationRequest::clear_sid() {
+  sid_ = 0u;
+  clear_has_sid();
+}
+inline ::google::protobuf::uint32 WaitNotificationRequest::sid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationRequest.sid)
+  return sid_;
+}
+inline void WaitNotificationRequest::set_sid(::google::protobuf::uint32 value) {
+  set_has_sid();
+  sid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.WaitNotificationRequest.sid)
+}
+
+// required sint32 timeout = 2;
+inline bool WaitNotificationRequest::has_timeout() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void WaitNotificationRequest::set_has_timeout() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void WaitNotificationRequest::clear_has_timeout() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void WaitNotificationRequest::clear_timeout() {
+  timeout_ = 0;
+  clear_has_timeout();
+}
+inline ::google::protobuf::int32 WaitNotificationRequest::timeout() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationRequest.timeout)
+  return timeout_;
+}
+inline void WaitNotificationRequest::set_timeout(::google::protobuf::int32 value) {
+  set_has_timeout();
+  timeout_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.WaitNotificationRequest.timeout)
+}
+
+// required bool partial = 3;
+inline bool WaitNotificationRequest::has_partial() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void WaitNotificationRequest::set_has_partial() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void WaitNotificationRequest::clear_has_partial() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void WaitNotificationRequest::clear_partial() {
+  partial_ = false;
+  clear_has_partial();
+}
+inline bool WaitNotificationRequest::partial() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationRequest.partial)
+  return partial_;
+}
+inline void WaitNotificationRequest::set_partial(bool value) {
+  set_has_partial();
+  partial_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.WaitNotificationRequest.partial)
+}
+
+// -------------------------------------------------------------------
+
+// WaitNotificationResponse_Buffers
+
+// required uint64 sva = 1;
+inline bool WaitNotificationResponse_Buffers::has_sva() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void WaitNotificationResponse_Buffers::set_has_sva() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void WaitNotificationResponse_Buffers::clear_has_sva() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void WaitNotificationResponse_Buffers::clear_sva() {
+  sva_ = GOOGLE_ULONGLONG(0);
+  clear_has_sva();
+}
+inline ::google::protobuf::uint64 WaitNotificationResponse_Buffers::sva() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.sva)
+  return sva_;
+}
+inline void WaitNotificationResponse_Buffers::set_sva(::google::protobuf::uint64 value) {
+  set_has_sva();
+  sva_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.sva)
+}
+
+// required bytes data = 2;
+inline bool WaitNotificationResponse_Buffers::has_data() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void WaitNotificationResponse_Buffers::set_has_data() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void WaitNotificationResponse_Buffers::clear_has_data() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void WaitNotificationResponse_Buffers::clear_data() {
+  if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_->clear();
+  }
+  clear_has_data();
+}
+inline const ::std::string& WaitNotificationResponse_Buffers::data() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.data)
+  return *data_;
+}
+inline void WaitNotificationResponse_Buffers::set_data(const ::std::string& value) {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.data)
+}
+inline void WaitNotificationResponse_Buffers::set_data(const char* value) {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.data)
+}
+inline void WaitNotificationResponse_Buffers::set_data(const void* value, size_t size) {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  data_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.data)
+}
+inline ::std::string* WaitNotificationResponse_Buffers::mutable_data() {
+  set_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    data_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.data)
+  return data_;
+}
+inline ::std::string* WaitNotificationResponse_Buffers::release_data() {
+  clear_has_data();
+  if (data_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = data_;
+    data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void WaitNotificationResponse_Buffers::set_allocated_data(::std::string* data) {
+  if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete data_;
+  }
+  if (data) {
+    set_has_data();
+    data_ = data;
+  } else {
+    clear_has_data();
+    data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.WaitNotificationResponse.Buffers.data)
+}
+
+// -------------------------------------------------------------------
+
+// WaitNotificationResponse
+
+// optional bytes tci = 1;
+inline bool WaitNotificationResponse::has_tci() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void WaitNotificationResponse::set_has_tci() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void WaitNotificationResponse::clear_has_tci() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void WaitNotificationResponse::clear_tci() {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_->clear();
+  }
+  clear_has_tci();
+}
+inline const ::std::string& WaitNotificationResponse::tci() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationResponse.tci)
+  return *tci_;
+}
+inline void WaitNotificationResponse::set_tci(const ::std::string& value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.WaitNotificationResponse.tci)
+}
+inline void WaitNotificationResponse::set_tci(const char* value) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.WaitNotificationResponse.tci)
+}
+inline void WaitNotificationResponse::set_tci(const void* value, size_t size) {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  tci_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.WaitNotificationResponse.tci)
+}
+inline ::std::string* WaitNotificationResponse::mutable_tci() {
+  set_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    tci_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.WaitNotificationResponse.tci)
+  return tci_;
+}
+inline ::std::string* WaitNotificationResponse::release_tci() {
+  clear_has_tci();
+  if (tci_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = tci_;
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void WaitNotificationResponse::set_allocated_tci(::std::string* tci) {
+  if (tci_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete tci_;
+  }
+  if (tci) {
+    set_has_tci();
+    tci_ = tci;
+  } else {
+    clear_has_tci();
+    tci_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.WaitNotificationResponse.tci)
+}
+
+// repeated .com.trustonic.tee_proxy.WaitNotificationResponse.Buffers buffers = 2;
+inline int WaitNotificationResponse::buffers_size() const {
+  return buffers_.size();
+}
+inline void WaitNotificationResponse::clear_buffers() {
+  buffers_.Clear();
+}
+inline const ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers& WaitNotificationResponse::buffers(int index) const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.WaitNotificationResponse.buffers)
+  return buffers_.Get(index);
+}
+inline ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers* WaitNotificationResponse::mutable_buffers(int index) {
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.WaitNotificationResponse.buffers)
+  return buffers_.Mutable(index);
+}
+inline ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers* WaitNotificationResponse::add_buffers() {
+  // @@protoc_insertion_point(field_add:com.trustonic.tee_proxy.WaitNotificationResponse.buffers)
+  return buffers_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers >&
+WaitNotificationResponse::buffers() const {
+  // @@protoc_insertion_point(field_list:com.trustonic.tee_proxy.WaitNotificationResponse.buffers)
+  return buffers_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::WaitNotificationResponse_Buffers >*
+WaitNotificationResponse::mutable_buffers() {
+  // @@protoc_insertion_point(field_mutable_list:com.trustonic.tee_proxy.WaitNotificationResponse.buffers)
+  return &buffers_;
+}
+
+// -------------------------------------------------------------------
+
+// MapRequest_Buffers
+
+// required uint32 len = 1;
+inline bool MapRequest_Buffers::has_len() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MapRequest_Buffers::set_has_len() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MapRequest_Buffers::clear_has_len() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void MapRequest_Buffers::clear_len() {
+  len_ = 0u;
+  clear_has_len();
+}
+inline ::google::protobuf::uint32 MapRequest_Buffers::len() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.MapRequest.Buffers.len)
+  return len_;
+}
+inline void MapRequest_Buffers::set_len(::google::protobuf::uint32 value) {
+  set_has_len();
+  len_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.MapRequest.Buffers.len)
+}
+
+// required uint32 flags = 2;
+inline bool MapRequest_Buffers::has_flags() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void MapRequest_Buffers::set_has_flags() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void MapRequest_Buffers::clear_has_flags() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void MapRequest_Buffers::clear_flags() {
+  flags_ = 0u;
+  clear_has_flags();
+}
+inline ::google::protobuf::uint32 MapRequest_Buffers::flags() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.MapRequest.Buffers.flags)
+  return flags_;
+}
+inline void MapRequest_Buffers::set_flags(::google::protobuf::uint32 value) {
+  set_has_flags();
+  flags_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.MapRequest.Buffers.flags)
+}
+
+// -------------------------------------------------------------------
+
+// MapRequest
+
+// required uint32 sid = 1;
+inline bool MapRequest::has_sid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MapRequest::set_has_sid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MapRequest::clear_has_sid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void MapRequest::clear_sid() {
+  sid_ = 0u;
+  clear_has_sid();
+}
+inline ::google::protobuf::uint32 MapRequest::sid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.MapRequest.sid)
+  return sid_;
+}
+inline void MapRequest::set_sid(::google::protobuf::uint32 value) {
+  set_has_sid();
+  sid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.MapRequest.sid)
+}
+
+// repeated .com.trustonic.tee_proxy.MapRequest.Buffers buffers = 2;
+inline int MapRequest::buffers_size() const {
+  return buffers_.size();
+}
+inline void MapRequest::clear_buffers() {
+  buffers_.Clear();
+}
+inline const ::com::trustonic::tee_proxy::MapRequest_Buffers& MapRequest::buffers(int index) const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.MapRequest.buffers)
+  return buffers_.Get(index);
+}
+inline ::com::trustonic::tee_proxy::MapRequest_Buffers* MapRequest::mutable_buffers(int index) {
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.MapRequest.buffers)
+  return buffers_.Mutable(index);
+}
+inline ::com::trustonic::tee_proxy::MapRequest_Buffers* MapRequest::add_buffers() {
+  // @@protoc_insertion_point(field_add:com.trustonic.tee_proxy.MapRequest.buffers)
+  return buffers_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapRequest_Buffers >&
+MapRequest::buffers() const {
+  // @@protoc_insertion_point(field_list:com.trustonic.tee_proxy.MapRequest.buffers)
+  return buffers_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapRequest_Buffers >*
+MapRequest::mutable_buffers() {
+  // @@protoc_insertion_point(field_mutable_list:com.trustonic.tee_proxy.MapRequest.buffers)
+  return &buffers_;
+}
+
+// -------------------------------------------------------------------
+
+// MapResponse_Buffers
+
+// required uint64 sva = 1;
+inline bool MapResponse_Buffers::has_sva() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void MapResponse_Buffers::set_has_sva() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void MapResponse_Buffers::clear_has_sva() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void MapResponse_Buffers::clear_sva() {
+  sva_ = GOOGLE_ULONGLONG(0);
+  clear_has_sva();
+}
+inline ::google::protobuf::uint64 MapResponse_Buffers::sva() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.MapResponse.Buffers.sva)
+  return sva_;
+}
+inline void MapResponse_Buffers::set_sva(::google::protobuf::uint64 value) {
+  set_has_sva();
+  sva_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.MapResponse.Buffers.sva)
+}
+
+// -------------------------------------------------------------------
+
+// MapResponse
+
+// repeated .com.trustonic.tee_proxy.MapResponse.Buffers buffers = 1;
+inline int MapResponse::buffers_size() const {
+  return buffers_.size();
+}
+inline void MapResponse::clear_buffers() {
+  buffers_.Clear();
+}
+inline const ::com::trustonic::tee_proxy::MapResponse_Buffers& MapResponse::buffers(int index) const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.MapResponse.buffers)
+  return buffers_.Get(index);
+}
+inline ::com::trustonic::tee_proxy::MapResponse_Buffers* MapResponse::mutable_buffers(int index) {
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.MapResponse.buffers)
+  return buffers_.Mutable(index);
+}
+inline ::com::trustonic::tee_proxy::MapResponse_Buffers* MapResponse::add_buffers() {
+  // @@protoc_insertion_point(field_add:com.trustonic.tee_proxy.MapResponse.buffers)
+  return buffers_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapResponse_Buffers >&
+MapResponse::buffers() const {
+  // @@protoc_insertion_point(field_list:com.trustonic.tee_proxy.MapResponse.buffers)
+  return buffers_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::MapResponse_Buffers >*
+MapResponse::mutable_buffers() {
+  // @@protoc_insertion_point(field_mutable_list:com.trustonic.tee_proxy.MapResponse.buffers)
+  return &buffers_;
+}
+
+// -------------------------------------------------------------------
+
+// UnmapRequest_Buffers
+
+// required uint64 sva = 1;
+inline bool UnmapRequest_Buffers::has_sva() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void UnmapRequest_Buffers::set_has_sva() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void UnmapRequest_Buffers::clear_has_sva() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void UnmapRequest_Buffers::clear_sva() {
+  sva_ = GOOGLE_ULONGLONG(0);
+  clear_has_sva();
+}
+inline ::google::protobuf::uint64 UnmapRequest_Buffers::sva() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.UnmapRequest.Buffers.sva)
+  return sva_;
+}
+inline void UnmapRequest_Buffers::set_sva(::google::protobuf::uint64 value) {
+  set_has_sva();
+  sva_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.UnmapRequest.Buffers.sva)
+}
+
+// -------------------------------------------------------------------
+
+// UnmapRequest
+
+// required uint32 sid = 1;
+inline bool UnmapRequest::has_sid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void UnmapRequest::set_has_sid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void UnmapRequest::clear_has_sid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void UnmapRequest::clear_sid() {
+  sid_ = 0u;
+  clear_has_sid();
+}
+inline ::google::protobuf::uint32 UnmapRequest::sid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.UnmapRequest.sid)
+  return sid_;
+}
+inline void UnmapRequest::set_sid(::google::protobuf::uint32 value) {
+  set_has_sid();
+  sid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.UnmapRequest.sid)
+}
+
+// repeated .com.trustonic.tee_proxy.UnmapRequest.Buffers buffers = 2;
+inline int UnmapRequest::buffers_size() const {
+  return buffers_.size();
+}
+inline void UnmapRequest::clear_buffers() {
+  buffers_.Clear();
+}
+inline const ::com::trustonic::tee_proxy::UnmapRequest_Buffers& UnmapRequest::buffers(int index) const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.UnmapRequest.buffers)
+  return buffers_.Get(index);
+}
+inline ::com::trustonic::tee_proxy::UnmapRequest_Buffers* UnmapRequest::mutable_buffers(int index) {
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.UnmapRequest.buffers)
+  return buffers_.Mutable(index);
+}
+inline ::com::trustonic::tee_proxy::UnmapRequest_Buffers* UnmapRequest::add_buffers() {
+  // @@protoc_insertion_point(field_add:com.trustonic.tee_proxy.UnmapRequest.buffers)
+  return buffers_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::UnmapRequest_Buffers >&
+UnmapRequest::buffers() const {
+  // @@protoc_insertion_point(field_list:com.trustonic.tee_proxy.UnmapRequest.buffers)
+  return buffers_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::com::trustonic::tee_proxy::UnmapRequest_Buffers >*
+UnmapRequest::mutable_buffers() {
+  // @@protoc_insertion_point(field_mutable_list:com.trustonic.tee_proxy.UnmapRequest.buffers)
+  return &buffers_;
+}
+
+// -------------------------------------------------------------------
+
+// UnmapResponse
+
+// -------------------------------------------------------------------
+
+// GetErrorRequest
+
+// required uint32 sid = 1;
+inline bool GetErrorRequest::has_sid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void GetErrorRequest::set_has_sid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void GetErrorRequest::clear_has_sid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void GetErrorRequest::clear_sid() {
+  sid_ = 0u;
+  clear_has_sid();
+}
+inline ::google::protobuf::uint32 GetErrorRequest::sid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetErrorRequest.sid)
+  return sid_;
+}
+inline void GetErrorRequest::set_sid(::google::protobuf::uint32 value) {
+  set_has_sid();
+  sid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetErrorRequest.sid)
+}
+
+// -------------------------------------------------------------------
+
+// GetErrorResponse
+
+// required sint32 exit_code = 1;
+inline bool GetErrorResponse::has_exit_code() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void GetErrorResponse::set_has_exit_code() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void GetErrorResponse::clear_has_exit_code() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void GetErrorResponse::clear_exit_code() {
+  exit_code_ = 0;
+  clear_has_exit_code();
+}
+inline ::google::protobuf::int32 GetErrorResponse::exit_code() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetErrorResponse.exit_code)
+  return exit_code_;
+}
+inline void GetErrorResponse::set_exit_code(::google::protobuf::int32 value) {
+  set_has_exit_code();
+  exit_code_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetErrorResponse.exit_code)
+}
+
+// -------------------------------------------------------------------
+
+// GetVersionRequest
+
+// -------------------------------------------------------------------
+
+// GetVersionResponse
+
+// required string product_id = 1;
+inline bool GetVersionResponse::has_product_id() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void GetVersionResponse::set_has_product_id() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void GetVersionResponse::clear_has_product_id() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void GetVersionResponse::clear_product_id() {
+  if (product_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    product_id_->clear();
+  }
+  clear_has_product_id();
+}
+inline const ::std::string& GetVersionResponse::product_id() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.product_id)
+  return *product_id_;
+}
+inline void GetVersionResponse::set_product_id(const ::std::string& value) {
+  set_has_product_id();
+  if (product_id_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    product_id_ = new ::std::string;
+  }
+  product_id_->assign(value);
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.product_id)
+}
+inline void GetVersionResponse::set_product_id(const char* value) {
+  set_has_product_id();
+  if (product_id_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    product_id_ = new ::std::string;
+  }
+  product_id_->assign(value);
+  // @@protoc_insertion_point(field_set_char:com.trustonic.tee_proxy.GetVersionResponse.product_id)
+}
+inline void GetVersionResponse::set_product_id(const char* value, size_t size) {
+  set_has_product_id();
+  if (product_id_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    product_id_ = new ::std::string;
+  }
+  product_id_->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:com.trustonic.tee_proxy.GetVersionResponse.product_id)
+}
+inline ::std::string* GetVersionResponse::mutable_product_id() {
+  set_has_product_id();
+  if (product_id_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    product_id_ = new ::std::string;
+  }
+  // @@protoc_insertion_point(field_mutable:com.trustonic.tee_proxy.GetVersionResponse.product_id)
+  return product_id_;
+}
+inline ::std::string* GetVersionResponse::release_product_id() {
+  clear_has_product_id();
+  if (product_id_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    return NULL;
+  } else {
+    ::std::string* temp = product_id_;
+    product_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+    return temp;
+  }
+}
+inline void GetVersionResponse::set_allocated_product_id(::std::string* product_id) {
+  if (product_id_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+    delete product_id_;
+  }
+  if (product_id) {
+    set_has_product_id();
+    product_id_ = product_id;
+  } else {
+    clear_has_product_id();
+    product_id_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  // @@protoc_insertion_point(field_set_allocated:com.trustonic.tee_proxy.GetVersionResponse.product_id)
+}
+
+// required uint32 mci = 2;
+inline bool GetVersionResponse::has_mci() const {
+  return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void GetVersionResponse::set_has_mci() {
+  _has_bits_[0] |= 0x00000002u;
+}
+inline void GetVersionResponse::clear_has_mci() {
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline void GetVersionResponse::clear_mci() {
+  mci_ = 0u;
+  clear_has_mci();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::mci() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.mci)
+  return mci_;
+}
+inline void GetVersionResponse::set_mci(::google::protobuf::uint32 value) {
+  set_has_mci();
+  mci_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.mci)
+}
+
+// required uint32 so = 3;
+inline bool GetVersionResponse::has_so() const {
+  return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void GetVersionResponse::set_has_so() {
+  _has_bits_[0] |= 0x00000004u;
+}
+inline void GetVersionResponse::clear_has_so() {
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline void GetVersionResponse::clear_so() {
+  so_ = 0u;
+  clear_has_so();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::so() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.so)
+  return so_;
+}
+inline void GetVersionResponse::set_so(::google::protobuf::uint32 value) {
+  set_has_so();
+  so_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.so)
+}
+
+// required uint32 mclf = 4;
+inline bool GetVersionResponse::has_mclf() const {
+  return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void GetVersionResponse::set_has_mclf() {
+  _has_bits_[0] |= 0x00000008u;
+}
+inline void GetVersionResponse::clear_has_mclf() {
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline void GetVersionResponse::clear_mclf() {
+  mclf_ = 0u;
+  clear_has_mclf();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::mclf() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.mclf)
+  return mclf_;
+}
+inline void GetVersionResponse::set_mclf(::google::protobuf::uint32 value) {
+  set_has_mclf();
+  mclf_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.mclf)
+}
+
+// required uint32 container = 5;
+inline bool GetVersionResponse::has_container() const {
+  return (_has_bits_[0] & 0x00000010u) != 0;
+}
+inline void GetVersionResponse::set_has_container() {
+  _has_bits_[0] |= 0x00000010u;
+}
+inline void GetVersionResponse::clear_has_container() {
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline void GetVersionResponse::clear_container() {
+  container_ = 0u;
+  clear_has_container();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::container() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.container)
+  return container_;
+}
+inline void GetVersionResponse::set_container(::google::protobuf::uint32 value) {
+  set_has_container();
+  container_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.container)
+}
+
+// required uint32 mc_config = 6;
+inline bool GetVersionResponse::has_mc_config() const {
+  return (_has_bits_[0] & 0x00000020u) != 0;
+}
+inline void GetVersionResponse::set_has_mc_config() {
+  _has_bits_[0] |= 0x00000020u;
+}
+inline void GetVersionResponse::clear_has_mc_config() {
+  _has_bits_[0] &= ~0x00000020u;
+}
+inline void GetVersionResponse::clear_mc_config() {
+  mc_config_ = 0u;
+  clear_has_mc_config();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::mc_config() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.mc_config)
+  return mc_config_;
+}
+inline void GetVersionResponse::set_mc_config(::google::protobuf::uint32 value) {
+  set_has_mc_config();
+  mc_config_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.mc_config)
+}
+
+// required uint32 tl_api = 7;
+inline bool GetVersionResponse::has_tl_api() const {
+  return (_has_bits_[0] & 0x00000040u) != 0;
+}
+inline void GetVersionResponse::set_has_tl_api() {
+  _has_bits_[0] |= 0x00000040u;
+}
+inline void GetVersionResponse::clear_has_tl_api() {
+  _has_bits_[0] &= ~0x00000040u;
+}
+inline void GetVersionResponse::clear_tl_api() {
+  tl_api_ = 0u;
+  clear_has_tl_api();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::tl_api() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.tl_api)
+  return tl_api_;
+}
+inline void GetVersionResponse::set_tl_api(::google::protobuf::uint32 value) {
+  set_has_tl_api();
+  tl_api_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.tl_api)
+}
+
+// required uint32 dr_api = 8;
+inline bool GetVersionResponse::has_dr_api() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void GetVersionResponse::set_has_dr_api() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void GetVersionResponse::clear_has_dr_api() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+inline void GetVersionResponse::clear_dr_api() {
+  dr_api_ = 0u;
+  clear_has_dr_api();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::dr_api() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.dr_api)
+  return dr_api_;
+}
+inline void GetVersionResponse::set_dr_api(::google::protobuf::uint32 value) {
+  set_has_dr_api();
+  dr_api_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.dr_api)
+}
+
+// required uint32 nwd = 9;
+inline bool GetVersionResponse::has_nwd() const {
+  return (_has_bits_[0] & 0x00000100u) != 0;
+}
+inline void GetVersionResponse::set_has_nwd() {
+  _has_bits_[0] |= 0x00000100u;
+}
+inline void GetVersionResponse::clear_has_nwd() {
+  _has_bits_[0] &= ~0x00000100u;
+}
+inline void GetVersionResponse::clear_nwd() {
+  nwd_ = 0u;
+  clear_has_nwd();
+}
+inline ::google::protobuf::uint32 GetVersionResponse::nwd() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GetVersionResponse.nwd)
+  return nwd_;
+}
+inline void GetVersionResponse::set_nwd(::google::protobuf::uint32 value) {
+  set_has_nwd();
+  nwd_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GetVersionResponse.nwd)
+}
+
+// -------------------------------------------------------------------
+
+// GpRequestCancellationRequest
+
+// required uint32 sid = 1;
+inline bool GpRequestCancellationRequest::has_sid() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void GpRequestCancellationRequest::set_has_sid() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void GpRequestCancellationRequest::clear_has_sid() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void GpRequestCancellationRequest::clear_sid() {
+  sid_ = 0u;
+  clear_has_sid();
+}
+inline ::google::protobuf::uint32 GpRequestCancellationRequest::sid() const {
+  // @@protoc_insertion_point(field_get:com.trustonic.tee_proxy.GpRequestCancellationRequest.sid)
+  return sid_;
+}
+inline void GpRequestCancellationRequest::set_sid(::google::protobuf::uint32 value) {
+  set_has_sid();
+  sid_ = value;
+  // @@protoc_insertion_point(field_set:com.trustonic.tee_proxy.GpRequestCancellationRequest.sid)
+}
+
+// -------------------------------------------------------------------
+
+// GpRequestCancellationResponse
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace tee_proxy
+}  // namespace trustonic
+}  // namespace com
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_mc_2eproto__INCLUDED
diff --git a/mobicore/ClientLib/src/mc_client_api.cpp b/mobicore/ClientLib/src/mc_client_api.cpp
new file mode 100644 (file)
index 0000000..1d356a6
--- /dev/null
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+
+#undef LOG_TAG
+#define LOG_TAG "TeeMcClient"
+#include "log.h"
+#include "MobiCoreDriverApi.h"
+#include "common_client.h"
+#include "buildTag.h"
+
+static const __attribute__((used)) char* buildtag =
+    MOBICORE_COMPONENT_BUILD_TAG;
+
+//------------------------------------------------------------------------------
+
+/*
+ * On mcCloseDevice(), all mappings need to be removed, which means we need to
+ * keep them somewhere.  We keep them in an array, resized when needed.
+ * Both map and length must be kept in user-space, as after a fork another
+ * mapping with same address may have appeared from the other process(es).
+ */
+struct maplen {
+    uint8_t* wsm;
+    uint32_t len;
+};
+
+static struct maplen* wsms;
+static size_t wsms_capacity, wsms_length;
+static pthread_mutex_t wsms_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static CommonClient& client = CommonClient::getInstance();
+
+static inline int wsms_add(uint8_t* wsm, uint32_t len) {
+    int ret = 0;
+    pthread_mutex_lock(&wsms_mutex);
+    if (wsms_length == wsms_capacity) {
+        size_t new_wsms_capacity = wsms_capacity;
+        /* Need some room */
+        if (new_wsms_capacity == 0) {
+            new_wsms_capacity = 16;
+        } else {
+            new_wsms_capacity *= 2;
+        }
+        struct maplen* new_wsms = static_cast<struct maplen*>(realloc(wsms,
+                                      new_wsms_capacity * sizeof(*wsms)));
+        if (!new_wsms) {
+            LOG_ERRNO("resize WSMs array");
+            ret = -1;
+        } else {
+            wsms = new_wsms;
+            wsms_capacity = new_wsms_capacity;
+        }
+    }
+    if (ret == 0) {
+        wsms[wsms_length].wsm = wsm;
+        wsms[wsms_length].len = len;
+        wsms_length++;
+        LOG_D("add %p %d", wsm, len);
+    }
+    pthread_mutex_unlock(&wsms_mutex);
+    return ret;
+}
+
+static inline int wsms_remove(uint8_t* wsm) {
+    int ret = 0;
+    pthread_mutex_lock(&wsms_mutex);
+    /* Find position of WSM */
+    size_t i;
+    for (i = 0; i < wsms_length; i++) {
+        if (wsms[i].wsm == wsm) {
+            break;
+        }
+    }
+    if (i == wsms_length) {
+        LOG_E("WSM %p not found in array", wsm);
+        ret = -1;
+    } else {
+        /* Replace WSM with last so the first free element remains wsms[wsms_length] */
+        wsms[i] = wsms[--wsms_length];
+        LOG_D("rm %p", wsm);
+    }
+    pthread_mutex_unlock(&wsms_mutex);
+    return ret;
+}
+
+static inline int wsms_len(uint8_t* wsm) {
+    int len = -1;
+    pthread_mutex_lock(&wsms_mutex);
+    for (size_t i = 0; i < wsms_length; i++) {
+        if (wsms[i].wsm == wsm) {
+            len = wsms[i].len;
+            LOG_D("rm len %p %d", wsm, len);
+            break;
+        }
+    }
+    pthread_mutex_unlock(&wsms_mutex);
+    return len;
+}
+
+static inline struct maplen wsms_getLast(void) {
+    struct maplen wsm;
+    pthread_mutex_lock(&wsms_mutex);
+    if (wsms_length > 0) {
+        wsm = wsms[wsms_length - 1];
+        LOG_D("rm last %p", wsm.wsm);
+    } else {
+        wsm.wsm = NULL;
+        // To make Coverity happy
+        wsm.len = 0;
+    }
+    pthread_mutex_unlock(&wsms_mutex);
+    return wsm;
+}
+
+/* Only 1 device is supported */
+static inline bool isValidDevice(uint32_t deviceId) {
+    return (MC_DEVICE_ID_DEFAULT == deviceId);
+}
+
+/* Convert driver errors into tbase set */
+static mcResult_t convert_syscall_error(int32_t ret) {
+    switch (ret) {
+        case 0:
+            return MC_DRV_OK;
+        case -1:
+            switch (errno) {
+                case ENOMSG:
+                    return MC_DRV_NO_NOTIFICATION;
+                case EBADMSG:
+                    return MC_DRV_ERR_NOTIFICATION;
+                case ENOSPC:
+                    return MC_DRV_ERR_OUT_OF_RESOURCES;
+                case EHOSTDOWN:
+                    return MC_DRV_ERR_INIT;
+                case ENODEV:
+                    return MC_DRV_ERR_UNKNOWN_DEVICE;
+                case ENXIO:
+                    return MC_DRV_ERR_UNKNOWN_SESSION;
+                case EPERM:
+                    return MC_DRV_ERR_INVALID_OPERATION;
+                case EBADE:
+                    return MC_DRV_ERR_INVALID_RESPONSE;
+                case ETIME:
+                    return MC_DRV_ERR_TIMEOUT;
+                case ENOMEM:
+                    return MC_DRV_ERR_NO_FREE_MEMORY;
+                case EUCLEAN:
+                    return MC_DRV_ERR_FREE_MEMORY_FAILED;
+                case ENOTEMPTY:
+                    return MC_DRV_ERR_SESSION_PENDING;
+                case EHOSTUNREACH:
+                    return MC_DRV_ERR_DAEMON_UNREACHABLE;
+                case ENOENT:
+                    return MC_DRV_ERR_INVALID_DEVICE_FILE;
+                case EINVAL:
+                    return MC_DRV_ERR_INVALID_PARAMETER;
+                case EPROTO:
+                    return MC_DRV_ERR_KERNEL_MODULE;
+                case EADDRINUSE:
+                    return MC_DRV_ERR_BULK_MAPPING;
+                case EADDRNOTAVAIL:
+                    return MC_DRV_ERR_BULK_UNMAPPING;
+                case ECOMM:
+                    return MC_DRV_INFO_NOTIFICATION;
+                case EUNATCH:
+                    return MC_DRV_ERR_NQ_FAILED;
+                case EBADF:
+                    return MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
+                case EINTR:
+                    return MC_DRV_ERR_INTERRUPTED_BY_SIGNAL;
+                case EKEYREJECTED:
+                    return MC_DRV_ERR_WRONG_PUBLIC_KEY;
+                case ECONNREFUSED:
+                    return MC_DRV_ERR_SERVICE_BLOCKED;
+                case ECONNABORTED:
+                    return MC_DRV_ERR_SERVICE_LOCKED;
+                case ECONNRESET:
+                    return MC_DRV_ERR_SERVICE_KILLED;
+                default:
+                    LOG_ERRNO("syscall");
+                    return MC_DRV_ERR_UNKNOWN;
+            }
+        default:
+            LOG_E("Unknown code %d", ret);
+            return MC_DRV_ERR_UNKNOWN;
+    }
+}
+
+//------------------------------------------------------------------------------
+//      CLIENT API
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcOpenDevice(
+    uint32_t deviceId
+) {
+    LOG_D("===%s(%i)===", __FUNCTION__, deviceId);
+
+    // Check parameters
+    if (!isValidDevice(deviceId) &&
+            (deviceId != CommonClient::DRIVER) &&
+            (deviceId != CommonClient::PROXY)) {
+        return MC_DRV_ERR_UNKNOWN_DEVICE;
+    }
+
+    // For test purpose
+    switch (deviceId) {
+        case CommonClient::DRIVER:
+            client.setOpenMode(CommonClient::DRIVER);
+            break;
+        case CommonClient::PROXY:
+            client.setOpenMode(CommonClient::PROXY);
+            break;
+    }
+
+    if (client.open()) {
+        return convert_syscall_error(-1);
+    }
+
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcCloseDevice(
+    uint32_t deviceId
+) {
+    LOG_D("===%s(%i)===", __FUNCTION__, deviceId);
+
+    // Check parameters
+    if (!isValidDevice(deviceId)) {
+        return MC_DRV_ERR_UNKNOWN_DEVICE;
+    }
+
+    // Check whether there are still some 'devices open'
+    if (client.closeCheck() == 0) {
+        return MC_DRV_OK;
+    }
+
+    // Check that all sessions are closed for client
+    mcResult_t mcResult = convert_syscall_error(client.hasOpenSessions());
+    if (mcResult != MC_DRV_OK) {
+        return mcResult;
+    }
+
+    // Free all remaining WSMs
+    while (true) {
+        struct maplen wsm = wsms_getLast();
+        if (wsm.wsm == NULL) {
+            break;
+        }
+        mcFreeWsm(deviceId, wsm.wsm);
+    }
+
+    // Close the device
+    client.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+__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_ERR_UNKNOWN;
+    struct mc_ioctl_open_session sess;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!uuid) {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Call ioctl
+        sess.sid = 0;
+        memcpy( (void*)&sess.uuid, uuid, sizeof(sess.uuid) );
+        sess.tci = (uintptr_t)tci;
+        sess.tcilen = len;
+        sess.is_gp_uuid = false;
+        sess.identity.login_type = LOGIN_PUBLIC;
+        sess.identity.pid = 0;
+        ret = client.openSession(sess);
+        mcResult = convert_syscall_error(ret);
+        if (MC_DRV_OK != mcResult) {
+            break;
+        }
+
+        // Fill in return parameters
+        session->sessionId = sess.sid;
+    } while (false);
+
+    /* Legacy error matching */
+    if (MC_DRV_OK != mcResult) {
+        if (MC_DRV_ERR_UNKNOWN == mcResult) {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+        }
+
+        LOG_E("return 0x%x", mcResult);
+    }
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcOpenTrustlet(
+    mcSessionHandle_t*  session,
+    mcSpid_t            spid,
+    uint8_t*            trustlet,
+    uint32_t            tLen,
+    uint8_t*            tci,
+    uint32_t            tciLen
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    struct mc_ioctl_open_trustlet trus;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        // Call ioctl
+        trus.sid = 0;
+        trus.spid = spid;
+        trus.buffer = (uintptr_t)trustlet;
+        trus.tlen = tLen;
+        trus.tci = (uintptr_t)tci;
+        trus.tcilen = tciLen;
+        ret = client.openTrustlet(trus);
+        mcResult = convert_syscall_error(ret);
+
+        // Fill in return parameters
+        if (MC_DRV_OK == mcResult) {
+            session->sessionId = trus.sid;
+        }
+
+    } while (false);
+
+    /* Legacy error matching */
+    if (MC_DRV_OK != mcResult) {
+        if (MC_DRV_ERR_UNKNOWN == mcResult) {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+        }
+
+        LOG_E("return 0x%x", mcResult);
+    }
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcCloseSession(
+    mcSessionHandle_t*  session
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        // Call ioctl
+        ret = client.closeSession(session->sessionId);
+        mcResult = convert_syscall_error(ret);
+
+    } while (false);
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcNotify(
+    mcSessionHandle_t*  session
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        // Call ioctl
+        ret = client.notify(session->sessionId);
+        mcResult = convert_syscall_error(ret);
+
+    } while (false);
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcWaitNotification(
+    mcSessionHandle_t*  session,
+    int32_t             timeout
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    struct mc_ioctl_wait wait;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        // Call ioctl
+        wait.sid = session->sessionId;
+        wait.timeout = timeout;
+        do {
+            ret = client.waitNotification(wait);
+            mcResult = convert_syscall_error(ret);
+        } while (MC_INFINITE_TIMEOUT == timeout &&
+                 MC_DRV_ERR_INTERRUPTED_BY_SIGNAL == mcResult);
+
+    } 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
+) {
+    (void) align;
+    (void) wsmFlags;
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    LOG_D("===%s(len=%i)===", __FUNCTION__, len);
+
+    do {
+        // Check parameters
+        if (!isValidDevice(deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!client.isOpen()) {
+            LOG_E("Client not open");
+            mcResult = MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
+            break;
+        }
+        if (!wsm) {
+            LOG_E("Wsm pointer is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        // Alloc and map kernel buffer into user space
+        if (client.malloc(wsm, len)) {
+            mcResult = convert_syscall_error(-1);
+            break;
+        }
+        wsms_add(*wsm, len);
+        mcResult = MC_DRV_OK;
+
+    } while (false);
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+// Note: mcFreeWsm() only succeeds if wsm is as returned by mcMallocWsm().
+__MC_CLIENT_LIB_API mcResult_t mcFreeWsm(
+    uint32_t            deviceId,
+    uint8_t*            wsm
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+
+    LOG_D("===%s(%p)===", __FUNCTION__, wsm);
+
+    do {
+        // Check parameters
+        if (!isValidDevice(deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!client.isOpen()) {
+            LOG_E("Client not open");
+            mcResult = MC_DRV_ERR_DAEMON_DEVICE_NOT_OPEN;
+            break;
+        }
+        // Get mapping length
+        int len = wsms_len(wsm);
+        if (len == -1) {
+            LOG_E("wsm %p buffer not available", wsm);
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+        } else {
+            // Unmap and free kernel buffer
+            int ret = client.free(wsm, len);
+            mcResult = convert_syscall_error(ret);
+            if (ret == 0) {
+                wsms_remove(wsm);
+            }
+        }
+    } while (false);
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcMap(
+    mcSessionHandle_t*  session,
+    void*               buf,
+    uint32_t            bufLen,
+    mcBulkMap_t*        mapInfo
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    struct mc_ioctl_map map;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!mapInfo) {
+            LOG_E("mapInfo pointer is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Call ioctl
+        map.sid = session->sessionId;
+        map.bufs[0].va = (uintptr_t)buf;
+        map.bufs[0].len = bufLen;
+        map.bufs[0].flags = MC_IO_MAP_INPUT_OUTPUT;
+        LOG_D("map va=%llx len=%u", map.bufs[0].va, map.bufs[0].len);
+        for (int i = 1; i < MC_MAP_MAX; i++) {
+            map.bufs[i].va = 0;
+        }
+        ret = client.map(map);
+        mcResult = convert_syscall_error(ret);
+        if (MC_DRV_OK != mcResult) {
+            break;
+        }
+        LOG_D("map'd va=%llx len=%u sva=%llx",
+              map.bufs[0].va, map.bufs[0].len, map.bufs[0].sva);
+
+        // Fill in return parameters
+#if ( __WORDSIZE != 64 )
+        mapInfo->sVirtualAddr = (void*)(uintptr_t)map.bufs[0].sva;
+#else
+        mapInfo->sVirtualAddr = (uint32_t)map.bufs[0].sva;
+#endif
+        mapInfo->sVirtualLen = map.bufs[0].len;
+    } while (false);
+
+    /* Legacy error matching */
+    if (MC_DRV_OK != mcResult) {
+        if (MC_DRV_ERR_UNKNOWN == mcResult) {
+            mcResult = MC_DRV_ERR_BULK_MAPPING;
+        }
+
+        LOG_E("return 0x%x", mcResult);
+    }
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcUnmap(
+    mcSessionHandle_t*  session,
+    void*               buf,
+    mcBulkMap_t*        mapInfo
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    struct mc_ioctl_map map;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!mapInfo) {
+            LOG_E("mapInfo pointer is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Call ioctl
+        map.sid = session->sessionId;
+        map.bufs[0].va = (uintptr_t)buf;
+        map.bufs[0].sva = (uintptr_t)mapInfo->sVirtualAddr;
+        map.bufs[0].len = mapInfo->sVirtualLen;
+        LOG_D("unmap va=%llx len=%u sva=%llx",
+              map.bufs[0].va, map.bufs[0].len, map.bufs[0].sva);
+        for (int i = 1; i < MC_MAP_MAX; i++) {
+            map.bufs[i].va = 0;
+        }
+        ret = client.unmap(map);
+        mcResult = convert_syscall_error(ret);
+
+    } while (false);
+
+    if (MC_DRV_OK != mcResult) {
+        if (MC_DRV_ERR_UNKNOWN == mcResult) {
+            mcResult = MC_DRV_ERR_BULK_UNMAPPING;
+        }
+
+        LOG_E("return 0x%x", mcResult);
+    }
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcGetSessionErrorCode(
+    mcSessionHandle_t*  session,
+    int32_t*            lastErr
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    struct mc_ioctl_geterr err;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!session) {
+            LOG_E("Session handle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (!isValidDevice(session->deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!lastErr) {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Call ioctl
+        err.sid = session->sessionId;
+        ret = client.getError(err);
+        mcResult = convert_syscall_error(ret);
+        if (MC_DRV_OK != mcResult) {
+            break;
+        }
+
+        // Fill in return parameters
+        *lastErr = err.value;
+
+    } while (false);
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcGetMobiCoreVersion(
+    uint32_t            deviceId,
+    mcVersionInfo_t*    versionInfo
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    int ret;
+
+    LOG_D("===%s()===", __FUNCTION__);
+
+    do {
+        // Check parameters
+        if (!isValidDevice(deviceId)) {
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if (!versionInfo) {
+            LOG_E("versionInfo pointer is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        struct mc_version_info version_info;
+        ret = client.getVersion(version_info);
+        if (!ret) {
+            memcpy(versionInfo, &version_info, sizeof(*versionInfo));
+        }
+        mcResult = convert_syscall_error(ret);
+    } while (false);
+
+    return mcResult;
+}
diff --git a/mobicore/ClientLib/src/mc_user.h b/mobicore/ClientLib/src/mc_user.h
new file mode 100644 (file)
index 0000000..e8ac3d6
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MC_USER_H_
+#define _MC_USER_H_
+
+#define MCDRVMODULEAPI_VERSION_MAJOR 2
+#define MCDRVMODULEAPI_VERSION_MINOR 10
+
+#include <linux/types.h>
+
+#define MC_USER_DEVNODE                "mobicore-user"
+
+/** Maximum length of MobiCore product ID string. */
+#define MC_PRODUCT_ID_LEN      64
+
+/** Number of buffers that can be mapped at once */
+#define MC_MAP_MAX             4
+
+/** Max length for buffers */
+#define BUFFER_LENGTH_MAX      0x100000
+
+/** Flags for buffers to map (aligned on GP) */
+#define MC_IO_MAP_INPUT                0x1
+#define MC_IO_MAP_OUTPUT       0x2
+#define MC_IO_MAP_INPUT_OUTPUT (MC_IO_MAP_INPUT | MC_IO_MAP_OUTPUT)
+
+/*
+ * Universally Unique Identifier (UUID) according to ISO/IEC 11578.
+ */
+struct mc_uuid_t {
+       __u8            value[16];      /* Value of the UUID. */
+};
+
+/*
+ * GP TA login types.
+ */
+enum mc_login_type {
+       LOGIN_PUBLIC = 0,
+       LOGIN_USER,
+       LOGIN_GROUP,
+       LOGIN_APPLICATION = 4,
+       LOGIN_USER_APPLICATION,
+       LOGIN_GROUP_APPLICATION,
+};
+
+/*
+ * GP TA identity structure.
+ */
+struct mc_identity {
+       enum mc_login_type      login_type;
+       union {
+               __u8            login_data[16];
+               gid_t           gid;            /* Requested group id */
+               struct {
+                       uid_t   euid;
+                       uid_t   ruid;
+               } uid;
+       };
+       pid_t                   pid;            /* Client, when using proxy */
+};
+
+/*
+ * Data exchange structure of the MC_IO_OPEN_SESSION ioctl command.
+ */
+struct mc_ioctl_open_session {
+       struct mc_uuid_t uuid;          /* trustlet uuid */
+       __u32           is_gp_uuid;     /* uuid is for GP TA */
+       __u32           sid;            /* session id (out) */
+       __u64           tci;            /* tci buffer pointer */
+       __u32           tcilen;         /* tci length */
+       struct mc_identity identity;    /* GP TA identity */
+};
+
+/*
+ * Data exchange structure of the MC_IO_OPEN_TRUSTLET ioctl command.
+ */
+struct mc_ioctl_open_trustlet {
+       __u32           sid;            /* session id (out) */
+       __u32           spid;           /* trustlet spid */
+       __u64           buffer;         /* trustlet binary pointer */
+       __u32           tlen;           /* binary length  */
+       __u64           tci;            /* tci buffer pointer */
+       __u32           tcilen;         /* tci length */
+};
+
+/*
+ * Data exchange structure of the MC_IO_WAIT ioctl command.
+ */
+struct mc_ioctl_wait {
+       __u32           sid;            /* session id (in) */
+       __s32           timeout;        /* notification timeout */
+       __u32           partial;        /* for proxy server to retry silently */
+};
+
+/*
+ * Data exchange structure of the MC_IO_ALLOC ioctl command.
+ */
+struct mc_ioctl_alloc {
+       __u32           len;            /* buffer length  */
+       __u32           handle;         /* user handle for the buffer (out) */
+};
+
+/*
+ * Buffer mapping incoming and outgoing information.
+ */
+struct mc_ioctl_buffer {
+       __u64           va;             /* user space address of buffer */
+       __u32           len;            /* buffer length  */
+       __u64           sva;            /* SWd virt address of buffer (out) */
+       __u32           flags;          /* buffer flags  */
+};
+
+/*
+ * Data exchange structure of the MC_IO_MAP and MC_IO_UNMAP ioctl commands.
+ */
+struct mc_ioctl_map {
+       __u32           sid;            /* session id */
+       struct mc_ioctl_buffer bufs[MC_MAP_MAX]; /* buffers info */
+};
+
+/*
+ * Data exchange structure of the MC_IO_ERR ioctl command.
+ */
+struct mc_ioctl_geterr {
+       __u32           sid;            /* session id */
+       __s32           value;          /* error value (out) */
+};
+
+/*
+ * Global MobiCore Version Information.
+ */
+struct mc_version_info {
+       char product_id[MC_PRODUCT_ID_LEN]; /** Product ID string */
+       __u32 version_mci;              /** Mobicore Control Interface */
+       __u32 version_so;               /** Secure Objects */
+       __u32 version_mclf;             /** MobiCore Load Format */
+       __u32 version_container;        /** MobiCore Container Format */
+       __u32 version_mc_config;        /** MobiCore Config. Block Format */
+       __u32 version_tl_api;           /** MobiCore Trustlet API */
+       __u32 version_dr_api;           /** MobiCore Driver API */
+       __u32 version_nwd;              /** This Driver */
+};
+
+/*
+ * defines for the ioctl mobicore driver module function call from user space.
+ */
+/* MobiCore IOCTL magic number */
+#define MC_IOC_MAGIC   'M'
+
+/*
+ * Implement corresponding functions from user api
+ */
+#define MC_IO_OPEN_SESSION     \
+       _IOWR(MC_IOC_MAGIC, 0, struct mc_ioctl_open_session)
+#define MC_IO_OPEN_TRUSTLET    \
+       _IOWR(MC_IOC_MAGIC, 1, struct mc_ioctl_open_trustlet)
+#define MC_IO_CLOSE_SESSION    _IO(MC_IOC_MAGIC, 2)
+#define MC_IO_NOTIFY           _IO(MC_IOC_MAGIC, 3)
+#define MC_IO_WAIT             _IOW(MC_IOC_MAGIC, 4, struct mc_ioctl_wait)
+#define MC_IO_MAP              _IOWR(MC_IOC_MAGIC, 5, struct mc_ioctl_map)
+#define MC_IO_UNMAP            _IOW(MC_IOC_MAGIC, 6, struct mc_ioctl_map)
+#define MC_IO_ERR              _IOWR(MC_IOC_MAGIC, 7, struct mc_ioctl_geterr)
+#define MC_IO_HAS_SESSIONS     _IO(MC_IOC_MAGIC, 8)
+#define MC_IO_VERSION          _IOR(MC_IOC_MAGIC, 9, struct mc_version_info)
+
+#endif /* _MC_USER_H_ */
diff --git a/mobicore/ClientLib/src/proxy_client.cpp b/mobicore/ClientLib/src/proxy_client.cpp
new file mode 100644 (file)
index 0000000..356f492
--- /dev/null
@@ -0,0 +1,812 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include <string.h>     // strncpy
+#include <sys/mman.h>   // mmap, munmap
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#undef LOG_TAG
+#define LOG_TAG "TeeProxyClient"
+#include "log.h"
+#include "mcVersionHelper.h"
+#include "proxy_common.h"
+#include "proxy_client.h"
+
+using namespace com::trustonic::tee_proxy;
+
+class ClientConnection {
+    std::string buffer_;
+    std::mutex comm_mutex_;
+    std::mutex comm_queue_mutex_;
+    int socket_ = -1;
+    bool is_open_ = false;
+    bool is_broken_ = false;
+    Session* session_ = nullptr;
+public:
+    ~ClientConnection() {
+        if (is_open_) {
+            close();
+        }
+        delete session_;
+    }
+    int open() {
+        socket_ = ::socket(AF_UNIX, SOCK_STREAM, 0);
+        if (socket_ < 0) {
+            LOG_ERRNO("socket");
+            return -1;
+        }
+        struct sockaddr_un sock_un;
+        sock_un.sun_family = AF_UNIX;
+        ::strncpy(sock_un.sun_path, SOCKET_PATH, sizeof(sock_un.sun_path) - 1);
+        socklen_t len = static_cast<socklen_t>(strlen(sock_un.sun_path) +
+                                               sizeof(sock_un.sun_family));
+        sock_un.sun_path[0] = '\0';         // Abstract
+        if (::connect(socket_, reinterpret_cast<struct sockaddr*>(&sock_un),
+                      len) < 0) {
+            LOG_ERRNO("connect");
+            return -1;
+        }
+        is_open_ = true;
+        LOG_D("socket %d connected", socket_);
+        return 0;
+    }
+    int close() {
+        ::close(socket_);
+        is_open_ = false;
+        LOG_D("socket %d session %x closed", socket_, session_ ? session_->id() : 0);
+        return 0;
+    }
+    bool isBroken() const {
+        return is_broken_;
+    }
+    void setSession(Session* session) {
+        session_ = session;
+    }
+    Session* session() const {
+        return session_;
+    }
+    int call(RpcMethod method, const ::google::protobuf::MessageLite& request,
+             ::google::protobuf::MessageLite& response) {
+        // Trick to ensure round-robin access to two callers
+        comm_queue_mutex_.lock();
+        std::lock_guard<std::mutex> comm_lock(comm_mutex_);
+        comm_queue_mutex_.unlock();
+        LOG_D("socket %d session %x call %s", socket_,
+              session_ ? session_->id() : 0, methodToString(method));
+
+        // Request
+        {
+            // Serialize request
+            if (!request.SerializeToString(&buffer_)) {
+                LOG_E("Failed to serialize");
+                is_broken_ = true;
+                return -1;
+            }
+
+            // Send request header
+            RequestHeader header;
+            ::memcpy(header.magic, PROTOCOL_MAGIC, sizeof(header.magic));
+            header.version = PROTOCOL_VERSION;
+            header.method = static_cast<uint16_t>(method);
+            header.length = static_cast<uint32_t>(buffer_.length());
+            if (send_all(socket_, "header", &header, sizeof(header))) {
+                is_broken_ = true;
+                return -1;
+            }
+
+            // Send request data
+            LOG_D("send %u bytes of data", header.length);
+            if (send_all(socket_, "data", &buffer_[0], header.length)) {
+                is_broken_ = true;
+                return -1;
+            }
+        }
+
+        // Response
+        {
+            // Receive response header
+            ResponseHeader header;
+            if (recv_all(socket_, "header", &header, sizeof(header))) {
+                is_broken_ = true;
+                return -1;
+            }
+
+            // Check header
+            if (::memcmp(header.magic, PROTOCOL_MAGIC, sizeof(header.magic))) {
+                LOG_E("Wrong magic");
+                is_broken_ = true;
+                return -1;
+            }
+            if (header.version != PROTOCOL_VERSION) {
+                LOG_E("Wrong version");
+                is_broken_ = true;
+                return -1;
+            }
+            if (header.proto_rc < 0) {
+                errno = -header.proto_rc;
+                LOG_E("Protocol error reported: %s",
+                      strerror(-header.proto_rc));
+                is_broken_ = true;
+                return -1;
+            }
+
+            // Receive response data
+            LOG_D("receive %d bytes of data", header.proto_rc);
+            if (header.proto_rc != 0) {
+                // Receive response data
+                int length = header.proto_rc;
+                buffer_.resize(length);
+                if (recv_all(socket_, "data", &buffer_[0], length)) {
+                    is_broken_ = true;
+                    return -1;
+                }
+
+                // Parse response
+                if (!response.ParseFromString(buffer_)) {
+                    LOG_E("Failed to parse");
+                    is_broken_ = true;
+                    return -1;
+                }
+            }
+
+            // Method errors do not require specific method action
+            if (header.method_rc) {
+                errno = header.method_rc;
+                LOG_D("Error reported: %s", strerror(errno));
+                return -1;
+            }
+        }
+        LOG_D("socket %d session %x call done", socket_,
+              session_ ? session_->id() : 0);
+        return 0;
+    }
+};
+
+class SessionConnectionsList {
+    std::mutex mutex_;
+    std::vector<ClientConnection*> connections_;
+public:
+    ClientConnection* find(uint32_t id) {
+        std::lock_guard<std::mutex> lock(mutex_);
+        for (auto& connection: connections_) {
+            if (connection->session()->id() == id) {
+                return connection;
+            }
+        }
+        return nullptr;
+    }
+    int deleteConnection(uint32_t id) {
+        LOG_D("%s %p: %x", __FUNCTION__, this, id);
+        std::lock_guard<std::mutex> lock(mutex_);
+        auto it = std::find_if(connections_.begin(), connections_.end(),
+        [this, id](ClientConnection* connection) {
+            return connection->session()->id() == id;
+        });
+        if (it == connections_.end()) {
+            // Not found
+            return -1;
+        }
+        delete *it;
+        connections_.erase(it);
+        return 0;
+    }
+    void push_back(ClientConnection* connection) {
+        LOG_D("%s %p: %x", __FUNCTION__, this, connection->session()->id());
+        std::lock_guard<std::mutex> lock(mutex_);
+        connections_.push_back(connection);
+    }
+    bool empty() const {
+        return connections_.empty();
+    }
+};
+
+struct ProxyClient::Impl {
+    bool is_open_;
+    // Versions
+    mc_version_info version_info;
+    // Sessions
+    SessionConnectionsList connections;
+    Impl(): is_open_(false) {
+        ::memset(&version_info, 0, sizeof(version_info));
+    }
+    int getVersion(ClientConnection& conn, struct mc_version_info& version_info);
+};
+
+ProxyClient::ProxyClient(): pimpl_(new Impl) {
+}
+
+ProxyClient::~ProxyClient() {
+    delete pimpl_;
+}
+
+int ProxyClient::open() {
+    ClientConnection conn;
+    if (conn.open()) {
+        return -1;
+    }
+    // Cache versions
+    if (pimpl_->getVersion(conn, pimpl_->version_info)) {
+        return -1;
+    }
+    conn.close();
+    pimpl_->is_open_ = true;
+    LOG_I("proxy client open");
+    return 0;
+}
+
+int ProxyClient::close() {
+    pimpl_->is_open_ = false;
+    LOG_I("proxy client closed");
+    return 0;
+}
+
+bool ProxyClient::isOpen() const {
+    return pimpl_->is_open_;
+}
+
+int ProxyClient::hasOpenSessions() const {
+    int ret = 0;
+    if (!pimpl_->connections.empty()) {
+        ret = -1;
+        errno = ENOTEMPTY;
+    }
+    LOG_D("%s rc=%d", __FUNCTION__, ret);
+    return ret;
+}
+
+int ProxyClient::openSession(struct mc_ioctl_open_session& session) {
+    LOG_D("tci 0x%llx len %u", session.tci, session.tcilen);
+    if ((session.tci && !session.tcilen) ||
+            (!session.tci && session.tcilen)) {
+        LOG_E("TCI and its length are inconsistent");
+        errno = EINVAL;
+        return -1;
+    }
+    // So we return the correct error code
+    if (session.tcilen > BUFFER_LENGTH_MAX) {
+        errno = EINVAL;
+        return -1;
+    }
+    // Open the session
+    void* tci = reinterpret_cast<void*>(static_cast<uintptr_t>(session.tci));
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    OpenSessionRequest request;
+    request.set_uuid(static_cast<void*>(&session.uuid), sizeof(session.uuid));
+    request.set_is_gp_uuid(session.is_gp_uuid);
+    if (tci) {
+        request.set_tci(tci, session.tcilen);
+    }
+    request.set_login_type(static_cast<LoginType>(session.identity.login_type));
+    request.set_login_data(static_cast<void*>(session.identity.login_data),
+                           sizeof(session.identity.login_data));
+    // Create connection
+    std::unique_ptr<ClientConnection> conn(new ClientConnection);
+    if (conn->open()) {
+        LOG_E("Failed to open connection");
+        return -1;
+    }
+    // Exchange
+    OpenSessionResponse response;
+    if (conn->call(OPEN_SESSION, request, response)) {
+        // Error logged in call()
+        return -1;
+    }
+    // Response
+    if (!response.has_id()) {
+        LOG_E("Required parameter missing");
+        return -1;
+    }
+    // Success
+    errno = saved_errno;
+    session.sid = response.id();
+    LOG_D("session %x open", session.sid);
+    Session::Buffer* buffer;
+    if (tci) {
+        buffer = new Session::Buffer(tci, session.tcilen);
+    } else {
+        buffer = nullptr;
+    }
+    conn->setSession(new Session(session.sid, buffer));
+    pimpl_->connections.push_back(conn.release());
+    return 0;
+}
+
+int ProxyClient::openTrustlet(struct mc_ioctl_open_trustlet& trustlet) {
+    LOG_D("tci 0x%llx len %u", trustlet.tci, trustlet.tcilen);
+    if ((trustlet.tci && !trustlet.tcilen) ||
+            (!trustlet.tci && trustlet.tcilen)) {
+        LOG_E("TCI and its length are inconsistent");
+        return -1;
+    }
+    // So we return the correct error code
+    if (trustlet.tcilen > BUFFER_LENGTH_MAX) {
+        errno = EINVAL;
+        return -1;
+    }
+    // Open the trustlet
+    void* app = reinterpret_cast<void*>(static_cast<uintptr_t>(trustlet.buffer));
+    void* tci = reinterpret_cast<void*>(static_cast<uintptr_t>(trustlet.tci));
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    OpenTrustletRequest request;
+    request.set_spid(trustlet.spid);
+    request.set_trustapp(app, trustlet.tlen);
+    if (tci) {
+        request.set_tci(tci, trustlet.tcilen);
+    }
+    // Create connection
+    std::unique_ptr<ClientConnection> conn(new ClientConnection);
+    if (conn->open()) {
+        LOG_E("Failed to open connection");
+        return -1;
+    }
+    // Exchange
+    OpenTrustletResponse response;
+    if (conn->call(OPEN_TRUSTLET, request, response)) {
+        // Error logged in call()
+        return -1;
+    }
+    // Response
+    if (!response.has_id()) {
+        LOG_E("Required parameter missing");
+        return -1;
+    }
+    // Success
+    errno = saved_errno;
+    trustlet.sid = response.id();
+    LOG_D("session %x open", trustlet.sid);
+    // Create session management object
+    Session::Buffer* buffer;
+    if (tci) {
+        buffer = new Session::Buffer(tci, trustlet.tcilen);
+    } else {
+        buffer = nullptr;
+    }
+    conn->setSession(new Session(trustlet.sid, buffer));
+    pimpl_->connections.push_back(conn.release());
+    return 0;
+}
+
+int ProxyClient::closeSession(uint32_t session_id) {
+    LOG_D("session %x close", session_id);
+    // Find session connection
+    auto connection = pimpl_->connections.find(session_id);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    CloseSessionRequest request;
+    request.set_id(session_id);
+    // Exchange
+    CloseSessionResponse response;
+    if (connection->call(CLOSE_SESSION, request, response)) {
+        // Error logged in call()
+        if (connection->isBroken()) {
+            pimpl_->connections.deleteConnection(session_id);
+        }
+        return -1;
+    }
+    // No response
+    // Success
+    errno = saved_errno;
+    if (pimpl_->connections.deleteConnection(session_id)) {
+        errno = ENXIO;
+        return -1;
+    }
+    LOG_D("session %x closed", session_id);
+    return 0;
+}
+
+int ProxyClient::notify(uint32_t session_id) {
+    LOG_D("session %x notify", session_id);
+    // Find session connection
+    auto connection = pimpl_->connections.find(session_id);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    NotifyRequest request;
+    request.set_sid(session_id);
+    auto session = connection->session();
+    if (session->hasTci()) {
+        request.set_tci(session->tci(), session->tciLen());
+    }
+    std::lock_guard<std::mutex> buffers_lock(session->buffersMutex());
+    auto& buffers = session->buffers();
+    for (auto& buf: buffers) {
+        if (buf->info().flags & MC_IO_MAP_INPUT) {
+            NotifyRequest_Buffers* buffer = request.add_buffers();
+            buffer->set_sva(buf->info().sva);
+            buffer->set_data(buf->address(), buf->info().len);
+        }
+    }
+    // Exchange
+    NotifyResponse response;
+    if (connection->call(NOTIFY, request, response)) {
+        // Error logged in call()
+        if (connection->isBroken()) {
+            pimpl_->connections.deleteConnection(session_id);
+        }
+        return -1;
+    }
+    // No response
+    // Success
+    errno = saved_errno;
+    LOG_D("session %x notification sent", session_id);
+    return 0;
+}
+
+int ProxyClient::waitNotification(const struct mc_ioctl_wait& wait) {
+    LOG_D("session %x wait for notification", wait.sid);
+    // Find session connection
+    auto connection = pimpl_->connections.find(wait.sid);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    WaitNotificationRequest request;
+    request.set_sid(wait.sid);
+    // Timeout to server cannot exceed a few seconds, retry every 5s
+    int32_t timeout_left = wait.timeout;
+    WaitNotificationResponse response;
+    bool failed = false;
+    while (true) {
+        if (wait.timeout < 0) {
+            // Infinite
+            request.set_timeout(timeout_max);
+            request.set_partial(true);
+        } else if (timeout_left > timeout_max) {
+            // Big
+            request.set_timeout(timeout_max);
+            request.set_partial(true);
+            timeout_left -= timeout_max;
+        } else {
+            // Small enough
+            request.set_timeout(timeout_left);
+            request.set_partial(false);
+            timeout_left = 0;
+        }
+        LOG_D("timeout: asked=%d left=%d set=%d",
+              wait.timeout, timeout_left, request.timeout());
+        // Exchange
+        if (!connection->call(WAIT, request, response)) {
+            LOG_D("done");
+            break;
+        }
+        // Real timeout or other error
+        if ((errno != ETIME) || !request.partial()) {
+            // Error logged in call()
+            if (connection->isBroken()) {
+                pimpl_->connections.deleteConnection(wait.sid);
+                LOG_D("abort");
+                return -1;
+            }
+            LOG_D("give up, but update buffers");
+            failed = true;
+            break;
+        }
+        LOG_D("retry");
+    }
+    // Response
+    auto session = connection->session();
+    if (response.has_tci() && session->updateTci(response.tci())) {
+        LOG_E("Could not update TCI");
+        return -1;
+    }
+    for (int i = 0; i < response.buffers_size(); i++) {
+        const WaitNotificationResponse_Buffers& buffer = response.buffers(i);
+        if (!buffer.has_sva() || !buffer.has_data()) {
+            LOG_E("Required parameter missing");
+            return -1;
+        }
+        std::lock_guard<std::mutex> buffers_lock(session->buffersMutex());
+        auto buf = session->findBuffer(buffer.sva());
+        if (!buf) {
+            LOG_E("Buffer not found for SVA %jx", buffer.sva());
+            return -1;
+        }
+        if (buffer.data().length() != buf->info().len) {
+            LOG_E("Buffer sizes differ for SVA %jx: %zu != %u",
+                  buffer.sva(), buffer.data().length(), buf->info().len);
+            return -1;
+        }
+        ::memcpy(buf->address(), buffer.data().c_str(), buf->info().len);
+    }
+    if (failed) {
+        return -1;
+    }
+    // Success
+    errno = saved_errno;
+    LOG_D("session %x notification received", wait.sid);
+    return 0;
+}
+
+int ProxyClient::malloc(uint8_t** buffer, uint32_t length) {
+    // Cannot share kernel buffers through the proxy
+    *buffer = (uint8_t*)::mmap(0, length, PROT_READ | PROT_WRITE,
+                               MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    if (*buffer == MAP_FAILED) {
+        errno = ENOMEM;
+        return -1;
+    }
+    LOG_D("mmap'd buffer %p len %u", *buffer, length);
+    return 0;
+}
+
+int ProxyClient::free(uint8_t* buffer, uint32_t length) {
+    LOG_D("munmap'd buffer %p len %u", buffer, length);
+    ::munmap(buffer, length);
+    return 0;
+}
+
+int ProxyClient::map(struct mc_ioctl_map& map) {
+    LOG_D("map buffer(s) to session %x", map.sid);
+    // Find session connection
+    auto connection = pimpl_->connections.find(map.sid);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    MapRequest request;
+    request.set_sid(map.sid);
+    for (int i = 0; i < MC_MAP_MAX; i++) {
+        if (map.bufs[i].va) {
+            if (map.bufs[i].len > BUFFER_LENGTH_MAX) {
+                LOG_E("Incorrect length for buffer: %u", map.bufs[i].len);
+                errno = -EINVAL;
+                return -1;
+            }
+            auto buffer = request.add_buffers();
+            buffer->set_len(map.bufs[i].len);
+            buffer->set_flags(map.bufs[i].flags);
+        }
+    }
+    // Exchange
+    MapResponse response;
+    if (connection->call(MAP, request, response)) {
+        // Error logged in call()
+        if (connection->isBroken()) {
+            pimpl_->connections.deleteConnection(map.sid);
+        }
+        return -1;
+    }
+    // Response
+    if (response.buffers_size() != request.buffers_size()) {
+        LOG_E("Response buffers size (%d) does not match request's (%d)",
+              response.buffers_size(), request.buffers_size());
+        return -1;
+    }
+    int buffer_index = 0;
+    for (int i = 0; i < MC_MAP_MAX; i++) {
+        if (map.bufs[i].va) {
+            const MapResponse_Buffers& buf = response.buffers(buffer_index++);
+            if (!buf.has_sva()) {
+                LOG_E("Required parameter missing");
+                return -1;
+            }
+            map.bufs[i].sva = buf.sva();
+        }
+    }
+    // Success
+    errno = saved_errno;
+    auto session = connection->session();
+    for (int i = 0; i < MC_MAP_MAX; i++) {
+        if (map.bufs[i].va) {
+            session->addBuffer(map.bufs[i]);
+        }
+    }
+    LOG_D("session %x buffer(s) mapped", map.sid);
+    return 0;
+}
+
+int ProxyClient::unmap(const struct mc_ioctl_map& map) {
+    LOG_D("unmap buffer(s) to session %x", map.sid);
+    // Find session connection
+    auto connection = pimpl_->connections.find(map.sid);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    UnmapRequest request;
+    request.set_sid(map.sid);
+    for (int i = 0; i < MC_MAP_MAX; i++) {
+        if (map.bufs[i].va) {
+            if (!map.bufs[i].sva) {
+                errno = EINVAL;
+                return -1;
+            }
+            UnmapRequest_Buffers* buffer = request.add_buffers();
+            buffer->set_sva(map.bufs[i].sva);
+        }
+    }
+    // Exchange
+    UnmapResponse response;
+    if (connection->call(UNMAP, request, response)) {
+        // Error logged in call()
+        if (connection->isBroken()) {
+            pimpl_->connections.deleteConnection(map.sid);
+        }
+        return -1;
+    }
+    // No response
+    // Success
+    errno = saved_errno;
+    auto session = connection->session();
+    for (int i = 0; i < MC_MAP_MAX; i++) {
+        if (map.bufs[i].va) {
+            if (session->removeBuffer(map.bufs[i].sva)) {
+                LOG_E("Unmapped buffer not found in session: %llu",
+                      map.bufs[i].sva);
+                return -1;
+            }
+        }
+    }
+    LOG_D("session %x buffer(s) unmapped", map.sid);
+    return 0;
+}
+
+int ProxyClient::getError(struct mc_ioctl_geterr& err) {
+    LOG_D("get session %x exit code", err.sid);
+    // Find session connection
+    auto connection = pimpl_->connections.find(err.sid);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    GetErrorRequest request;
+    request.set_sid(err.sid);
+    // Exchange
+    GetErrorResponse response;
+    if (connection->call(GET_ERROR, request, response)) {
+        // Error logged in call()
+        if (connection->isBroken()) {
+            pimpl_->connections.deleteConnection(err.sid);
+        }
+        return -1;
+    }
+    // Response
+    if (!response.has_exit_code()) {
+        LOG_E("Required parameter missing");
+        return -1;
+    }
+    // Success
+    errno = saved_errno;
+    err.value = response.exit_code();
+    LOG_D("session %x exit code %d", err.sid, err.value);
+    return 0;
+}
+
+int ProxyClient::Impl::getVersion(ClientConnection& conn,
+                                  struct mc_version_info& version_info) {
+    LOG_D("get version");
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    GetVersionRequest request;
+    // No inputs to set
+    // Exchange
+    GetVersionResponse response;
+    if (conn.call(GET_VERSION, request, response)) {
+        // Error logged in call()
+        return -1;
+    }
+    // Response
+    if (!response.has_product_id() ||
+            !response.has_mci() ||
+            !response.has_so() ||
+            !response.has_mclf() ||
+            !response.has_container() ||
+            !response.has_mc_config() ||
+            !response.has_tl_api() ||
+            !response.has_dr_api() ||
+            !response.has_nwd()) {
+        LOG_E("Required parameter missing");
+        return -1;
+    }
+    // Success
+    errno = saved_errno;
+    ::strncpy(version_info.product_id, response.product_id().c_str(),
+              MC_PRODUCT_ID_LEN);
+    version_info.product_id[MC_PRODUCT_ID_LEN - 1] = '\0';
+    version_info.version_mci = response.mci();
+    version_info.version_so = response.so();
+    version_info.version_mclf = response.mclf();
+    version_info.version_container = response.container();
+    version_info.version_mc_config = response.mc_config();
+    version_info.version_tl_api = response.tl_api();
+    version_info.version_dr_api = response.dr_api();
+    version_info.version_nwd = response.nwd();
+    return 0;
+}
+
+int ProxyClient::getVersion(struct mc_version_info& version_info) {
+    if (!pimpl_->is_open_) {
+        errno = EBADF;
+        return -1;
+    }
+    version_info = pimpl_->version_info;
+    return 0;
+}
+
+int ProxyClient::gpRequestCancellation(uint32_t session_id) {
+    LOG_D("cancel GP operation on session %x", session_id);
+    // Find session connection
+    auto connection = pimpl_->connections.find(session_id);
+    if (!connection) {
+        errno = ENXIO;
+        return -1;
+    }
+    int saved_errno = errno;
+    errno = EHOSTUNREACH;
+    // Request
+    GpRequestCancellationRequest request;
+    request.set_sid(session_id);
+    // Exchange
+    GpRequestCancellationResponse response;
+    if (connection->call(GP_REQUESTCANCELLATION, request, response)) {
+        // Error logged in call()
+        if (connection->isBroken()) {
+            pimpl_->connections.deleteConnection(session_id);
+        }
+        return -1;
+    }
+    // No response
+    // Success
+    errno = saved_errno;
+    return 0;
+}
diff --git a/mobicore/ClientLib/src/proxy_client.h b/mobicore/ClientLib/src/proxy_client.h
new file mode 100644 (file)
index 0000000..7fee59f
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PROXY_CLIENT_H__
+#define __PROXY_CLIENT_H__
+
+#include "iclient.h"
+
+class ProxyClient: public IClient {
+    struct Impl;
+    Impl* const pimpl_;
+public:
+    ProxyClient();
+    ~ProxyClient();
+    virtual int open() override;
+    virtual int close() override;
+    virtual bool isOpen() const override;
+    virtual int hasOpenSessions() const override;
+    virtual int openSession(struct mc_ioctl_open_session& session) override;
+    virtual int openTrustlet(struct mc_ioctl_open_trustlet& trustlet) override;
+    virtual int closeSession(uint32_t session_id) override;
+    virtual int notify(uint32_t session_id) override;
+    virtual int waitNotification(const struct mc_ioctl_wait& wait) override;
+    virtual int malloc(uint8_t** buffer, uint32_t length) override;
+    virtual int free(uint8_t* buffer, uint32_t length) override;
+    virtual int map(struct mc_ioctl_map& map) override;
+    virtual int unmap(const struct mc_ioctl_map& map) override;
+    virtual int getError(struct mc_ioctl_geterr& err) override;
+    virtual int getVersion(struct mc_version_info& version_info) override;
+    virtual int gpRequestCancellation(uint32_t session_id) override;
+};
+
+#endif // __PROXY_CLIENT_H__
diff --git a/mobicore/ClientLib/src/proxy_common.h b/mobicore/ClientLib/src/proxy_common.h
new file mode 100644 (file)
index 0000000..b2c7ca8
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <algorithm>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include <stdlib.h>     // malloc, free
+#include <sys/mman.h>   // mmap, munmap
+
+#include "mc_user.h"    // mc_ioctl_buffer
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+#include "mc.pb.h"
+#pragma GCC diagnostic pop
+
+#define SOCKET_PATH             "@/com/trustonic/tee_proxy"
+#define PROTOCOL_MAGIC          "T7e3"
+#define PROTOCOL_VERSION        1
+
+/*
+ * ProtoBuf gives us the serialisation mechanism, but that's not enough to send
+ * our RPC messages: we also need to pass the method we want to call, the total
+ * length of the data, and a magic number is usually welcome too. While at it,
+ * we'll throw a version number just in case.
+ *
+ * Hence:
+ *               ----------------------
+ *              |     Magic number     |        4 bytes (text)
+ *               ----------------------
+ *              |  Method  |  Version  |        2 + 2 bytes (LE)
+ *               ----------------------
+ *              |    Message length    |        4 bytes (LE)
+ *               ----------------------
+ *              |                      |
+ *              |     Message data     |        N bytes (text)
+ *              ~                      ~
+ *              |                      |
+ *               ----------------------
+ */
+
+namespace com {
+namespace trustonic {
+namespace tee_proxy {
+
+struct RequestHeader {
+    char magic[4];
+    uint16_t version;
+    uint16_t method;
+    uint32_t length;
+};
+
+struct ResponseHeader {
+    char magic[4];
+    uint16_t version;
+    uint16_t method;
+    int32_t proto_rc;           // -errno if negative, length of data otherwise
+    uint32_t method_rc;         // errno from called method on server side
+};
+
+enum RpcMethod {
+    OPEN_SESSION = 0,
+    OPEN_TRUSTLET = 1,
+    CLOSE_SESSION = 2,
+    NOTIFY = 3,
+    WAIT = 4,
+    MAP = 5,
+    UNMAP = 6,
+    GET_ERROR = 7,
+    GET_VERSION = 9,
+    GP_REQUESTCANCELLATION = 27,
+};
+
+class Session {
+public:
+    class Buffer {
+        enum Type {
+            NONE,       // No buffer
+            CLIENT,     // Buffer managed by caller (client side)
+            SERVER,     // Buffer mmap'd (server side)
+        };
+        mc_ioctl_buffer info_;
+        void* address_;
+        Type type_;
+        int alloc(size_t length, uint32_t flags = MC_IO_MAP_INPUT_OUTPUT) {
+            // No posix_memalign, aligned_alloc, valloc, memalign, pvalloc in
+            // Android so we rely on mmap to give us page-aligned memory
+            size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
+            size_t aligned_length = (length + page_mask) & ~page_mask;
+            void* buf = ::mmap(0, aligned_length, PROT_READ | PROT_WRITE,
+                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+            if (buf == MAP_FAILED) {
+                LOG_E("Failed to allocate");
+                return -1;
+            }
+            type_ = SERVER;
+            address_ = buf;
+            info_.va = reinterpret_cast<uintptr_t>(address_);
+            info_.len = static_cast<uint32_t>(length);
+            info_.flags = flags;
+            LOG_D("alloc'd buffer %p:%u:%x", address_, info_.len, info_.flags);
+            return 0;
+        }
+    public:
+        Buffer(const Buffer&) = delete;
+        Buffer& operator=(const Buffer&) = delete;
+        // Constructor from buffer: allocate and fill in
+        Buffer(std::string buffer): address_(nullptr) {
+            if (!alloc(buffer.length())) {
+                update(buffer);
+            }
+        }
+        // Constructor for client TCI: pointer and length (can be null) given
+        Buffer(void* address, size_t length): address_(address) {
+            if (address_) {
+                info_.va = reinterpret_cast<uintptr_t>(address_);
+                info_.len = static_cast<uint32_t>(length);
+                info_.flags = MC_IO_MAP_INPUT_OUTPUT;
+                type_ = CLIENT;
+                LOG_D("use buffer %p:%u:%x", address_, info_.len, info_.flags);
+            } else {
+                info_.va = 0;
+                info_.len = 0;
+                info_.flags = 0;
+                type_ = NONE;
+            }
+            info_.sva = 0;
+        }
+        // Constructor for server buffer: allocate
+        Buffer(uint32_t length, uint32_t flags): address_(nullptr) {
+            alloc(length, flags);
+        }
+        // Constructor for client buffer: info given
+        Buffer(mc_ioctl_buffer info): info_(info) {
+            address_ = reinterpret_cast<void*>(
+                           static_cast<uintptr_t>(info_.va));
+            type_ = CLIENT;
+            LOG_D("use buffer %p:%u:%x", address_, info_.len, info_.flags);
+        }
+        ~Buffer() {
+            if (type_ == Buffer::SERVER) {
+                LOG_D("unmap buffer %p:%u:%x", address_, info_.len,
+                      info_.flags);
+                ::munmap(address_, info_.len);
+            }
+        }
+        // Accessors
+        const mc_ioctl_buffer& info() const {
+            return info_;
+        }
+        void* address() const {
+            return address_;
+        }
+        void setSva(uint64_t sva) {
+            info_.sva = sva;
+        }
+        int update(const std::string& buf) {
+            if (buf.length() != info_.len) {
+                LOG_E("Failed to update TCI");
+                return -1;
+            }
+            if (type_ != NONE) {
+                ::memcpy(address_, buf.c_str(), info_.len);
+            }
+            return 0;
+        }
+    };
+private:
+    uint32_t id_;
+    Buffer* tci_;
+    std::mutex buffers_mutex_;
+    std::vector<Buffer*> buffers_;
+public:
+    Session(uint32_t id, Buffer* tci): id_(id), tci_(tci) {}
+    ~Session() {
+        delete tci_;
+        for (auto& buf: buffers_) {
+            delete buf;
+        }
+    }
+    uint32_t id() const {
+        return id_;
+    }
+    bool hasTci() const {
+        return tci_;
+    }
+    const void* tci() const {
+        return tci_->address();
+    }
+    size_t tciLen() const {
+        return tci_->info().len;
+    }
+    int updateTci(const std::string& buf) {
+        return tci_->update(buf);
+    }
+    void addBuffer(Buffer* buffer) {
+        LOG_D("%p %s: 0x%llx", this, __FUNCTION__, buffer->info().sva);
+        std::lock_guard<std::mutex> buffers_lock(buffers_mutex_);
+        buffers_.push_back(buffer);
+    }
+    void addBuffer(mc_ioctl_buffer& info) {
+        LOG_D("%p %s: 0x%llx", this, __FUNCTION__, info.sva);
+        std::lock_guard<std::mutex> buffers_lock(buffers_mutex_);
+        auto buffer = new Buffer(info);
+        buffers_.push_back(buffer);
+    }
+    int removeBuffer(uint64_t sva) {
+        LOG_D("%p %s: %jx", this, __FUNCTION__, sva);
+        std::lock_guard<std::mutex> buffers_lock(buffers_mutex_);
+        auto it = std::find_if(buffers_.begin(), buffers_.end(),
+        [this, sva](Buffer* buffer) {
+            return buffer->info().sva == sva;
+        });
+        if (it == buffers_.end()) {
+            // Not found
+            return -1;
+        }
+        delete *it;
+        buffers_.erase(it);
+        return 0;
+    }
+    // Must be called under buffers_mutex_
+    Buffer* findBuffer(uint64_t sva) {
+        for (auto& buf: buffers_) {
+            if (buf->info().sva == sva) {
+                return buf;
+            }
+        }
+        return nullptr;
+    }
+    std::mutex& buffersMutex() {
+        return buffers_mutex_;
+    }
+    const std::vector<Buffer*>& buffers() {
+        return buffers_;
+    }
+};
+
+static int recv_all(int sock, const char* what, void* buffer, size_t length,
+                    bool may_close = false) {
+    auto cbuffer = static_cast<char*>(buffer);
+    size_t count = 0;
+    while (count < length) {
+        ssize_t rc = ::recv(sock, &cbuffer[count], length - count, 0);
+        if (rc <= 0) {
+            if (rc == 0) {
+                if (may_close) {
+                    LOG_D("socket closed");
+                } else {
+                    LOG_E("socket closed while receiving %s", what);
+                }
+                return -1;
+            }
+            if (errno != EINTR) {
+                LOG_ERRNO(what);
+                return -1;
+            }
+            LOG_D("signal ignored while sending %s", what);
+            continue;
+        } else {
+            count += rc;
+        }
+    }
+    return 0;
+}
+
+static const int32_t timeout_max = 1000;        // 1s
+
+static int send_all(int sock, const char* what, const void* buffer,
+                    size_t length) {
+    auto cbuffer = static_cast<const char*>(buffer);
+    size_t count = 0;
+    while (count < length) {
+        ssize_t rc = ::send(sock, &cbuffer[count], length - count,
+                            MSG_NOSIGNAL);
+        if (rc <= 0) {
+            if (rc == 0) {
+                LOG_E("socket closed while sending %s", what);
+                return -1;
+            }
+            if (errno != EINTR) {
+                LOG_ERRNO(what);
+                return -1;
+            }
+            LOG_D("signal ignored while sending %s", what);
+            continue;
+        } else {
+            count += rc;
+        }
+    }
+    return 0;
+}
+
+#ifndef NDEBUG
+static const char* methodToString(enum RpcMethod method) {
+    switch (method) {
+        case OPEN_SESSION:
+            return "openSession";
+        case OPEN_TRUSTLET:
+            return "openTruslet";
+        case CLOSE_SESSION:
+            return "closeSession";
+        case NOTIFY:
+            return "notify";
+        case WAIT:
+            return "waitNotification";
+        case MAP:
+            return "map";
+        case UNMAP:
+            return "unmap";
+        case GET_ERROR:
+            return "getError";
+        case GET_VERSION:
+            return "getVersion";
+        case GP_REQUESTCANCELLATION:
+            return "gpRequestCancellation";
+    }
+    return "unknown";
+}
+#endif
+
+}  // namespace tee_proxy
+}  // namespace trustonic
+}  // namespace com
diff --git a/mobicore/ClientLib/src/proxy_server.cpp b/mobicore/ClientLib/src/proxy_server.cpp
new file mode 100644 (file)
index 0000000..f307484
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <string>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#include "driver_client.h"
+#undef LOG_TAG
+#define LOG_TAG "TeeProxyServer"
+#include "log.h"
+#include "proxy_common.h"
+#include "proxy_server.h"
+
+using namespace com::trustonic::tee_proxy;
+
+template <class T>
+class FreeMe {
+    T* t_;
+public:
+    FreeMe(T* t): t_(t) {}
+    ~FreeMe() {
+        ::free(t_);
+    }
+    operator T* () {
+        return t_;
+    }
+    operator uintptr_t () {
+        return reinterpret_cast<uintptr_t>(t_);
+    }
+};
+
+class ServerConnection {
+    int listen_socket_;
+    int socket_ = -1;
+    pid_t pid_ = 0;
+    DriverClient driver;
+    std::mutex connection_mutex;     // Protects is_running_ and session_
+    bool is_running_ = false;
+    Session* session_ = nullptr;
+    std::thread thread_;
+    int receiveCredentials() {
+        // Make sure we can receive credentials
+        int enable = 1;
+        if (::setsockopt(socket_, SOL_SOCKET, SO_PASSCRED, &enable,
+                         sizeof(enable))) {
+            LOG_ERRNO("setsockopt");
+            return -1;
+        }
+
+        struct ucred credentials;
+        char ctrl[CMSG_SPACE(sizeof(credentials))];
+        struct iovec iov[1] = { { 0, 0 } };
+        struct msghdr msg = { 0, 0, iov, 1, ctrl, sizeof(ctrl), 0 };
+
+        msg.msg_iov->iov_base = nullptr;
+        msg.msg_iov->iov_len  = 0;
+        do {
+            if (::recvmsg(socket_, &msg, 0) == 0) {
+                break;
+            }
+            if ((errno != EINTR) && (errno != EAGAIN)) {
+                LOG_ERRNO("recvmsg");
+                return -1;
+            }
+        } while (true);
+
+        if (msg.msg_controllen < sizeof(struct cmsghdr)) {
+            errno = EINVAL;
+            LOG_ERRNO("check");
+            return -1;
+        }
+        struct cmsghdr* cmptr = CMSG_FIRSTHDR(&msg);
+        size_t size = sizeof(credentials);
+        if ((cmptr->cmsg_len != CMSG_LEN(size)) ||
+                (cmptr->cmsg_level != SOL_SOCKET) ||
+                (cmptr->cmsg_type != SCM_CREDENTIALS)) {
+            errno = EINVAL;
+            LOG_ERRNO("check");
+            return -1;
+        }
+
+        credentials = *(struct ucred*)CMSG_DATA(cmptr);
+        pid_ = credentials.pid;
+        return 0;
+    }
+    void connectionThread() {
+        LOG_D("thread entered %p", this);
+        std::string buffer;
+        do {
+            // Request
+            RpcMethod method;
+            {
+                // Receive request header
+                RequestHeader header;
+                if (recv_all(socket_, "header", &header, sizeof(header),
+                             true)) {
+                    break;
+                }
+                if (::memcmp(header.magic, PROTOCOL_MAGIC,
+                             sizeof(header.magic))) {
+                    LOG_E("Wrong magic");
+                    break;
+                }
+                if (header.version != PROTOCOL_VERSION) {
+                    LOG_E("Wrong version");
+                    break;
+                }
+                method = static_cast<RpcMethod>(header.method);
+                buffer.resize(header.length);
+                LOG_D("receive %u bytes of data for method %s",
+                      header.length, methodToString(method));
+
+                // Receive request data
+                if (recv_all(socket_, "data", &buffer[0], header.length)) {
+                    break;
+                }
+            }
+
+            // Dispatch:
+            // * method_rc is return code from lower layer
+            // * call returns -errno in case of error, length of data otherwise
+            int method_rc = 0;
+            int proto_rc = call(method, buffer, method_rc);
+
+            // Response
+            {
+                // Send response header
+                ResponseHeader header;
+                ::memcpy(header.magic, PROTOCOL_MAGIC, sizeof(header.magic));
+                header.version = PROTOCOL_VERSION;
+                header.method = static_cast<uint16_t>(method);
+                header.proto_rc = proto_rc;
+                header.method_rc = method_rc;
+                if (send_all(socket_, "header", &header, sizeof(header))) {
+                    break;
+                }
+
+                // Send response data
+                if (header.proto_rc > 0) {
+                    LOG_D("send %d bytes of data", header.proto_rc);
+                    if (send_all(socket_, "data", &buffer[0],
+                                 header.proto_rc)) {
+                        break;
+                    }
+                }
+            }
+        } while (driver.isOpen());
+        LOG_D("thread exiting %p", this);
+
+        // Close associated client
+        driver.close();
+        ::close(socket_);
+        is_running_ = false;
+        LOG_D("thread exited %p", this);
+    }
+public:
+    ServerConnection(int listen_socket): listen_socket_(listen_socket) {}
+    ~ServerConnection() {
+        delete session_;
+    }
+    int open() {
+        socket_ = ::accept(listen_socket_, nullptr, nullptr);
+        if (socket_ < 0) {
+            return -1;
+        }
+        if (receiveCredentials() < 0) {
+            ::close(socket_);
+            return -1;
+        }
+        // Create specific client for this connection
+        if (driver.open()) {
+            LOG_ERRNO("open driver");
+            ::close(socket_);
+            return -1;
+        }
+        // Start thread
+        is_running_ = true;
+        thread_ = std::thread(&ServerConnection::connectionThread, this);
+        LOG_I("proxy server open, client PID: %d", pid_);
+        return 0;
+    }
+    int close() {
+        thread_.join();
+        // driver and socket are closed at end of thread
+        LOG_I("proxy server closed, client PID: %d", pid_);
+        return 0;
+    }
+    bool isRunning() const {
+        return is_running_;
+    }
+    int call(RpcMethod method, std::string& buffer, int& method_rc) {
+        switch (method) {
+            case OPEN_SESSION:
+                return openSession(buffer, method_rc);
+            case OPEN_TRUSTLET:
+                return openTrustlet(buffer, method_rc);
+            case CLOSE_SESSION:
+                return closeSession(buffer, method_rc);
+            case NOTIFY:
+                return notify(buffer, method_rc);
+            case WAIT:
+                return waitNotification(buffer, method_rc);
+            case MAP:
+                return map(buffer, method_rc);
+            case UNMAP:
+                return unmap(buffer, method_rc);
+            case GET_ERROR:
+                return getError(buffer, method_rc);
+            case GET_VERSION:
+                return getVersion(buffer, method_rc);
+            case GP_REQUESTCANCELLATION:
+                return gpRequestCancellation(buffer, method_rc);
+        }
+        LOG_E("unkown method %d", method);
+        return -1;
+    }
+    // Actions
+    int openSession(std::string& buffer, int& method_rc);
+    int openTrustlet(std::string& buffer, int& method_rc);
+    int closeSession(std::string& buffer, int& method_rc);
+    int notify(std::string& buffer, int& method_rc);
+    int waitNotification(std::string& buffer, int& method_rc);
+    int map(std::string& buffer, int& method_rc);
+    int unmap(std::string& buffer, int& method_rc);
+    int getError(std::string& buffer, int& method_rc);
+    int getVersion(std::string& buffer, int& method_rc);
+    int gpRequestCancellation(std::string& buffer, int& method_rc);
+};
+
+struct ProxyServer::Impl {
+    int listen_socket = -1;
+    int signal_pipe[2];
+    std::thread thread;
+};
+
+ProxyServer::ProxyServer(): pimpl_(new Impl) {
+}
+
+ProxyServer::~ProxyServer() {
+    delete pimpl_;
+}
+
+int ProxyServer::open() {
+    // Make sure we have access to the driver
+    DriverClient driver;
+    if (driver.open()) {
+        LOG_ERRNO("open driver");
+        return -1;
+    }
+    driver.close();
+
+    // Make sure we're alone
+    int sock = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        LOG_ERRNO("socket");
+        return -1;
+    }
+    struct sockaddr_un sock_un;
+    sock_un.sun_family = AF_UNIX;
+    ::strncpy(sock_un.sun_path, SOCKET_PATH, sizeof(sock_un.sun_path) - 1);
+    socklen_t len = static_cast<socklen_t>(strlen(sock_un.sun_path) +
+                                           sizeof(sock_un.sun_family));
+    sock_un.sun_path[0] = '\0';         // Abstract
+    if (::bind(sock, reinterpret_cast<struct sockaddr*>(&sock_un), len) == 0) {
+        if (::listen(sock, 5) == 0) {
+            if (pipe(pimpl_->signal_pipe) == 0) {
+                pimpl_->listen_socket = sock;
+                pimpl_->thread = std::thread(&ProxyServer::run, this);
+                LOG_D("proxy open");
+                return 0;
+            } else {
+                LOG_ERRNO("pipe");
+            }
+        } else {
+            LOG_ERRNO("listen");
+        }
+    } else {
+        LOG_ERRNO("bind");
+    }
+    ::close(sock);
+    return -1;
+}
+
+int ProxyServer::close() {
+    if (pimpl_->listen_socket < 0) {
+        errno = EBADF;
+        return -1;
+    }
+    ::close(pimpl_->listen_socket);
+    pimpl_->listen_socket = -1;
+    // Make thread stop
+    if (pimpl_->thread.joinable()) {
+        ::write(pimpl_->signal_pipe[1], "c", 1);
+        ::close(pimpl_->signal_pipe[1]);
+        pimpl_->thread.join();
+    }
+    LOG_D("proxy closed");
+    return 0;
+}
+
+void ProxyServer::run() {
+    std::vector<ServerConnection*> connections;
+
+    LOG_D("proxy ready");
+    while (pimpl_->listen_socket >= 0) {
+        // Wait for new connections
+        fd_set fds;
+        FD_ZERO(&fds);
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+        FD_SET(pimpl_->signal_pipe[0], &fds);
+        FD_SET(pimpl_->listen_socket, &fds);
+#pragma GCC diagnostic pop
+        if ((::select(FD_SETSIZE, &fds, nullptr, nullptr, nullptr) < 0) &&
+                (errno != EINTR)) {
+            LOG_ERRNO("listen on server socket");
+            break;
+        }
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+        if (FD_ISSET(pimpl_->signal_pipe[0], &fds)) {
+#pragma GCC diagnostic pop
+            LOG_I("thread received stop message");
+            // Wait for client threads to stop
+            for (auto& connection: connections) {
+                connection->close();
+                LOG_D("delete connection %p", connection);
+                delete connection;
+            }
+            break;
+        }
+        auto connection = new ServerConnection(pimpl_->listen_socket);
+        if (connection->open() < 0) {
+            LOG_ERRNO("new connection");
+            delete connection;
+            // Relax
+            usleep(100000);
+        } else {
+            LOG_D("new connection %p", connection);
+            connections.push_back(connection);
+        }
+        // Cleanup dead connections
+        auto it = connections.begin();
+        while (it != connections.end()) {
+            auto connection = *it;
+            if (!connection->isRunning()) {
+                it = connections.erase(it);
+                connection->close();
+                LOG_D("delete connection %p", connection);
+                delete connection;
+            } else {
+                it++;
+            }
+        }
+    }
+    LOG_D("proxy exited");
+}
+
+int ServerConnection::openSession(std::string& buffer, int& method_rc) {
+    LOG_D("enter %s", __FUNCTION__);
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (session_) {
+        LOG_E("Session exists");
+        return -EBUSY;
+    }
+    // Request
+    OpenSessionRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_uuid() || !request.has_is_gp_uuid() ||
+            !request.has_login_type() || !request.has_login_data()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    // Call driver
+    struct mc_ioctl_open_session session;
+    if (request.uuid().length() != sizeof(session.uuid)) {
+        LOG_E("Incorrect parameter uuid");
+        return -EINVAL;
+    }
+    ::memcpy(&session.uuid, request.uuid().c_str(), sizeof(session.uuid));
+    session.is_gp_uuid = request.is_gp_uuid();
+    Session::Buffer* tci;
+    if (request.has_tci()) {
+        tci = new Session::Buffer(request.tci());
+        session.tcilen = tci->info().len;
+        session.tci = tci->info().va;
+    } else {
+        tci = nullptr;
+        session.tcilen = 0;
+        session.tci = 0;
+    }
+    std::unique_ptr<Session::Buffer> tci_ptr(tci);
+    session.identity.login_type =
+        static_cast<mc_login_type>(request.login_type());
+    session.identity.pid = pid_;
+    if (request.login_data().length() != sizeof(session.identity.login_data)) {
+        LOG_E("Incorrect parameter login_data");
+        return -EINVAL;
+    }
+    ::memcpy(&session.identity.login_data, request.login_data().c_str(),
+             sizeof(session.identity.login_data));
+
+    // Call
+    if (driver.openSession(session)) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // Response
+    OpenSessionResponse response;
+    response.set_id(session.sid);
+    if (!response.SerializeToString(&buffer)) {
+        LOG_E("Failed to serialize");
+        return -EPIPE;
+    }
+    LOG_D("session %x open", session.sid);
+    session_ = new Session(session.sid, tci_ptr.release());
+    return static_cast<int>(buffer.length());
+}
+
+int ServerConnection::openTrustlet(std::string& buffer, int& method_rc) {
+    LOG_D("enter %s", __FUNCTION__);
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (session_) {
+        LOG_E("Session exists");
+        return -EBUSY;
+    }
+    // Request
+    OpenTrustletRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_spid() || !request.has_trustapp()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    // Call driver
+    struct mc_ioctl_open_trustlet trustlet;
+    trustlet.spid = request.spid();
+    trustlet.tlen = static_cast<int>(request.trustapp().length());
+    // Create TrustApp buffer
+    FreeMe<void> trustapp = ::malloc(trustlet.tlen);
+    if (!trustapp) {
+        LOG_E("Failed to allocate TrustApp");
+        return -ENOMEM;
+    }
+    ::memcpy(trustapp, request.trustapp().c_str(), trustlet.tlen);
+    trustlet.buffer = trustapp;
+    Session::Buffer* tci;
+    if (request.has_tci()) {
+        tci = new Session::Buffer(request.tci());
+        trustlet.tcilen = tci->info().len;
+        trustlet.tci = tci->info().va;
+    } else {
+        tci = nullptr;
+        trustlet.tcilen = 0;
+        trustlet.tci = 0;
+    }
+    std::unique_ptr<Session::Buffer> tci_ptr(tci);
+
+    // Call
+    if (driver.openTrustlet(trustlet)) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // Response
+    OpenTrustletResponse response;
+    response.set_id(trustlet.sid);
+    if (!response.SerializeToString(&buffer)) {
+        LOG_E("Failed to serialize");
+        return -EPIPE;
+    }
+    LOG_D("session %x open", trustlet.sid);
+    session_ = new Session(trustlet.sid, tci_ptr.release());
+    return static_cast<int>(buffer.length());
+}
+
+int ServerConnection::closeSession(std::string& buffer, int& method_rc) {
+    // Request
+    CloseSessionRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_id()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    // Check session
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (!session_) {
+        LOG_E("No session");
+        return -ENOENT;
+    }
+
+    // Call
+    if (driver.closeSession(request.id())) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // No response
+    LOG_D("session %x closed", request.id());
+    delete session_;
+    session_ = nullptr;
+    return 0;
+}
+
+int ServerConnection::notify(std::string& buffer, int& method_rc) {
+    // Request
+    NotifyRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    // Check session
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (!session_) {
+        LOG_E("No session");
+        return -ENOENT;
+    }
+    if (!request.has_sid() || (session_->hasTci() && !request.has_tci())) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    // Update TCI
+    if (session_->hasTci() && session_->updateTci(request.tci())) {
+        LOG_E("Failed to update TCI");
+        return -EINVAL;
+    }
+    // Update mapped buffers
+    if (request.buffers_size() > static_cast<int>(session_->buffers().size())) {
+        LOG_E("Too many buffers: %d > %zu", request.buffers_size(),
+              session_->buffers().size());
+        return -EINVAL;
+    }
+    for (int i = 0; i < request.buffers_size(); i++) {
+        const NotifyRequest_Buffers& session_buffer = request.buffers(i);
+        if (!session_buffer.has_sva()) {
+            LOG_E("Given buffer has no SVA");
+            return -EINVAL;
+        }
+        if (!session_buffer.has_data()) {
+            LOG_E("Given buffer has no data");
+            return -EINVAL;
+        }
+        auto buf = session_->findBuffer(session_buffer.sva());
+        if (!buf) {
+            LOG_E("No buffer record for SVA %jx in session %x",
+                  session_buffer.sva(), request.sid());
+            return -EPIPE;
+        }
+        buf->update(session_buffer.data());
+    }
+
+    // Call
+    if (driver.notify(request.sid())) {
+        method_rc = errno;
+        return 0;
+    }
+
+    // No response
+    LOG_D("session %x notification sent", request.sid());
+    return 0;
+}
+
+int ServerConnection::waitNotification(std::string& buffer, int& method_rc) {
+    // Request
+    WaitNotificationRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_sid() || !request.has_timeout() ||
+            !request.has_partial()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    // Refuse big timeouts (client shall retry so we know it's still around)
+    if ((request.timeout() < 0) || (request.timeout() > timeout_max)) {
+        LOG_E("Timeout exceeds 10s");
+        return -ENOENT;
+    }
+
+    // Find session
+    LOG_D("session %x wait for notification", request.sid());
+    // Check session
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (!session_) {
+        LOG_E("No session");
+        return -ENOENT;
+    }
+    // Call driver
+    struct mc_ioctl_wait wait;
+    wait.sid = request.sid();
+    wait.timeout = request.timeout();
+
+    // Call
+    if (driver.waitNotification(wait)) {
+        method_rc = errno;
+        if ((errno == ETIME) && request.partial()) {
+            // No point sending buffers on partial timeout
+            return 0;
+        }
+        // Send potentially modified buffers back on failure too
+        LOG_ERRNO("waitNotification");
+    }
+
+    // Response
+    WaitNotificationResponse response;
+    // Send updated TCI
+    if (session_->hasTci()) {
+        response.set_tci(session_->tci(), session_->tciLen());
+    }
+    // Send updated mapped buffers
+    auto& buffers = session_->buffers();
+    for (auto& buf: buffers) {
+        if (buf->info().flags & MC_IO_MAP_OUTPUT) {
+            auto session_buffer = response.add_buffers();
+            session_buffer->set_sva(buf->info().sva);
+            session_buffer->set_data(buf->address(), buf->info().len);
+        }
+    }
+    if (!response.SerializeToString(&buffer)) {
+        LOG_E("Failed to serialize");
+        return -EPIPE;
+    }
+    LOG_D("session %x notification received", request.sid());
+    return static_cast<int>(buffer.length());
+}
+
+int ServerConnection::map(std::string& buffer, int& method_rc) {
+    // Request
+    MapRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_sid()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    // Check session
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (!session_) {
+        LOG_E("No session");
+        return -ENOENT;
+    }
+    if (request.buffers_size() > MC_MAP_MAX) {
+        LOG_E("Incorrect number of buffers: %d > %d", request.buffers_size(),
+              MC_MAP_MAX);
+        return -EINVAL;
+    }
+    // Prepare local buffers
+    struct mc_ioctl_map map;
+    map.sid = request.sid();
+    LOG_D("map %d buffers to session %x", request.buffers_size(), map.sid);
+    std::vector<std::unique_ptr<Session::Buffer>> buffers;
+    for (int i = 0; i < request.buffers_size(); i++) {
+        const MapRequest_Buffers& session_buffer = request.buffers(i);
+        if (!session_buffer.has_len() || !session_buffer.has_flags()) {
+            LOG_E("Required parameter missing");
+            return -EINVAL;
+        }
+        if (!(session_buffer.flags() & MC_IO_MAP_INPUT_OUTPUT) ||
+                (session_buffer.flags() & ~MC_IO_MAP_INPUT_OUTPUT)) {
+            LOG_E("Incorrect flags for buffer: %x", session_buffer.flags());
+            return -EINVAL;
+        }
+        buffers.emplace_back(new Session::Buffer(session_buffer.len(),
+                             session_buffer.flags()));
+        map.bufs[i] = buffers.back()->info();
+    }
+    for (int i = request.buffers_size(); i < MC_MAP_MAX; i++) {
+        map.bufs[i].va = 0;
+    }
+
+    // Call
+    if (driver.map(map)) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // Response
+    MapResponse response;
+    // Confirm/return buffers
+    for (int i = 0; i < request.buffers_size(); i++) {
+        Session::Buffer* buf = buffers[i].release();
+        buf->setSva(map.bufs[i].sva);
+        session_->addBuffer(buf);
+        auto session_buffer = response.add_buffers();
+        session_buffer->set_sva(map.bufs[i].sva);
+    }
+    if (!response.SerializeToString(&buffer)) {
+        LOG_E("Failed to serialize");
+        return -EPIPE;
+    }
+    LOG_D("session %x %d buffer(s) mapped", map.sid, request.buffers_size());
+    return static_cast<int>(buffer.length());
+}
+
+int ServerConnection::unmap(std::string& buffer, int& method_rc) {
+    // Request
+    UnmapRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_sid()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    if (request.buffers_size() > MC_MAP_MAX) {
+        LOG_E("Incorrect number of buffers: %d", request.buffers_size());
+        return -EINVAL;
+    }
+    // Check session
+    std::lock_guard<std::mutex> connection_lock(connection_mutex);
+    if (!session_) {
+        LOG_E("No session");
+        return -ENOENT;
+    }
+    // Find local buffers
+    struct mc_ioctl_map map;
+    map.sid = request.sid();
+    LOG_D("unmap %d buffers from session %x", request.buffers_size(), map.sid);
+    if (request.buffers_size() > static_cast<int>(session_->buffers().size())) {
+        LOG_E("More buffers to unmap than we have: %d > %zu",
+              request.buffers_size(), session_->buffers().size());
+        return -EINVAL;
+    }
+    std::vector<Session::Buffer*> buffers;
+    for (int i = 0; i < request.buffers_size(); i++) {
+        // Need to find buffer to get VA/length
+        const UnmapRequest_Buffers& session_buffer = request.buffers(i);
+        if (!session_buffer.has_sva()) {
+            LOG_E("Given buffer has no SVA");
+            return -EINVAL;
+        }
+        auto buf = session_->findBuffer(session_buffer.sva());
+        if (!buf) {
+            LOG_E("No buffer record for SVA %jx in session %x",
+                  session_buffer.sva(), request.sid());
+            method_rc = EINVAL;
+            return 0;
+        }
+        map.bufs[i] = buf->info();
+        buffers.push_back(buf);
+    }
+    for (int i = request.buffers_size(); i < MC_MAP_MAX; i++) {
+        map.bufs[i].va = 0;
+    }
+
+    // Call
+    if (driver.unmap(map)) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // No response
+    // Delete buffers
+    for (size_t i = 0; i < buffers.size(); i++) {
+        if (session_->removeBuffer(buffers[i]->info().sva)) {
+            LOG_E("Did not find our buffer anymore!?!");
+            return -EPIPE;
+        }
+    }
+    LOG_D("session %x %d buffer(s) unmapped", map.sid, request.buffers_size());
+    return 0;
+}
+
+int ServerConnection::getError(std::string& buffer, int& method_rc) {
+    // Request
+    GetErrorRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_sid()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+    struct mc_ioctl_geterr err;
+    err.sid = request.sid();
+
+    // Call
+    if (driver.getError(err)) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // Response
+    GetErrorResponse response;
+    response.set_exit_code(err.value);
+    if (!response.SerializeToString(&buffer)) {
+        LOG_E("Failed to serialize");
+        return -EPIPE;
+    }
+    LOG_D("session %x exit code %d", err.sid, err.value);
+    return static_cast<int>(buffer.length());
+}
+
+int ServerConnection::getVersion(std::string& buffer, int& method_rc) {
+    // Request
+    GetVersionRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    // No inputs to check
+    struct mc_version_info version_info;
+
+    // Call
+    if (driver.getVersion(version_info)) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // Response
+    GetVersionResponse response;
+    response.set_product_id(version_info.product_id);
+    response.set_mci(version_info.version_mci);
+    response.set_so(version_info.version_so);
+    response.set_mclf(version_info.version_mclf);
+    response.set_container(version_info.version_container);
+    response.set_mc_config(version_info.version_mc_config);
+    response.set_tl_api(version_info.version_tl_api);
+    response.set_dr_api(version_info.version_dr_api);
+    response.set_nwd(version_info.version_nwd);
+    if (!response.SerializeToString(&buffer)) {
+        LOG_E("Failed to serialize");
+        return -EPIPE;
+    }
+    return static_cast<int>(buffer.length());
+}
+
+int ServerConnection::gpRequestCancellation(std::string& buffer,
+        int& method_rc) {
+    // Request
+    GetErrorRequest request;
+    if (!request.ParseFromString(buffer)) {
+        LOG_E("Failed to parse");
+        return -EPIPE;
+    }
+    if (!request.has_sid()) {
+        LOG_E("Required parameter missing");
+        return -EINVAL;
+    }
+
+    // Call
+    if (driver.gpRequestCancellation(request.sid())) {
+        method_rc = errno;
+        LOG_D("Error reported %s", strerror(errno));
+        return 0;
+    }
+
+    // No response
+    return 0;
+}
diff --git a/mobicore/ClientLib/src/tee_client_api.cpp b/mobicore/ClientLib/src/tee_client_api.cpp
new file mode 100644 (file)
index 0000000..5bcf06b
--- /dev/null
@@ -0,0 +1,972 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "Mci/mcinq.h"          /* TA termination codes */
+
+#undef LOG_TAG
+#define LOG_TAG "TeeGpClient"
+#include "log.h"
+#include "common_client.h"
+#include "tee_client_api.h"
+#include "GpTci.h"      /* Needs stuff from tee_client_api.h or its includes */
+
+//------------------------------------------------------------------------------
+// Macros
+#define _TEEC_GET_PARAM_TYPE(t, i) (((t) >> (4*i)) & 0xF)
+
+//Parameter number
+#define _TEEC_PARAMETER_NUMBER      4
+
+/**
+ * These error codes are still to be decided by GP and as we do not wish to
+ * expose any part of the GP TAF as of yet, for now they will have to live here
+ * until we decide what to do about them.
+ */
+#define TEEC_ERROR_TA_LOCKED        0xFFFF0257
+#define TEEC_ERROR_SD_BLOCKED       0xFFFF0258
+#define TEEC_ERROR_TARGET_KILLED    0xFFFF0259
+
+static const size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
+static CommonClient& client = CommonClient::getInstance();
+
+//------------------------------------------------------------------------------
+// Local functions
+static TEEC_Result _TEEC_UnwindOperation(
+    TEEC_Session_IMP*    session,
+    _TEEC_TCI*           tci,
+    TEEC_Operation*      operation,
+    bool                 copyValues,
+    uint32_t*            returnOrigin);
+
+//------------------------------------------------------------------------------
+static void _libUuidToArray(
+    const TEEC_UUID* uuid,
+    uint8_t*         uuidArr) {
+    uint8_t* pIdentifierCursor = (uint8_t*)uuid;
+    /* offsets and syntax constants. See explanations above */
+#ifdef S_BIG_ENDIAN
+    uint32_t offsets = 0;
+#else
+    uint32_t offsets = 0xF1F1DF13;
+#endif
+    uint32_t i;
+
+    for (i = 0; i < sizeof(TEEC_UUID); i++) {
+        /* Two-digit hex number */
+        uint8_t number;
+        int32_t offset = ((int32_t)((offsets & 0xF) << 28)) >> 28;
+        number = pIdentifierCursor[offset];
+        offsets >>= 4;
+        pIdentifierCursor++;
+
+        uuidArr[i] = number;
+    }
+}
+
+//------------------------------------------------------------------------------
+static TEEC_Result _TEEC_SetupOperation(
+    TEEC_Session_IMP*    session,
+    _TEEC_TCI*           tci,
+    TEEC_Operation*      operation,
+    uint32_t*            returnOrigin) {
+    uint32_t                    i;
+    _TEEC_ParameterInternal*    imp;
+    TEEC_Parameter*             ext;
+    TEEC_Result                 teecResult = TEEC_SUCCESS;
+
+    LOG_D(" %s()", __func__);
+
+    tci->operation.isCancelled = false;
+    tci->operation.paramTypes = 0;
+
+    //operation can be NULL
+    if (operation) {
+        uint32_t n_buf = 0;
+        operation->started = 1;
+        // Buffers to map to SWd
+        struct mc_ioctl_map map;
+        map.sid = session->sessionId;
+        // Operation parameters for the buffers above
+        _TEEC_ParameterInternal* imps[_TEEC_PARAMETER_NUMBER] = { NULL };
+
+        //This design allows a non-NULL buffer with a size of 0 bytes to allow trivial integration with any
+        //implementations of the C library malloc, in which is valid to allocate a zero byte buffer and receive a non-
+        //NULL pointer which may not be de-referenced in return.
+
+        for (i = 0; i < _TEEC_PARAMETER_NUMBER && teecResult == TEEC_SUCCESS; i++) {
+            uint8_t paramType = _TEEC_GET_PARAM_TYPE(operation->paramTypes, i);
+
+            imp = &tci->operation.params[i];
+            ext = &operation->params[i];
+
+            switch (paramType) {
+                case TEEC_VALUE_OUTPUT:
+                    LOG_D("  cycle %d, TEEC_VALUE_OUTPUT", i);
+                    break;
+                case TEEC_NONE:
+                    LOG_D("  cycle %d, TEEC_NONE", i);
+                    break;
+                case TEEC_VALUE_INPUT:
+                case TEEC_VALUE_INOUT: {
+                    LOG_D("  cycle %d, TEEC_VALUE_IN*", i);
+                    imp->value.a = ext->value.a;
+                    imp->value.b = ext->value.b;
+                    break;
+                }
+                case TEEC_MEMREF_TEMP_INPUT:
+                case TEEC_MEMREF_TEMP_OUTPUT:
+                case TEEC_MEMREF_TEMP_INOUT: {
+                    // A Temporary Memory Reference may be null, which can be used
+                    // to denote a special case for the parameter. Output Memory
+                    // References that are null are typically used to request the
+                    // required output size.
+                    LOG_D("  cycle %d, TEEC_MEMREF_TEMP_*", i);
+                    if ((ext->tmpref.size) && (ext->tmpref.buffer)) {
+                        map.bufs[n_buf].va = (uintptr_t)ext->tmpref.buffer;
+                        map.bufs[n_buf].len = (uint32_t)ext->tmpref.size;
+                        map.bufs[n_buf].flags = paramType & TEEC_MEM_INOUT;
+                        imps[n_buf] = imp;
+                        n_buf++;
+                    } else {
+                        LOG_D("  cycle %d, TEEC_TEMP_IN*  - zero pointer or size", i);
+                    }
+                    break;
+                }
+                case TEEC_MEMREF_WHOLE: {
+                    LOG_D("  cycle %d, TEEC_MEMREF_WHOLE", i);
+                    if (ext->memref.parent->size) {
+                        map.bufs[n_buf].va = (uintptr_t)ext->memref.parent->buffer;
+                        map.bufs[n_buf].len = (uint32_t)ext->memref.parent->size;
+                        map.bufs[n_buf].flags = ext->memref.parent->flags & TEEC_MEM_INOUT;
+                        imps[n_buf] = imp;
+                        n_buf++;
+                    }
+                    /* We don't transmit that the mem ref is the whole shared mem */
+                    /* Magic number 4 means that it is a mem ref */
+                    paramType = (uint8_t)ext->memref.parent->flags | 4;
+                    break;
+                }
+                case TEEC_MEMREF_PARTIAL_INPUT:
+                case TEEC_MEMREF_PARTIAL_OUTPUT:
+                case TEEC_MEMREF_PARTIAL_INOUT: {
+                    LOG_D("  cycle %d, TEEC_MEMREF_PARTIAL_*", i);
+                    //Check data flow consistency
+                    if ((((ext->memref.parent->flags & TEEC_MEM_INOUT) == TEEC_MEM_INPUT) &&
+                            (paramType == TEEC_MEMREF_PARTIAL_OUTPUT)) ||
+                            (((ext->memref.parent->flags & TEEC_MEM_INOUT) == TEEC_MEM_OUTPUT) &&
+                             (paramType == TEEC_MEMREF_PARTIAL_INPUT))) {
+                        LOG_E("PARTIAL data flow inconsistency");
+                        *returnOrigin = TEEC_ORIGIN_API;
+                        teecResult = TEEC_ERROR_BAD_PARAMETERS;
+                        break;
+                    }
+                    /* We don't transmit that the mem ref is partial */
+                    paramType &= TEEC_MEMREF_TEMP_INOUT;
+
+                    if (ext->memref.offset + ext->memref.size > ext->memref.parent->size) {
+                        LOG_E("PARTIAL offset/size error");
+                        *returnOrigin = TEEC_ORIGIN_API;
+                        teecResult = TEEC_ERROR_BAD_PARAMETERS;
+                        break;
+                    }
+                    if (ext->memref.size) {
+                        map.bufs[n_buf].va = (uintptr_t)ext->memref.parent->buffer + ext->memref.offset;
+                        map.bufs[n_buf].len = (uint32_t)ext->memref.size;
+                        map.bufs[n_buf].flags = paramType & TEEC_MEM_INOUT;
+                        imps[n_buf] = imp;
+                        n_buf++;
+                    }
+                    break;
+                }
+                default:
+                    LOG_E("cycle %d, default", i);
+                    *returnOrigin = TEEC_ORIGIN_API;
+                    teecResult = TEEC_ERROR_BAD_PARAMETERS;
+                    break;
+            }
+            tci->operation.paramTypes |= (uint32_t)(paramType << i * 4);
+        }
+
+        if (n_buf > MC_MAP_MAX) {
+            LOG_E("too many buffers: %s", strerror(errno));
+            teecResult = TEEC_ERROR_EXCESS_DATA;
+        }
+
+        if ((teecResult == TEEC_SUCCESS) && (tci->operation.isCancelled)) {
+            LOG_E("the operation has been cancelled in COMMS");
+            *returnOrigin = TEEC_ORIGIN_COMMS;
+            teecResult = TEEC_ERROR_CANCEL;
+        }
+
+        // Map buffers
+        if ((teecResult == TEEC_SUCCESS) && (n_buf > 0)) {
+            for (i = n_buf; i < MC_MAP_MAX; i++) {
+                map.bufs[i].va = 0;
+            }
+            if (client.map(map) == 0) {
+                for (i = 0; i < MC_MAP_MAX; i++) {
+                    if (map.bufs[i].va) {
+                        imps[i]->memref.sVirtualAddr = (uint32_t)map.bufs[i].sva;
+                        imps[i]->memref.sVirtualLen = map.bufs[i].len;
+                    }
+                }
+            } else {
+                LOG_E("client map failed: %s", strerror(errno));
+                *returnOrigin = TEEC_ORIGIN_COMMS;
+                teecResult = TEEC_ERROR_GENERIC;
+            }
+        }
+
+        if (teecResult != TEEC_SUCCESS) {
+            uint32_t retOrigIgnored;
+            _TEEC_UnwindOperation(session, tci, operation, false, &retOrigIgnored);
+            //Zeroing out tci->operation
+            ::memset(&tci->operation, 0, sizeof(tci->operation));
+            return teecResult;
+        }
+    }
+
+    //Copy version indicator field
+    ::memcpy(tci->header, "TCIGP000", sizeof(tci->header));
+
+    // Fill in invalid values for secure world to overwrite
+    tci->returnStatus = TEEC_ERROR_BAD_STATE;
+
+    // Signal completion of request writing
+    tci->ready = 1;
+
+    return teecResult;
+}
+
+//------------------------------------------------------------------------------
+static TEEC_Result _TEEC_UnwindOperation(
+    TEEC_Session_IMP*    session,
+    _TEEC_TCI*           tci,
+    TEEC_Operation*      operation,
+    bool                 copyValues,
+    uint32_t*            returnOrigin) {
+    uint32_t                    i;
+    _TEEC_ParameterInternal*    imp;
+    TEEC_Parameter*             ext;
+    uint32_t                    n_buf = 0;
+
+    //operation can be NULL
+    if (operation == NULL) {
+        return  TEEC_SUCCESS;
+    }
+
+    LOG_D(" %s()", __func__);
+
+    operation->started = 2;
+    // Buffers to unmap from SWd
+    struct mc_ioctl_map map;
+    map.sid = session->sessionId;
+    // Some sanity checks
+    if (tci->returnOrigin == 0 ||
+            ((tci->returnOrigin != TEEC_ORIGIN_TRUSTED_APP) &&
+             (tci->returnStatus != TEEC_SUCCESS))) {
+        *returnOrigin = TEEC_ORIGIN_COMMS;
+        return TEEC_ERROR_COMMUNICATION;
+    }
+    *returnOrigin = tci->returnOrigin;
+
+    //Clear sVirtualLen to unMap further
+    for (i = 0; i < _TEEC_PARAMETER_NUMBER; i++) {
+        imp = &tci->operation.params[i];
+        ext = &operation->params[i];
+
+        switch (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i)) {
+            case TEEC_VALUE_INPUT:
+                LOG_D("  cycle %d, TEEC_VALUE_INPUT", i);
+                break;
+            case TEEC_NONE:
+                LOG_D("  cycle %d, TEEC_NONE", i);
+                break;
+            case TEEC_VALUE_OUTPUT:
+            case TEEC_VALUE_INOUT: {
+                LOG_D("  cycle %d, TEEC_VALUE_*OUT", i);
+                if (copyValues) {
+                    ext->value.a = imp->value.a;
+                    ext->value.b = imp->value.b;
+                }
+                break;
+            }
+            case TEEC_MEMREF_TEMP_OUTPUT:
+            case TEEC_MEMREF_TEMP_INPUT:
+            case TEEC_MEMREF_TEMP_INOUT: {
+                LOG_D("  cycle %d, TEEC_TEMP*", i);
+                if ((copyValues) &&
+                        (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_TEMP_INPUT)) {
+                    ext->tmpref.size = imp->memref.outputSize;
+                }
+                if (imp->memref.sVirtualLen > 0) {
+                    map.bufs[n_buf].va = (uintptr_t)ext->tmpref.buffer;
+                    map.bufs[n_buf].sva = imp->memref.sVirtualAddr;
+                    map.bufs[n_buf].len = imp->memref.sVirtualLen;
+                    n_buf++;
+                }
+                break;
+            }
+            case TEEC_MEMREF_WHOLE: {
+                LOG_D("  cycle %d, TEEC_MEMREF_WHOLE", i);
+                if ((copyValues) && (ext->memref.parent->flags != TEEC_MEM_INPUT)) {
+                    ext->memref.size = imp->memref.outputSize;
+                }
+                if (imp->memref.sVirtualLen > 0) {
+                    map.bufs[n_buf].va = (uintptr_t)ext->memref.parent->buffer;
+                    map.bufs[n_buf].sva = imp->memref.sVirtualAddr;
+                    map.bufs[n_buf].len = imp->memref.sVirtualLen;
+                    n_buf++;
+                }
+                break;
+            }
+
+            case TEEC_MEMREF_PARTIAL_OUTPUT:
+            case TEEC_MEMREF_PARTIAL_INOUT:
+            case TEEC_MEMREF_PARTIAL_INPUT: {
+                LOG_D("  cycle %d, TEEC_MEMREF_PARTIAL*", i);
+                if ((copyValues) &&
+                        (_TEEC_GET_PARAM_TYPE(operation->paramTypes, i) != TEEC_MEMREF_PARTIAL_INPUT)) {
+                    ext->memref.size = imp->memref.outputSize;
+                }
+                if (imp->memref.sVirtualLen > 0) {
+                    map.bufs[n_buf].va = (uintptr_t)ext->memref.parent->buffer + ext->memref.offset;
+                    map.bufs[n_buf].sva = imp->memref.sVirtualAddr;
+                    map.bufs[n_buf].len = imp->memref.sVirtualLen;
+                    n_buf++;
+                }
+                break;
+            }
+            default:
+                LOG_E("cycle %d, bad parameter", i);
+                break;
+        }
+    }
+
+    if (n_buf > MC_MAP_MAX) {
+        LOG_E("too many buffers: %s", strerror(errno));
+        return TEEC_ERROR_EXCESS_DATA;
+    }
+
+    for (i = n_buf; i < MC_MAP_MAX; i++) {
+        map.bufs[i].va = 0;
+    }
+
+    if (n_buf > 0) {
+        // This function assumes that we cannot handle errors
+        if (client.unmap(map) < 0) {
+            LOG_E("client unmap failed: %s", strerror(errno));
+        }
+    }
+
+    return tci->returnStatus;
+}
+
+//------------------------------------------------------------------------------
+//TEEC_InitializeContext: TEEC_SUCCESS, Another error code from Table 4-2.
+TEEC_Result TEEC_InitializeContext(
+    const char*   name,
+    TEEC_Context* context) {
+    (void) name;
+    LOG_D("== %s() ==============", __func__);
+
+    if (context == NULL) {
+        LOG_E("context is NULL");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    // For test purpose
+    switch (context->imp.reserved) {
+        case CommonClient::DRIVER:
+            client.setOpenMode(CommonClient::DRIVER);
+            break;
+        case CommonClient::PROXY:
+            client.setOpenMode(CommonClient::PROXY);
+            break;
+    }
+
+    if (client.open()) {
+        switch (errno) {
+            case ENOENT:
+                return TEEC_ERROR_COMMUNICATION;
+            case EINVAL:
+                return TEEC_ERROR_BAD_PARAMETERS;
+            default:
+                return TEEC_ERROR_GENERIC;
+        }
+    }
+
+    return TEEC_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+//TEEC_FinalizeContext: void
+
+// The implementation of this function MUST NOT be able to fail: after this function returns the Client
+// Application must be able to consider that the Context has been closed.
+
+void TEEC_FinalizeContext(
+    TEEC_Context* context) {
+    LOG_D("== %s() ==============", __func__);
+
+    // The parameter context MUST point to an initialized TEE Context.
+    if (context == NULL) {
+        LOG_E("context is NULL");
+        return;
+    }
+
+    // The implementation of this function MUST NOT be able to fail: after this function returns the Client
+    // Application must be able to consider that the Context has been closed.
+    if (client.close()) {
+        LOG_E("mcCloseDevice failed: %s", strerror(errno));
+        /* continue even in case of error */;
+    }
+}
+
+static void _TEEC_DeleteTci(TEEC_Session_IMP* session_imp) {
+    if (session_imp->tci) {
+        ::munmap(session_imp->tci, page_size);
+        session_imp->tci = NULL;
+    }
+}
+
+static void _TEEC_CloseSession(TEEC_Session_IMP* session_imp) {
+    if (client.closeSession(session_imp->sessionId)) {
+        LOG_E("%s failed: %s", __func__, strerror(errno));
+    }
+    session_imp->active = false;
+}
+
+//------------------------------------------------------------------------------
+static TEEC_Result _TEEC_CallTA(
+    TEEC_Session_IMP*    session,
+    TEEC_Operation*      operation,
+    uint32_t*            returnOrigin) {
+    TEEC_Result     teecRes;
+    TEEC_Result     teecError = TEEC_SUCCESS;
+    int             ret = 0;
+
+    LOG_D(" %s()", __func__);
+
+    // Phase 1: start the operation and wait for the result
+    _TEEC_TCI* tci = static_cast<_TEEC_TCI*>(session->tci);
+    teecRes = _TEEC_SetupOperation(session, tci, operation, returnOrigin);
+    if (teecRes != TEEC_SUCCESS ) {
+        LOG_E("_TEEC_SetupOperation failed (%08x)", teecRes);
+        return teecRes;
+    }
+
+    // Signal the Trusted App
+    ret = client.notify(session->sessionId);
+    if (ret) {
+        LOG_E("Notify failed: %s", strerror(errno));
+        teecError = TEEC_ERROR_COMMUNICATION;
+    } else {
+        // -------------------------------------------------------------
+        // Wait for the Trusted App response
+        struct mc_ioctl_wait wait;
+        wait.sid = session->sessionId;
+        wait.timeout = -1;
+        ret = client.waitNotification(wait);
+        if (ret) {
+            teecError = TEEC_ERROR_COMMUNICATION;
+            if (errno == ECOMM) {
+                struct mc_ioctl_geterr err;
+                err.sid = session->sessionId;
+
+                ret = client.getError(err);
+                switch (err.value) {
+                    case TA_EXIT_CODE_FINISHED:
+                        // We may get here if the TA_OpenSessionEntryPoint returns an error and TA goes fast through DestroyEntryPoint and exits the TA.
+                        teecError = TEEC_SUCCESS;
+                        break;
+                    case ERR_SESSION_KILLED:
+                        teecError = TEEC_ERROR_TARGET_KILLED;
+                        break;
+                    case ERR_INVALID_SID:
+                    case ERR_SID_NOT_ACTIVE:
+                        LOG_E("mcWaitNotification failed: %s", strerror(errno));
+                        LOG_E("mcGetSessionErrorCode returned %d", err.value);
+                        break;
+                    default:
+                        LOG_E("Target is DEAD");
+                        *returnOrigin = TEEC_ORIGIN_TEE;
+                        teecError = TEEC_ERROR_TARGET_DEAD;
+                        break;
+                }
+            }
+        }
+    }
+    // Phase 2: Return values and cleanup
+    // unmap memory and copy values if no error
+    teecRes = _TEEC_UnwindOperation(session, tci, operation,
+                                    (teecError == TEEC_SUCCESS), returnOrigin);
+    if (teecRes != TEEC_SUCCESS ) {
+        LOG_E("_TEEC_UnwindOperation (%08x)", teecRes);
+        /* continue even in case of error */;
+    }
+
+    // Cleanup
+    if (teecError != TEEC_SUCCESS) {
+        if (teecError == TEEC_ERROR_COMMUNICATION) {
+            *returnOrigin = TEEC_ORIGIN_COMMS;
+        }
+        // Previous interactions failed, either TA is dead or communication error
+        _TEEC_CloseSession(session);
+        _TEEC_DeleteTci(session);
+    }
+    return teecError;
+}
+
+//------------------------------------------------------------------------------
+//TEEC_OpenSession: if the returnOrigin is different from TEEC_ORIGIN_TRUSTED_APP, an error code from Table 4-2
+// If the returnOrigin is equal to TEEC_ORIGIN_TRUSTED_APP, a return code defined by the
+//protocol between the Client Application and the Trusted Application.
+TEEC_Result TEEC_OpenSession (
+    TEEC_Context*        context,
+    TEEC_Session*        session,
+    const TEEC_UUID*     destination,
+    uint32_t             connectionMethod,
+    const void*          connectionData,
+    TEEC_Operation*      operation,
+    uint32_t*            returnOrigin) {
+    TEEC_Result         teecRes;
+    uint32_t            returnOrigin_local = TEEC_ORIGIN_API;
+    struct mc_uuid_t    tauuid;
+    int                 ret = 0;
+
+    LOG_D("== %s() ==============", __func__);
+    // -------------------------------------------------------------
+    //The parameter context MUST point to an initialized TEE Context.
+    if (context == NULL) {
+        LOG_E("context is NULL");
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_API;
+        }
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    if (session == NULL) {
+        LOG_E("session is NULL");
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_API;
+        }
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    if ((connectionMethod != TEEC_LOGIN_PUBLIC) &&
+            (connectionMethod != TEEC_LOGIN_USER) &&
+            (connectionMethod != TEEC_LOGIN_GROUP) &&
+            (connectionMethod != TEEC_LOGIN_APPLICATION) &&
+            (connectionMethod != TEEC_LOGIN_USER_APPLICATION) &&
+            (connectionMethod != TEEC_LOGIN_GROUP_APPLICATION)) {
+        LOG_E("connectionMethod not supported");
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_API;
+        }
+        return TEEC_ERROR_NOT_IMPLEMENTED;
+    }
+
+    if ((TEEC_LOGIN_GROUP == connectionMethod) ||
+            (TEEC_LOGIN_GROUP_APPLICATION == connectionMethod)) {
+        if (NULL == connectionData) {
+            LOG_E("connectionData is NULL");
+            if (returnOrigin) {
+                *returnOrigin = TEEC_ORIGIN_API;
+            }
+            return TEEC_ERROR_BAD_PARAMETERS;
+        }
+    }
+
+    // -------------------------------------------------------------
+    session->imp.active = false;
+
+    _libUuidToArray(destination, tauuid.value);
+
+    if (operation) {
+        operation->imp.session = &session->imp;
+    }
+
+    //Allocate a 4kB page with mmap, zero it out, and set session->imp.tci to its address.
+    session->imp.tci = NULL;
+    void* bulkBuf = (void*)::mmap(0, page_size, PROT_READ | PROT_WRITE,
+                                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (bulkBuf == MAP_FAILED) {
+        LOG_E("mmap failed on tci buffer allocation");
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_API;
+        }
+        return TEEC_ERROR_OUT_OF_MEMORY;
+    }
+
+    session->imp.tci = bulkBuf;
+    ::memset(session->imp.tci, 0, page_size);
+
+    ::pthread_mutex_init(&session->imp.mutex_tci, NULL);
+    ::pthread_mutex_lock(&session->imp.mutex_tci);
+
+    //Fill the TCI buffer session.tci with the destination UUID.
+    _TEEC_TCI* tci = static_cast<_TEEC_TCI*>(session->imp.tci);
+    ::memcpy(&tci->destination, destination, sizeof(tci->destination));
+    // -------------------------------------------------------------
+    struct mc_ioctl_open_session sess;
+    sess.sid = 0;
+    sess.tci = (uintptr_t)tci;
+    sess.tcilen = sizeof(_TEEC_TCI);
+    sess.uuid = tauuid;
+    sess.is_gp_uuid = 1;
+    sess.identity.login_type = static_cast<mc_login_type>(connectionMethod);
+    sess.identity.pid = 0;
+    if (connectionData) {
+        ::memcpy(&sess.identity.login_data, connectionData,
+                 sizeof(sess.identity.login_data));
+    }
+
+    ret = client.openSession(sess);
+    if (ret) {
+        LOG_E("%s failed: %s", __func__, strerror(errno));
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_COMMS;
+        }
+        switch (errno) {
+            case ENOENT:
+                teecRes = TEEC_ERROR_ITEM_NOT_FOUND;
+                break;
+            case EACCES:
+                teecRes = TEEC_ERROR_ACCESS_DENIED;
+                break;
+            case EINVAL:
+                teecRes = TEEC_ERROR_NOT_IMPLEMENTED;
+                break;
+            case ENOSPC:
+                teecRes = TEEC_ERROR_OUT_OF_MEMORY;
+                break;
+            case ECONNREFUSED:
+                teecRes = TEEC_ERROR_SD_BLOCKED;
+                break;
+            case ECONNABORTED:
+                teecRes = TEEC_ERROR_TA_LOCKED;
+                break;
+            case ECONNRESET:
+                teecRes = TEEC_ERROR_TARGET_KILLED;
+                break;
+            case EBUSY:
+                teecRes = TEEC_ERROR_BUSY;
+                break;
+            default:
+                teecRes = TEEC_ERROR_GENERIC;
+        }
+        goto error;
+    }
+
+    session->imp.context = context->imp;
+    session->imp.sessionId = sess.sid;
+    session->imp.active = true;
+    LOG_I(" created session ID %x", session->imp.sessionId);
+
+    // Let TA go through entry points
+    LOG_D(" let TA go through entry points");
+    tci->operation.type = _TA_OPERATION_OPEN_SESSION;
+    teecRes = _TEEC_CallTA(&session->imp, operation, &returnOrigin_local);
+
+    // Check for error on communication level
+    if (teecRes != TEEC_SUCCESS ) {
+        LOG_E("_TEEC_CallTA failed(%08x)", teecRes);
+        // Nothing to do here because _TEEC_CallTA closes broken sessions
+        if (returnOrigin) {
+            *returnOrigin = returnOrigin_local;
+        }
+        goto error;
+    }
+    LOG_D(" no errors in com layer");
+
+    // Check for error from TA
+    if (returnOrigin) {
+        *returnOrigin = tci->returnOrigin;
+    }
+    teecRes = tci->returnStatus;
+    if (teecRes != TEEC_SUCCESS ) {
+        LOG_E("TA OpenSession EP failed(%08x)", teecRes);
+        goto error;
+    }
+
+    LOG_D(" %s() = TEEC_SUCCESS ", __func__);
+    ::pthread_mutex_unlock(&session->imp.mutex_tci);
+
+    if (returnOrigin) {
+        *returnOrigin = TEEC_ORIGIN_TRUSTED_APP;
+    }
+    return TEEC_SUCCESS;
+
+    // -------------------------------------------------------------
+error:
+    if (session->imp.active) {
+        // After notifying us, TA went to Destry EP, so close session now
+        _TEEC_CloseSession(&session->imp);
+    }
+
+    ::pthread_mutex_unlock(&session->imp.mutex_tci);
+    ::pthread_mutex_destroy(&session->imp.mutex_tci);
+    _TEEC_DeleteTci(&session->imp);
+
+    LOG_D(" %s() = 0x%x", __func__, teecRes);
+    return teecRes;
+}
+
+//------------------------------------------------------------------------------
+TEEC_Result TEEC_InvokeCommand(
+    TEEC_Session*     session,
+    uint32_t          commandID,
+    TEEC_Operation*   operation,
+    uint32_t*         returnOrigin) {
+    TEEC_Result teecRes;
+    uint32_t returnOrigin_local = TEEC_ORIGIN_API;
+
+    LOG_D("== %s() ==============", __func__);
+
+    // -------------------------------------------------------------
+    if (session == NULL) {
+        LOG_E("session is NULL");
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_API;
+        }
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    if (!session->imp.active) {
+        LOG_E("session is inactive");
+        if (returnOrigin) {
+            *returnOrigin = TEEC_ORIGIN_API;
+        }
+        return TEEC_ERROR_BAD_STATE;
+    }
+    // -------------------------------------------------------------
+    if (operation) {
+        operation->imp.session = &session->imp;
+    }
+
+    ::pthread_mutex_lock(&session->imp.mutex_tci);
+
+    // Call TA
+    _TEEC_TCI* tci = static_cast<_TEEC_TCI*>(session->imp.tci);
+    tci->operation.commandId = commandID;
+    tci->operation.type = _TA_OPERATION_INVOKE_COMMAND;
+    teecRes = _TEEC_CallTA(&session->imp, operation, &returnOrigin_local);
+    if (teecRes != TEEC_SUCCESS ) {
+        LOG_E("_TEEC_CallTA failed(%08x)", teecRes);
+        if (returnOrigin) {
+            *returnOrigin = returnOrigin_local;
+        }
+    } else {
+        if (returnOrigin) {
+            *returnOrigin = tci->returnOrigin;
+        }
+        teecRes = tci->returnStatus;
+    }
+
+    ::pthread_mutex_unlock(&session->imp.mutex_tci);
+    LOG_D(" %s() = 0x%x", __func__, teecRes);
+    return teecRes;
+}
+
+//------------------------------------------------------------------------------
+void TEEC_CloseSession(TEEC_Session* session) {
+    TEEC_Result     teecRes = TEEC_SUCCESS;
+    uint32_t        returnOrigin;
+
+    LOG_D("== %s() ==============", __func__);
+
+    // -------------------------------------------------------------
+    //The Implementation MUST do nothing if the session parameter is NULL.
+    if (session == NULL) {
+        LOG_E("session is NULL");
+        return;
+    }
+
+    // -------------------------------------------------------------
+    if (session->imp.active) {
+        // Let TA go through CloseSession and Destroy entry points
+        LOG_D(" let TA go through close entry points");
+        ::pthread_mutex_lock(&session->imp.mutex_tci);
+        _TEEC_TCI* tci = static_cast<_TEEC_TCI*>(session->imp.tci);
+        tci->operation.type = _TA_OPERATION_CLOSE_SESSION;
+        teecRes = _TEEC_CallTA(&session->imp, NULL, &returnOrigin);
+        if (teecRes != TEEC_SUCCESS ) {
+            /* continue even in case of error */;
+            LOG_E("_TEEC_CallTA failed(%08x)", teecRes);
+        }
+
+        if (session->imp.active) {
+            _TEEC_CloseSession(&session->imp);
+        }
+        ::pthread_mutex_unlock(&session->imp.mutex_tci);
+    }
+
+    ::pthread_mutex_destroy(&session->imp.mutex_tci);
+    _TEEC_DeleteTci(&session->imp);
+
+    LOG_D(" %s() = 0x%x", __func__, teecRes);
+}
+
+//------------------------------------------------------------------------------
+TEEC_Result TEEC_RegisterSharedMemory(
+    TEEC_Context*      context,
+    TEEC_SharedMemory* sharedMem) {
+    LOG_D("== %s() ==============", __func__);
+
+    //The parameter context MUST point to an initialized TEE Context.
+    if (context == NULL) {
+        LOG_E("context is NULL");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    //The parameter sharedMem MUST point to the Shared Memory structure defining
+    //the memory region to register.
+    if (sharedMem == NULL) {
+        LOG_E("sharedMem is NULL");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    //The buffer field MUST point to the memory region to be shared, and MUST not be NULL.
+    if (sharedMem->buffer == NULL) {
+        LOG_E("sharedMem->buffer is NULL");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    if ((static_cast<int>(sharedMem->flags) & ~TEEC_MEM_INOUT)) {
+        LOG_E("sharedMem->flags is incorrect");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    if (sharedMem->flags == 0) {
+        LOG_E("sharedMem->flags is incorrect");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    sharedMem->imp.implementation_allocated = false;
+    return TEEC_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+TEEC_Result TEEC_AllocateSharedMemory(
+    TEEC_Context*      context,
+    TEEC_SharedMemory* sharedMem) {
+    //No connection to "context"?
+    LOG_D("== %s() ==============", __func__);
+
+    //The parameter context MUST point to an initialized TEE Context.
+    if (context == NULL) {
+        LOG_E("context is NULL");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    //The parameter sharedMem MUST point to the Shared Memory structure defining
+    //the memory region to register.
+    if (sharedMem == NULL) {
+        LOG_E("sharedMem is NULL");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    if (static_cast<int>(sharedMem->flags) & ~TEEC_MEM_INOUT) {
+        LOG_E("sharedMem->flags is incorrect");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+    if (sharedMem->flags == 0) {
+        LOG_E("sharedMem->flags is incorrect");
+        return TEEC_ERROR_BAD_PARAMETERS;
+    }
+
+    sharedMem->buffer = malloc(sharedMem->size);
+    if (sharedMem->buffer == NULL) {
+        LOG_E("malloc failed");
+        return TEEC_ERROR_OUT_OF_MEMORY;
+    }
+    sharedMem->imp.implementation_allocated = true;
+
+    return TEEC_SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+void TEEC_ReleaseSharedMemory (
+    TEEC_SharedMemory* sharedMem) {
+    //No connection to "context"?
+    LOG_D("== %s() ==============", __func__);
+
+    //The Implementation MUST do nothing if the sharedMem parameter is NULL
+    if (sharedMem == NULL) {
+        LOG_E("sharedMem is NULL");
+        return;
+    }
+
+    //For a memory buffer allocated using TEEC_AllocateSharedMemory the Implementation
+    //MUST free the underlying memory
+    if (sharedMem->imp.implementation_allocated) {
+        if (sharedMem->buffer) {
+            free(sharedMem->buffer);
+            sharedMem->buffer = NULL;
+            sharedMem->size = 0;
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+void TEEC_RequestCancellation(
+    TEEC_Operation* operation) {
+    LOG_D("== %s() ==============", __func__);
+
+    while (operation->started == 0);
+
+    LOG_D("while(operation->started ==0) passed");
+
+    if (operation->started > 1) {
+        LOG_D("The operation has finished");
+        return;
+    }
+
+    TEEC_Session_IMP* session = operation->imp.session;
+    operation->started = 2;
+
+    if (!session->active)  {
+        LOG_D("Corresponding session is not active");
+        return;
+    }
+
+    if (client.gpRequestCancellation(session->sessionId)) {
+        LOG_ERRNO("gpRequestCancellation");
+    }
+}
+
+//------------------------------------------------------------------------------
diff --git a/mobicore/Daemon/Android.mk b/mobicore/Daemon/Android.mk
new file mode 100644 (file)
index 0000000..7fedf8d
--- /dev/null
@@ -0,0 +1,145 @@
+# =============================================================================
+#
+# MobiCore Android build components
+#
+# =============================================================================
+
+LOCAL_PATH := $(call my-dir)
+
+# Registry Shared Library
+# =============================================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libMcRegistry
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_CFLAGS += -DLOG_TAG=\"McRegistry\"
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -DLOG_ANDROID
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_SHARED_LIBRARIES := libMcClient
+ifeq ($(APP_PROJECT_PATH),)
+LOCAL_SHARED_LIBRARIES += liblog
+else
+# Local build
+LOCAL_LDLIBS := -llog
+endif
+
+LOCAL_SRC_FILES := \
+       src/Connection.cpp \
+       src/Registry.cpp
+
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDES)
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Daemon Application
+# =============================================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := mcDriverDaemon
+LOCAL_MODULE_TAGS := eng
+LOCAL_CFLAGS += -DLOG_TAG=\"McDaemon\"
+LOCAL_CFLAGS += -DTBASE_API_LEVEL=5
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -DLOG_ANDROID
+ifdef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_CFLAGS += -DWITHOUT_PROXY
+endif # TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libMcClient_static
+ifeq ($(APP_PROJECT_PATH),)
+LOCAL_SHARED_LIBRARIES += \
+       liblog
+
+ifdef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+include external/stlport/libstlport.mk
+
+LOCAL_C_INCLUDES += \
+       external/stlport/stlport
+
+LOCAL_SHARED_LIBRARIES += \
+       libstlport
+else # TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_STATIC_LIBRARIES += \
+       libMcProxy
+
+LOCAL_SHARED_LIBRARIES += \
+       libprotobuf-cpp-lite \
+       libcutils
+
+endif # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+else # !NDK
+# Local build
+LOCAL_LDLIBS := -llog
+ifndef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+LOCAL_CFLAGS += -static-libstdc++
+
+LOCAL_STATIC_LIBRARIES += \
+       libMcProxy \
+       libprotobuf-cpp-lite
+endif # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+endif # NDK
+
+LOCAL_SRC_FILES := \
+       src/Connection.cpp \
+       src/CThread.cpp \
+       src/MobiCoreDriverDaemon.cpp \
+       src/SecureWorld.cpp \
+       src/FSD2.cpp \
+       src/Server.cpp \
+       src/PrivateRegistry.cpp
+
+include $(BUILD_EXECUTABLE)
+
+ifndef TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+# Static version of the daemon for recovery
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := mcDriverDaemon_static
+LOCAL_MODULE_TAGS := eng
+LOCAL_CFLAGS += -DLOG_TAG=\"McDaemon\"
+LOCAL_CFLAGS += -DTBASE_API_LEVEL=5
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -DLOG_ANDROID
+LOCAL_CFLAGS += -DWITHOUT_FSD
+LOCAL_CFLAGS += -DWITHOUT_PROXY
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_STATIC_LIBRARIES := libMcClient_static
+ifeq ($(APP_PROJECT_PATH),)
+LOCAL_STATIC_LIBRARIES += \
+       liblog libc libc++_static libcutils
+
+else # !NDK
+# Local build
+LOCAL_LDLIBS := -llog
+endif # NDK
+
+LOCAL_SRC_FILES := \
+       src/Connection.cpp \
+       src/CThread.cpp \
+       src/MobiCoreDriverDaemon.cpp \
+       src/SecureWorld.cpp \
+       src/Server.cpp \
+       src/PrivateRegistry.cpp
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+include $(BUILD_EXECUTABLE)
+
+endif # !TRUSTONIC_ANDROID_LEGACY_SUPPORT
+
+# adding the root folder to the search path appears to make absolute paths
+# work for import-module - lets see how long this works and what surprises
+# future developers get from this.
+$(call import-add-path,/)
+$(call import-module,$(COMP_PATH_MobiCoreClientLib_module))
+$(call import-module,$(COMP_PATH_AndroidProtoBuf))
diff --git a/mobicore/Daemon/MODULE_LICENSE_BSD b/mobicore/Daemon/MODULE_LICENSE_BSD
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mobicore/Daemon/NOTICE b/mobicore/Daemon/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/Daemon/include/MobiCoreRegistry.h b/mobicore/Daemon/include/MobiCoreRegistry.h
new file mode 100644 (file)
index 0000000..dfbb1c3
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICORE_REGISTRY_H_
+#define MOBICORE_REGISTRY_H_
+
+#include "MobiCoreDriverApi.h"
+#include "mcContainer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /** Stores an authentication token in registry.
+     * @param  so Authentication token secure object.
+     * @param  size Authentication token object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreAuthToken(void *so, uint32_t size);
+
+    /** Reads an authentication token from registry.
+     * @param[out] so Authentication token secure object.
+     * @param[out] size Authentication token secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadAuthToken(void *so, uint32_t *size);
+
+    /** 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.
+     * @param size Root container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreRoot(void *so, uint32_t size);
+
+    /** Reads a root container secure object from the registry.
+     * @param[out] so Root container secure object.
+     * @param[out] size Root container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadRoot(void *so, uint32_t *size);
+
+    /** 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, void *so, uint32_t size);
+
+    /** Reads a service provider container secure object from the registry.
+     * @param spid Service provider ID.
+     * @param[out] so Service provider container secure object.
+     * @param[out] size Service provider container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadSp(mcSpid_t spid, void *so, uint32_t *size);
+
+    /** 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 spid SPID of the trustlet container.
+     * @param so Trustlet container secure object.
+     * @param size Trustlet container secure object size.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t size);
+
+    /** Reads a trustlet container secure object from the registry.
+     * @param uuid Trustlet UUID.
+     * @param spid SPID of the trustlet container
+     * @param[out] so Trustlet container secure object.
+     * @param[out] size Trustlet container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t *size);
+
+    /** Deletes a trustlet container secure object and all of its associated data.
+     * @param uuid Trustlet UUID.
+     * @param spid Service provider ID
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid, const mcSpid_t spid);
+
+    /**
+     * mcRegistryCleanupTA()
+     *
+     * Removes all associated data of a TA (when uninstalled)
+     *
+     * @param [in] uuid the UUID to clean up all files belonging too
+     * @retrurn MC_DRV_OK is successful, othwise an error code from mcResult_t
+     */
+    mcResult_t mcRegistryCleanupTA(const mcUuid_t *uuid);
+
+    /** 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);
+
+    /** Stores a Trustlet Application blob in the registry.
+     * @param spid SPID of the trustlet container.
+     * @param blob Trustlet Application blob.
+     * @param size Trustlet Application blob size.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreTABlob(mcSpid_t spid, void *blob, uint32_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MOBICORE_REGISTRY_H_
+
diff --git a/mobicore/Daemon/src/CThread.cpp b/mobicore/Daemon/src/CThread.cpp
new file mode 100644 (file)
index 0000000..9fe47de
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * Thread implementation (pthread abstraction).
+ */
+
+#include <signal.h>
+
+#include <log.h>
+
+#include "CThread.h"
+
+//------------------------------------------------------------------------------
+static void* thread_startup(void *arg) {
+    reinterpret_cast<CThread*>(arg)->run();
+    return NULL;
+}
+
+//------------------------------------------------------------------------------
+void CThread::terminate() {
+    m_terminate = true;
+}
+
+//------------------------------------------------------------------------------
+bool CThread::shouldTerminate() {
+    return m_terminate;
+}
+
+//------------------------------------------------------------------------------
+void CThread::start(const char* name) {
+    int ret;
+    ret = pthread_create(&m_thread, NULL, thread_startup, this);
+    if (0 != ret)
+        LOG_E("pthread_create failed with error code %d", ret);
+
+    ret = pthread_setname_np(m_thread, name);
+    if (0 != ret)
+        LOG_E("pthread_setname_np failed with error code %d %s", ret, name);
+}
+
+//------------------------------------------------------------------------------
+void CThread::join() {
+    int ret;
+    ret = pthread_join(m_thread, NULL);
+    if (0 != ret)
+        LOG_E("pthread_join failed with error code %d", ret);
+}
+
+//------------------------------------------------------------------------------
+int CThread::kill(int sig) {
+    return pthread_kill(m_thread, sig);
+}
diff --git a/mobicore/Daemon/src/CThread.h b/mobicore/Daemon/src/CThread.h
new file mode 100644 (file)
index 0000000..07028ed
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CTHREAD_H_
+#define CTHREAD_H_
+
+#include <pthread.h>
+
+class CThread {
+public:
+    // m_thread value does not matter, only initialised for code checkers
+    CThread(): m_terminate(false), m_thread(pthread_self()) {}
+    virtual ~CThread() {}
+    virtual void run() = 0;
+    void start(const char* name);
+    void join();
+    void terminate();
+    int kill(int sig);
+protected:
+    bool shouldTerminate();
+private:
+    bool m_terminate;
+    pthread_t m_thread;
+};
+
+#endif /*CTHREAD_H_*/
+
diff --git a/mobicore/Daemon/src/Connection.cpp b/mobicore/Daemon/src/Connection.cpp
new file mode 100644 (file)
index 0000000..8977617
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * Connection data.
+ */
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <cstring>
+#include <errno.h>
+#include <poll.h>
+#include <log.h>
+#include <sys/un.h>
+
+#include "Connection.h"
+
+//------------------------------------------------------------------------------
+Connection::Connection(void):
+    m_socket(-1)
+{
+}
+
+//------------------------------------------------------------------------------
+Connection::Connection(int socketDescriptor):
+        m_socket(socketDescriptor)
+{
+    assert(-1 != socketDescriptor);
+}
+
+//------------------------------------------------------------------------------
+Connection::~Connection(void)
+{
+    LOG_D("closing Connection... fd=%i", m_socket);
+    if (m_socket != -1) {
+        int ret = ::close(m_socket);
+        if(ret)
+            LOG_ERRNO("close");
+    }
+    LOG_D(" Socket connection closed.");
+}
+
+//------------------------------------------------------------------------------
+bool Connection::connect(const char *dest)
+{
+    if (m_socket >= 0) {
+        LOG_E("Already connected");
+        return false;
+    }
+
+    struct sockaddr_un sockaddr; /**< Remote address */
+    memset(&sockaddr, 0, sizeof(sockaddr));
+    sockaddr.sun_family = AF_UNIX;
+    if (sizeof(sockaddr.sun_path) - 1 < strlen(dest)) {
+        LOG_E("Invalid destination socket %s", dest);
+        return false;
+    }
+
+    LOG_D("Connecting to %s socket", dest);
+    sockaddr.sun_family = AF_UNIX;
+    memset(sockaddr.sun_path, 0, sizeof(sockaddr.sun_path));
+    strncpy(sockaddr.sun_path, dest, strlen(dest));
+
+    m_socket = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (m_socket < 0) {
+        LOG_ERRNO("Can't open stream socket.");
+        return false;
+    }
+
+    socklen_t len = static_cast<socklen_t>(strlen(sockaddr.sun_path) + sizeof(sockaddr.sun_family));
+    // The Daemon socket is in the Abstract Domain(LINUX ONLY!)
+    sockaddr.sun_path[0] = 0;
+    if (::connect(m_socket, reinterpret_cast<struct sockaddr*>(&sockaddr), len) < 0) {
+        LOG_ERRNO("connect()");
+        return false;
+    }
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+ssize_t Connection::readData(void *buffer, uint32_t len, int32_t timeout)
+{
+    ssize_t ret = 0;
+    struct timeval tv;
+    struct timeval *ptv = NULL;
+    fd_set readfds;
+
+    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(m_socket, &readfds);
+    ret = select(m_socket + 1, &readfds, NULL, NULL, ptv);
+
+    // check for read error
+    if (ret == -1) {
+        LOG_ERRNO("select");
+        return -1;
+    }
+
+    // Handle case of no descriptor ready
+    if (ret == 0) {
+        LOG_W("Timeout during select() / No more notifications.");
+        return -2;
+    }
+
+    // one or more descriptors are ready
+
+    // finally check if fd has been selected -> must socketDescriptor
+    if (!FD_ISSET(m_socket, &readfds)) {
+        LOG_ERRNO("no fd is set, select");
+        return ret;
+    }
+
+    ret = recv(m_socket, buffer, len, MSG_DONTWAIT);
+    if (ret == 0)
+        LOG_D(" readData(): peer orderly closed connection.");
+
+    return ret;
+}
+
+ssize_t Connection::readMsg(const iovec *iov, uint32_t nr_seg, int32_t timeout)
+{
+    ssize_t ret = -1;
+    struct msghdr msg;
+    struct timeval tv;
+    struct timeval *ptv = NULL;
+    fd_set readfds;
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = const_cast<iovec *>(iov);
+    msg.msg_iovlen = nr_seg;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+
+    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(m_socket, &readfds);
+    ret = select(m_socket + 1, &readfds, NULL, NULL, ptv);
+
+    // check for read error
+    if (ret == -1) {
+        LOG_ERRNO("select");
+        return -1;
+    }
+
+    // Handle case of no descriptor ready
+    if (ret == 0) {
+        LOG_W("Timeout during select() / No more notifications.");
+        return -2;
+    }
+
+    // one or more descriptors are ready
+
+    // finally check if fd has been selected -> must socketDescriptor
+    if (!FD_ISSET(m_socket, &readfds)) {
+        LOG_ERRNO("no fd is set, select");
+        return ret;
+    }
+
+    ret = recvmsg(m_socket, &msg, MSG_DONTWAIT);
+    if (ret == 0)
+        LOG_D("readData(): peer orderly closed connection.");
+
+    return ret;
+}
+
+
+//------------------------------------------------------------------------------
+ssize_t Connection::writeData(const void *buffer, uint32_t len)
+{
+    const char *cbuf = static_cast<const char*>(buffer);
+    uint32_t left = len;
+    while (left) {
+        ssize_t wlen = ::send(m_socket, cbuf, left, 0);
+        if (wlen < 0) {
+            LOG_ERRNO("writeData");
+            return -1;
+        }
+        if (wlen == 0) {
+            LOG_E("Client closed the connection");
+            return -1;
+        }
+        left -= wlen;
+        cbuf += wlen;
+    }
+    return len;
+}
+
+ssize_t Connection::writeMsg(const iovec *iov, uint32_t nr_seg)
+{
+    ssize_t ret = -1, len;
+    struct msghdr msg;
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = const_cast<iovec *>(iov);
+    msg.msg_iovlen = nr_seg;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+
+    for( len = 0; nr_seg > 0; nr_seg--, iov++)
+        len += iov->iov_len;
+
+    ret = sendmsg(m_socket, &msg, 0);
+    if (ret != len) {
+        LOG_E("%s: could not send all data, ret=%zd, errno: %d (%s)",
+               __FUNCTION__, ret, errno, strerror(errno));
+        ret = -1;
+    }
+
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+int Connection::waitData(int32_t timeout)
+{
+    int ret;
+    struct timeval tv;
+    struct timeval *ptv = NULL;
+    fd_set readfds;
+
+    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(m_socket, &readfds);
+    ret = select(m_socket + 1, &readfds, NULL, NULL, ptv);
+
+    // check for read error
+    if (ret == -1) {
+        LOG_ERRNO("select");
+        return ret;
+    } else if (ret == 0) {
+        LOG_E("select() timed out");
+        return -1;
+    }
+
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+bool Connection::isConnectionAlive(void)
+{
+    int retval;
+    struct pollfd ufds[1];
+    ufds[0].fd = m_socket;
+    ufds[0].events = POLLRDHUP;
+
+    retval = poll(ufds, 1, 10);
+    if (retval < 0 || retval > 0) {
+        LOG_ERRNO("poll");
+        return false;
+    }
+    return true;
+}
diff --git a/mobicore/Daemon/src/Connection.h b/mobicore/Daemon/src/Connection.h
new file mode 100644 (file)
index 0000000..3503052
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CONNECTION_H_
+#define CONNECTION_H_
+
+#include <sys/socket.h>         // iovec
+
+class Connection
+{
+public:
+    Connection(void);
+    Connection(int socketDescriptor);
+
+    ~Connection(void);
+
+    /**
+     * Connect to destination.
+     *
+     * @param Destination pointer.
+     * @return true on success.
+     */
+    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
+     */
+    ssize_t readData(void *buffer, uint32_t len, int32_t timeout = -1);
+    ssize_t readMsg(const iovec *iov, uint32_t nr_seg, int32_t timeout = -1);
+    /**
+     * Write bytes to the connection.
+     *
+     * @param buffer    Pointer to source buffer.
+     * @param len       Number of bytes to read.
+     * @return Number of bytes written.
+     * @return -1 if written bytes not equal to len.
+     */
+    ssize_t writeData(const void *buffer, uint32_t len);
+    ssize_t writeMsg(const iovec *iov, uint32_t nr_seg);
+
+    /**
+     * Wait for data to be available.
+     *
+     * @param timeout   Timeout in milliseconds
+     * @return 0 if data is available
+     * @return error code if otherwise
+     */
+    int waitData(int32_t timeout);
+
+    /*
+     * Checks if the socket is  still connected to the daemon
+     *
+     * @return true if connection is still alive.
+     */
+    bool isConnectionAlive(void);
+
+    int socket() const
+    {
+        return m_socket;
+    }
+
+private:
+    int m_socket; /**< Local socket descriptor */
+};
+
+#endif /* CONNECTION_H_ */
+
diff --git a/mobicore/Daemon/src/ConnectionHandler.h b/mobicore/Daemon/src/ConnectionHandler.h
new file mode 100644 (file)
index 0000000..8d44c63
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef 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/src/FSD2.cpp b/mobicore/Daemon/src/FSD2.cpp
new file mode 100644 (file)
index 0000000..523851e
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Filesystem v2 delegate.
+ *
+ * Handles incoming storage requests from TA through STH
+ */
+
+#include <unistd.h>
+#include <string>
+#include <cstring>
+#include <errno.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <memory>
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+#include <sys/stat.h>
+
+#undef LOG_TAG
+#define LOG_TAG "TeeFilesystem"
+#include <log.h>
+#include "tee_client_api.h"     /* TEEC_Result */
+#include "MobiCoreDriverApi.h"  /* MC session */
+#include "sth2ProxyApi.h"
+#include "sfs_error.h"
+#include "FSD2.h"
+
+#define MAX_SECTOR_SIZE                 4096
+#define SECTOR_NUM                      8
+#define SFS_L2_CACHE_SLOT_SPACE         12  // Hard coded size, cf. sfs_internal.h
+#define DEFAULT_WORKSPACE_SIZE          (SECTOR_NUM * (MAX_SECTOR_SIZE + SFS_L2_CACHE_SLOT_SPACE))
+
+extern const std::string& getTbStoragePath();
+
+/*----------------------------------------------------------------------------
+ * Utilities functions
+ *----------------------------------------------------------------------------*/
+static TEEC_Result errno2serror() {
+    switch (errno) {
+        case EINVAL:
+            return S_ERROR_BAD_PARAMETERS;
+        case EMFILE:
+            return S_ERROR_NO_MORE_HANDLES;
+        case ENOENT:
+            return S_ERROR_ITEM_NOT_FOUND;
+        case EEXIST:
+            return S_ERROR_ITEM_EXISTS;
+        case ENOSPC:
+            return S_ERROR_STORAGE_NO_SPACE;
+        case ENOMEM:
+            return S_ERROR_OUT_OF_MEMORY;
+        case EBADF:
+        case EACCES:
+        default:
+            return S_ERROR_STORAGE_UNREACHABLE;
+    }
+}
+
+class Partition {
+    std::string name_;
+    FILE* fd_;
+    off_t size_;
+public:
+    Partition(std::string name): name_(name), fd_(NULL), size_(0) {}
+    const char* name() const {
+        return name_.c_str();
+    }
+    off_t size() {
+        if (size_ == 0) {
+            struct stat st;
+            if (::stat(name(), &st)) {
+                return -1;
+            }
+            size_ = st.st_size;
+        }
+        return size_;
+    }
+    TEEC_Result create() {
+        LOG_I("%s: Create storage file \"%s\"", __func__, name());
+        fd_ = ::fopen(name(), "w+b");
+        if (!fd_) {
+            LOG_E("%s: %s creating storage file \"%s\"", __func__,
+                  strerror(errno), name());
+            return errno2serror();
+        }
+        return S_SUCCESS;
+    }
+    TEEC_Result destroy() {
+        if (!fd_) {
+            /* The partition is not open */
+            return S_ERROR_BAD_STATE;
+        }
+
+        /* Try to erase the file */
+        if (::unlink(name())) {
+            /* File in use or OS didn't allow the operation */
+            return errno2serror();
+        }
+
+        return S_SUCCESS;
+    }
+    TEEC_Result open() {
+        /* Open the file */
+        LOG_I("%s: Open storage file \"%s\"", __func__, name());
+        fd_ = ::fopen(name(), "r+b");
+        if (!fd_) {
+            LOG_E("%s: %s opening storage file \"%s\"", __func__,
+                  strerror(errno), name());
+            return errno2serror();
+        }
+        LOG_I("%s: storage file \"%s\" successfully open (size: %ld KB / %ld B))",
+              __func__, name(), size() / 1024, size());
+        return S_SUCCESS;
+    }
+    TEEC_Result close() {
+        if (!fd_) {
+            /* The partition is not open */
+            return S_ERROR_BAD_STATE;
+        }
+
+        ::fclose(fd_);
+        fd_ = NULL;
+
+        return S_SUCCESS;
+    }
+    TEEC_Result read(uint8_t* buf, uint32_t length, uint32_t offset) {
+        if (!fd_) {
+            /* The partition is not open */
+            return S_ERROR_BAD_STATE;
+        }
+
+        if (::fseek(fd_, offset, SEEK_SET)) {
+            LOG_E("%s: fseek error: %s", __func__, strerror(errno));
+            return errno2serror();
+        }
+
+        if (::fread(buf, length, 1, fd_) != 1) {
+            if (feof(fd_)) {
+                LOG_E("%s: fread error: End-Of-File detected", __func__);
+                return S_ERROR_ITEM_NOT_FOUND;
+            }
+            LOG_E("%s: fread error: %s", __func__, strerror(errno));
+            return errno2serror();
+        }
+
+        return S_SUCCESS;
+    }
+    TEEC_Result write(const uint8_t* buf, uint32_t length, uint32_t offset) {
+        if (!fd_) {
+            /* The partition is not open */
+            return S_ERROR_BAD_STATE;
+        }
+
+        if (::fseek(fd_, offset, SEEK_SET)) {
+            LOG_E("%s: fseek error: %s", __func__, strerror(errno));
+            return errno2serror();
+        }
+
+        if (::fwrite(buf, length, 1, fd_) != 1) {
+            LOG_E("%s: fwrite error: %s", __func__, strerror(errno));
+            return errno2serror();
+        }
+        return S_SUCCESS;
+    }
+    TEEC_Result sync() {
+        if (!fd_) {
+            /* The partition is not open */
+            return S_ERROR_BAD_STATE;
+        }
+
+        /*
+         * First make sure that the data in the stdio buffers is flushed to the
+         * file descriptor
+         */
+        if (::fflush(fd_)) {
+            return errno2serror();
+        }
+
+        /* Then synchronize the file descriptor with the file-system */
+        if (::fdatasync(fileno(fd_))) {
+            return errno2serror();
+        }
+
+        return S_SUCCESS;
+    }
+    TEEC_Result resize(off_t new_size) {
+        if (!fd_) {
+            /* The partition is not open */
+            return S_ERROR_BAD_STATE;
+        }
+
+        if (new_size == size()) {
+            return S_SUCCESS;
+        }
+
+        if (new_size > size()) {
+            /*
+             * Enlarge the partition file. Make sure we actually write some
+             * non-zero data into the new sectors. Otherwise, some file-system
+             * might not really reserve the storage space but use a sparse
+             * representation. In this case, a subsequent write instruction
+             * could fail due to out-of-space, which we want to avoid.
+             */
+            if (::fseek(fd_, 0, SEEK_END)) {
+                LOG_E("%s: fseek error: %s", __func__, strerror(errno));
+                return errno2serror();
+            }
+
+            off_t count = new_size - size();
+            while (count) {
+                if (::fputc(0xA5, fd_) != 0xA5) {
+                    LOG_E("%s: fputc error: %s", __func__, strerror(errno));
+                    return errno2serror();
+                }
+                count--;
+            }
+        } else {
+            /* Truncate the partition file */
+            if (::ftruncate(fileno(fd_), new_size)) {
+                return errno2serror();
+            }
+        }
+        // Update size
+        size_ = new_size;
+        return S_SUCCESS;
+    }
+};
+
+struct FileSystem::Impl {
+    pthread_t thread;
+
+    /*
+     * Communication buffer, includes the workspace
+     */
+    struct {
+        STH2_delegation_exchange_buffer_t exchange_buffer;
+        uint8_t workspace[DEFAULT_WORKSPACE_SIZE];
+    } dci;
+
+    /*
+     * Provided by the SWd
+     */
+    uint32_t sector_size;
+
+    /*
+     * The 16 possible partitions
+     */
+    Partition* partitions[16];
+
+    // thread value does not matter, only initialised for code checkers
+    Impl(): thread(pthread_self()) {
+        ::memset(&dci, 0, sizeof(dci));
+        sector_size = 0;
+        for (int i = 0; i < 16; i++) {
+            partitions[i] = NULL;
+        }
+    }
+    void run();
+    int executeCommand();
+    const char* getCommandtypeString(uint32_t nInstructionID);
+};
+
+FileSystem::FileSystem(): pimpl_(new Impl) {}
+
+FileSystem::~FileSystem() {
+    delete pimpl_;
+}
+
+void* FileSystem::run(void* arg) {
+    FileSystem::Impl* pimpl = static_cast<FileSystem::Impl*>(arg);
+    pimpl->run();
+    return NULL;
+}
+
+int FileSystem::open() {
+    const std::string storage_dir_name = getTbStoragePath();
+
+    // Create Tbase storage directory if necessary, parent is assumed to exist
+    if (::mkdir(storage_dir_name.c_str(), 0700) && (errno != EEXIST)) {
+        LOG_ERRNO("creating storage folder");
+        // Do not return any error and block deamon boot flow or stop FSD thread.
+        // Just print a "warning/not critical error message".
+        // Directory could also be created by platform at initialization time.
+        // return -1;
+    }
+
+    // Create partitions with default names
+    for (int i = 0; i < 16; i++) {
+        char file_name[16];
+        snprintf(file_name, sizeof(file_name), "/Store_%1X.tf", i);
+        pimpl_->partitions[i] = new Partition(storage_dir_name + file_name);
+    }
+
+    /* Prepare DCI message buffer */
+    pimpl_->dci.exchange_buffer.nWorkspaceLength = DEFAULT_WORKSPACE_SIZE;
+
+    // Create listening thread
+    int ret = pthread_create(&pimpl_->thread, NULL, run, pimpl_);
+    if (ret) {
+        LOG_E("pthread_create failed with error code %d", ret);
+        return -1;
+    }
+
+    pthread_setname_np(pimpl_->thread, "McDaemon.FileSystem");
+    return 0;
+}
+
+int FileSystem::close() {
+    // Stop listening thread
+    pthread_kill(pimpl_->thread, SIGUSR1);
+    pthread_join(pimpl_->thread, NULL);
+
+    /* Clear DCI message buffer */
+    ::memset(&pimpl_->dci, 0, sizeof(pimpl_->dci));
+    return 0;
+}
+
+/*
+ * main
+ */
+void FileSystem::Impl::run() {
+    // Only accept USR1, to give up
+    sigset_t sigmask;
+    sigemptyset(&sigmask);
+    sigaddset(&sigmask, SIGUSR1);
+    pthread_sigmask(SIG_UNBLOCK, &sigmask, (sigset_t*)0);
+
+    mcResult_t mc_ret = mcOpenDevice(MC_DEVICE_ID_DEFAULT);
+    if (MC_DRV_OK != mc_ret) {
+        LOG_E("%s: mcOpenDevice returned: 0x%08X\n", __func__, mc_ret);
+        return;
+    }
+
+    const mcUuid_t uuid = SERVICE_DELEGATION_UUID;
+    mcSessionHandle_t session_handle;
+    session_handle.deviceId = MC_DEVICE_ID_DEFAULT;
+    mc_ret = mcOpenSession(&session_handle, &uuid, reinterpret_cast<uint8_t*>(&dci),
+                           sizeof(dci));
+    if (MC_DRV_OK != mc_ret) {
+        LOG_E("%s: mcOpenSession returned: 0x%08X\n", __func__, mc_ret);
+        mcCloseDevice(MC_DEVICE_ID_DEFAULT);
+        return;
+    }
+
+    LOG_I("%s: Start listening for request from STH2", __func__);
+    while (true) {
+        /* Wait for notification from SWd */
+        LOG_D("%s: Waiting for notification\n", __func__);
+        mc_ret = mcWaitNotification(&session_handle, MC_INFINITE_TIMEOUT_INTERRUPTIBLE);
+        if (mc_ret != MC_DRV_OK) {
+            LOG_E("%s: mcWaitNotification failed, error=0x%08X\n", __func__, mc_ret);
+            break;
+        }
+
+        /* Read sector size */
+        if (sector_size == 0) {
+            sector_size = dci.exchange_buffer.nSectorSize;
+            LOG_D("%s: Sector Size: %d bytes", __func__, sector_size);
+
+            /* Check sector size */
+            if (!(sector_size == 512 || sector_size == 1024 ||
+                    sector_size == 2048 || sector_size == 4096)) {
+                LOG_E("%s: Incorrect sector size: terminating...", __func__);
+                break;
+            }
+        }
+
+        LOG_D("%s: Received Command from STH2\n", __func__);
+        if (executeCommand()) {
+            break;
+        }
+
+        /* Set "listening" flag before notifying SPT2 */
+        dci.exchange_buffer.nDaemonState = STH2_DAEMON_LISTENING;
+        mc_ret = mcNotify(&session_handle);
+        if (mc_ret != MC_DRV_OK) {
+            LOG_E("%s: mcNotify() returned: 0x%08X\n", __func__, mc_ret);
+            break;
+        }
+    }
+
+    mc_ret = mcCloseSession(&session_handle);
+    if (MC_DRV_OK != mc_ret) {
+        LOG_E("%s: mcCloseSession returned: 0x%08X\n", __func__, mc_ret);
+    }
+
+    mc_ret = mcCloseDevice(MC_DEVICE_ID_DEFAULT);
+    if (MC_DRV_OK != mc_ret) {
+        LOG_E("%s: mcCloseDevice returned: 0x%08X\n", __func__, mc_ret);
+    }
+
+    LOG_W("%s: Exiting Filesystem thread", __func__);
+}
+
+/*----------------------------------------------------------------------------
+ * Instructions
+ *----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Command dispatcher function
+ *----------------------------------------------------------------------------*/
+/* Debug function to show the command name */
+const char* FileSystem::Impl::getCommandtypeString(uint32_t nInstructionID) {
+    switch (nInstructionID) {
+        case DELEGATION_INSTRUCTION_PARTITION_CREATE:
+            return "PARTITION_CREATE";
+        case DELEGATION_INSTRUCTION_PARTITION_OPEN:
+            return "PARTITION_OPEN";
+        case DELEGATION_INSTRUCTION_PARTITION_READ:
+            return "PARTITION_READ";
+        case DELEGATION_INSTRUCTION_PARTITION_WRITE:
+            return "PARTITION_WRITE";
+        case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE:
+            return "PARTITION_SET_SIZE";
+        case DELEGATION_INSTRUCTION_PARTITION_SYNC:
+            return "PARTITION_SYNC";
+        case DELEGATION_INSTRUCTION_PARTITION_CLOSE:
+            return "PARTITION_CLOSE";
+        case DELEGATION_INSTRUCTION_PARTITION_DESTROY:
+            return "PARTITION_DESTROY";
+        case DELEGATION_INSTRUCTION_SHUTDOWN:
+            return "SHUTDOWN";
+        case DELEGATION_INSTRUCTION_NOTIFY:
+            return "NOTIFY";
+        default:
+            return "UNKNOWN";
+    }
+}
+
+int FileSystem::Impl::executeCommand() {
+    TEEC_Result    nError;
+    uint32_t       nInstructionsIndex;
+    uint32_t       nInstructionsBufferSize =
+        dci.exchange_buffer.nInstructionsBufferSize;
+
+
+    LOG_D("%s: nInstructionsBufferSize=%d", __func__, nInstructionsBufferSize);
+
+    /* Reset the operation results */
+    nError = TEEC_SUCCESS;
+    dci.exchange_buffer.sAdministrativeData.nSyncExecuted = 0;
+    ::memset(dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates, 0,
+             sizeof(dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates));
+    ::memset(dci.exchange_buffer.sAdministrativeData.nPartitionOpenSizes, 0,
+             sizeof(dci.exchange_buffer.sAdministrativeData.nPartitionOpenSizes));
+
+    /* Execute the instructions */
+    nInstructionsIndex = 0;
+    while (true) {
+        DELEGATION_INSTRUCTION* pInstruction;
+        uint32_t nInstructionID;
+        pInstruction = (DELEGATION_INSTRUCTION*)(
+                           &dci.exchange_buffer.sInstructions[nInstructionsIndex/4]);
+        if (nInstructionsIndex + 4 > nInstructionsBufferSize) {
+            LOG_D("%s: Instruction buffer end, size = %i", __func__,
+                  nInstructionsBufferSize);
+            return 0;
+        }
+
+        nInstructionID = pInstruction->sGeneric.nInstructionID;
+        nInstructionsIndex += 4;
+
+        LOG_D("%s: nInstructionID=0x%02X [%s], nInstructionsIndex=%d", __func__,
+              nInstructionID, getCommandtypeString(nInstructionID), nInstructionsIndex);
+
+        if ((nInstructionID & 0x0F) == 0) {
+            /* Partition-independent instruction */
+            switch (nInstructionID) {
+                case DELEGATION_INSTRUCTION_SHUTDOWN: {
+                    return 1;
+                }
+                case DELEGATION_INSTRUCTION_NOTIFY: {
+                    /* Parse the instruction parameters */
+                    wchar_t  pMessage[100];
+                    uint32_t nMessageType;
+                    uint32_t nMessageSize;
+                    ::memset(pMessage, 0, 100*sizeof(wchar_t));
+
+                    if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
+                        return 0;
+                    }
+
+                    nMessageType = pInstruction->sNotify.nMessageType;
+                    nMessageSize = pInstruction->sNotify.nMessageSize;
+                    nInstructionsIndex += 8;
+                    if (nMessageSize > (99)*sizeof(wchar_t)) {
+                        /* How to handle the error correctly in this case ? */
+                        return 0;
+                    }
+
+                    if (nInstructionsIndex + nMessageSize > nInstructionsBufferSize) {
+                        return 0;
+                    }
+
+                    ::memcpy(pMessage, &pInstruction->sNotify.nMessage[0], nMessageSize);
+                    nInstructionsIndex += nMessageSize;
+                    /* Align the pInstructionsIndex on 4 bytes */
+                    nInstructionsIndex = (nInstructionsIndex + 3)&~3;
+                    switch (nMessageType) {
+                        case DELEGATION_NOTIFY_TYPE_ERROR:
+                            LOG_E("%s: %ls", __func__, pMessage);
+                            break;
+                        case DELEGATION_NOTIFY_TYPE_WARNING:
+                            LOG_W("%s: %ls", __func__, pMessage);
+                            break;
+                        case DELEGATION_NOTIFY_TYPE_DEBUG:
+                            LOG_D("%s: DEBUG: %ls", __func__, pMessage);
+                            break;
+                        default:
+                            LOG_D("%s: %ls", __func__, pMessage);
+                    }
+                    break;
+                }
+                default: {
+                    LOG_E("%s: Unknown instruction identifier: %02X", __func__, nInstructionID);
+                    nError = S_ERROR_BAD_PARAMETERS;
+                    break;
+                }
+            }
+        } else {
+            /* Partition-specific instruction */
+            uint32_t nPartitionID = (nInstructionID & 0xF0) >> 4;
+            Partition* partition = partitions[nPartitionID];
+            if (dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates[nPartitionID]
+                    == S_SUCCESS) {
+                /* Execute the instruction only if there is currently no error on the partition */
+                switch (nInstructionID & 0x0F) {
+                    case DELEGATION_INSTRUCTION_PARTITION_CREATE: {
+                        nError = partition->create();
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nError);
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_OPEN: {
+                        nError = partition->open();
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d pSize=%ld err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, partition->size() / sector_size,
+                              nError);
+                        if (nError == S_SUCCESS) {
+                            dci.exchange_buffer.sAdministrativeData.nPartitionOpenSizes[nPartitionID] =
+                                static_cast<unsigned int>(partition->size() / sector_size);
+                        }
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_READ: {
+                        /* Parse parameters */
+                        uint32_t nSectorID;
+                        uint32_t nWorkspaceOffset;
+                        if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
+                            return 0;
+                        }
+
+                        nSectorID = pInstruction->sReadWrite.nSectorID;
+                        nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
+                        nInstructionsIndex += 8;
+                        LOG_D("%s: >Partition %1X: read sector 0x%08X into workspace at offset 0x%08X",
+                              __func__, nPartitionID, nSectorID, nWorkspaceOffset);
+                        nError = partition->read(dci.exchange_buffer.sWorkspace + nWorkspaceOffset,
+                                                 sector_size, nSectorID * sector_size);
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_WRITE: {
+                        /* Parse parameters */
+                        uint32_t nSectorID;
+                        uint32_t nWorkspaceOffset;
+                        if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
+                            return 0;
+                        }
+
+                        nSectorID = pInstruction->sReadWrite.nSectorID;
+                        nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
+                        nInstructionsIndex += 8;
+                        LOG_D("%s: >Partition %1X: write sector 0x%X from workspace at offset 0x%X",
+                              __func__, nPartitionID, nSectorID, nWorkspaceOffset);
+                        nError = partition->write(dci.exchange_buffer.sWorkspace + nWorkspaceOffset,
+                                                  sector_size, nSectorID * sector_size);
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_SYNC: {
+                        nError = partition->sync();
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nError);
+                        if (nError == S_SUCCESS) {
+                            dci.exchange_buffer.sAdministrativeData.nSyncExecuted++;
+                        }
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE: {
+                        // nNewSize is a number of sectors
+                        uint32_t nNewSize;
+                        if (nInstructionsIndex + 4 > nInstructionsBufferSize) {
+                            return 0;
+                        }
+
+                        nNewSize = pInstruction->sSetSize.nNewSize;
+                        nInstructionsIndex += 4;
+                        nError = partition->resize(nNewSize * sector_size);
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d nNewSize=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nNewSize, nError);
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_CLOSE: {
+                        nError = partition->close();
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nError);
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_DESTROY: {
+                        nError = partition->destroy();
+                        LOG_D("%s: INSTRUCTION: ID=0x%x pid=%d err=0x%08X", __func__,
+                              (nInstructionID & 0x0F), nPartitionID, nError);
+                        break;
+                    }
+                    default: {
+                        LOG_E("%s: Unknown instruction identifier: %02X", __func__, nInstructionID);
+                        nError = S_ERROR_BAD_PARAMETERS;
+                        break;
+                    }
+                }
+                dci.exchange_buffer.sAdministrativeData.nPartitionErrorStates[nPartitionID] =
+                    nError;
+            } else {
+                /* Skip the instruction if there is currently error on the partition */
+                switch (nInstructionID & 0x0F) {
+                    case DELEGATION_INSTRUCTION_PARTITION_CREATE:
+                    case DELEGATION_INSTRUCTION_PARTITION_OPEN:
+                    case DELEGATION_INSTRUCTION_PARTITION_SYNC:
+                    case DELEGATION_INSTRUCTION_PARTITION_CLOSE:
+                    case DELEGATION_INSTRUCTION_PARTITION_DESTROY:
+                        break;
+                    case DELEGATION_INSTRUCTION_PARTITION_READ:
+                    case DELEGATION_INSTRUCTION_PARTITION_WRITE: {
+                        if (nInstructionsIndex + 8 > nInstructionsBufferSize) {
+                            return 0;
+                        }
+                        nInstructionsIndex += 8;
+                        break;
+                    }
+                    case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE: {
+                        if (nInstructionsIndex + 4 > nInstructionsBufferSize) {
+                            return 0;
+                        }
+                        nInstructionsIndex += 4;
+                        break;
+                    }
+                    default: {
+                        LOG_E("%s: Unknown instruction identifier: %02X", __func__, nInstructionID);
+                        /* OMS: update partition error with BAD PARAM ? */
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
diff --git a/mobicore/Daemon/src/FSD2.h b/mobicore/Daemon/src/FSD2.h
new file mode 100644 (file)
index 0000000..bda4c48
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FSD2_H_
+#define FSD2_H_
+
+class FileSystem {
+    struct Impl;
+    Impl* const pimpl_;
+    // Until we can use std::thread everywhere
+    static void* run(void* arg);
+public:
+    /**
+     * Constructor.
+     */
+    FileSystem();
+    /**
+     * Destructor.
+     */
+    ~FileSystem();
+    /**
+     * Ensure resources are available and start main thread.
+     */
+    int open();
+    /**
+     * Stop main thread and free resources.
+     */
+    int close();
+};
+
+#endif /* FSD2_H_ */
+
diff --git a/mobicore/Daemon/src/MobiCoreDriverCmd.h b/mobicore/Daemon/src/MobiCoreDriverCmd.h
new file mode 100644 (file)
index 0000000..06c6e99
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MOBICORE_REGISTRY_API_H_
+#define MOBICORE_REGISTRY_API_H_
+
+#include "mcUuid.h"
+#include "mcSpid.h"
+
+#define SOCK_PATH "#mcdaemon"
+
+typedef enum {
+    // Auth token OPS
+    MC_DRV_REG_READ_AUTH_TOKEN     = 0,
+    MC_DRV_REG_WRITE_AUTH_TOKEN,
+    MC_DRV_REG_DELETE_AUTH_TOKEN,
+    // Root container OPS
+    MC_DRV_REG_READ_ROOT_CONT,
+    MC_DRV_REG_WRITE_ROOT_CONT,
+    MC_DRV_REG_DELETE_ROOT_CONT,
+    // Service Provider Container OPS
+    MC_DRV_REG_READ_SP_CONT,
+    MC_DRV_REG_WRITE_SP_CONT,
+    MC_DRV_REG_DELETE_SP_CONT,
+    // Trustlet Container OPS
+    MC_DRV_REG_READ_TL_CONT,
+    MC_DRV_REG_WRITE_TL_CONT,
+    MC_DRV_REG_DELETE_TL_CONT,
+    // Shared Object Data write
+    MC_DRV_REG_WRITE_SO_DATA,
+    // TA Blob store
+    MC_DRV_REG_STORE_TA_BLOB,
+    // Delete all TA objects
+    MC_DRV_REG_DELETE_TA_OBJS,
+
+    MC_DRV_REG_END
+} mcDrvCmd_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+       /* id - free run counter managed by driver, initialized by
+        * initial_cmd_counter, incremented for each command.
+        * If difference between current value and value from previous command
+        * is greater than 1, it means daemon and driver are out of synch. */
+       uint32_t id;
+       uint32_t cmd;
+       uint32_t data_size;
+} CommandHeader;
+
+typedef struct {
+       /* id - must be same value as it was in the corresponding command,
+        * but managed by daemon */
+       uint32_t id;
+       uint32_t result;
+       uint32_t data_size;
+} ResponseHeader;
+
+typedef struct {
+       uint32_t len;
+       uint32_t tl_start_off;
+       uint8_t value[];
+} regObject_t;
+
+typedef struct {
+       mcUuid_t uuid;
+       mcSpid_t spid;
+       uint8_t blob[];
+} TlBlob;
+
+typedef struct {
+       mcSpid_t spid;
+       uint8_t blob[];
+} TaBlob;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MOBICORE_REGISTRY_API_H_
diff --git a/mobicore/Daemon/src/MobiCoreDriverDaemon.cpp b/mobicore/Daemon/src/MobiCoreDriverDaemon.cpp
new file mode 100644 (file)
index 0000000..9a822a3
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <signal.h>
+#include <libgen.h>
+
+#include <log.h>
+
+#include "cutils/properties.h"
+#include "mcVersion.h"
+#include "PrivateRegistry.h"
+#include "MobiCoreDriverDaemon.h"
+#include "buildTag.h"
+
+#define DRIVER_TCI_LEN 4096
+
+static SecureWorld* g_secure_world;
+
+//------------------------------------------------------------------------------
+/**
+ * Print daemon command line options
+ */
+static
+int printUsage(char *path)
+{
+    fprintf(stderr, "<t-base Driver Daemon %u.%u. \"%s\" %s %s\n",
+            DAEMON_VERSION_MAJOR, DAEMON_VERSION_MINOR,
+            MOBICORE_COMPONENT_BUILD_TAG, __DATE__, __TIME__);
+    fprintf(stderr, "usage: %s [-hbr]\n", basename(path));
+    fprintf(stderr, "Start <t-base Daemon\n\n");
+    fprintf(stderr, "-h\t\tshow this help\n");
+    fprintf(stderr, "-b\t\tfork to background\n");
+    fprintf(stderr, "-r DRIVER\t<t-base driver to load at start-up\n");
+    return 2;
+}
+
+//------------------------------------------------------------------------------
+/**
+ * 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
+ */
+const MobiCoreDriverDaemon::cmd_map_item_t
+MobiCoreDriverDaemon::reg_cmd_map[] = {
+    {
+        &MobiCoreDriverDaemon::reg_read_auth_token,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_store_auth_token,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_delete_auth_token,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_read_root_cont,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_store_root_cont,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_delete_root_cont,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_read_sp_cont,
+        sizeof(mcSpid_t)
+    },
+    {
+        &MobiCoreDriverDaemon::reg_store_sp_cont,
+        sizeof(TaBlob)
+    },
+    {
+        &MobiCoreDriverDaemon::reg_delete_sp_cont,
+        sizeof(mcSpid_t)
+    },
+    {
+        &MobiCoreDriverDaemon::reg_read_tl_cont,
+        sizeof(TlBlob)
+    },
+    {
+        &MobiCoreDriverDaemon::reg_store_tl_cont,
+        sizeof(TlBlob)
+    },
+    {
+        &MobiCoreDriverDaemon::reg_delete_tl_cont,
+        sizeof(TlBlob)
+    },
+    {
+        &MobiCoreDriverDaemon::reg_store_so_data,
+        0
+    },
+    {
+        &MobiCoreDriverDaemon::reg_store_ta_blob,
+        sizeof(TaBlob)
+    },
+    {
+       &MobiCoreDriverDaemon::reg_delete_ta_objs,
+        sizeof(mcUuid_t)
+    },
+};
+
+static void terminateDaemon(int signum)
+{
+    LOG_I("Signal %d received", signum);
+    if ((signum != SIGUSR1) && g_secure_world) {
+        g_secure_world->stopListening();
+    }
+}
+
+MobiCoreDriverDaemon::MobiCoreDriverDaemon():
+    m_reg_server(this, SOCK_PATH)
+{
+}
+
+//------------------------------------------------------------------------------
+int MobiCoreDriverDaemon::init(const std::vector<std::string>& drivers)
+{
+    sigset_t sigs_to_block;
+
+    if (!m_reg_server.valid())
+        return EXIT_FAILURE;
+
+    LOG_D("Initializing Device");
+
+    /* Set main thread's signal mask to block SIGUSR1.
+     * All other threads will inherit mask and have it blocked too */
+    sigemptyset(&sigs_to_block);
+    sigaddset(&sigs_to_block, SIGUSR1);
+    pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
+
+    // Open Secure World access
+    if (m_secure_world.open() < 0) {
+        return EXIT_FAILURE;
+    }
+
+    // Load SW device driver(s), if requested
+    for (auto driver = drivers.begin(); driver != drivers.end(); driver++) {
+        // We don't care will loadDriver failed or not...
+        m_secure_world.loadDriver(driver->c_str());
+    }
+
+    // Look for tokens and send it to <t-base if any
+    installEndorsementToken();
+
+    LOG_D("\n********* successfully initialized Daemon *********");
+    return EXIT_SUCCESS;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_store_auth_token(
+        const std::string& rx_data, std::string&)
+{
+    mcResult_t mcRet = mcRegistryStoreAuthToken(&rx_data[0], rx_data.size());
+    /* Load authentication token into <t-base */
+    if (MC_DRV_OK == mcRet) {
+        if (m_secure_world.loadToken(&rx_data[0], rx_data.size()) < 0) {
+            LOG_E("Failed to pass Auth Token to <t-base.");
+        }
+    }
+    return mcRet;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_store_root_cont(
+        const std::string& rx_data, std::string&)
+{
+    mcResult_t mcRet = mcRegistryStoreRoot(&rx_data[0], rx_data.size());
+    /* Load root container into <t-base */
+    if (MC_DRV_OK == mcRet) {
+        if (m_secure_world.loadToken(&rx_data[0], rx_data.size()) < 0) {
+            LOG_E("Failed to pass Root Container to <t-base.");
+        }
+    }
+    return mcRet;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_store_sp_cont(
+        const std::string& rx_data, std::string&)
+{
+    auto blob = reinterpret_cast<const TaBlob*>(&rx_data[0]);
+    size_t blobSize = rx_data.size() - sizeof(*blob);
+    return mcRegistryStoreSp(blob->spid, blob->blob, blobSize);
+}
+
+uint32_t MobiCoreDriverDaemon::reg_store_tl_cont(
+        const std::string& rx_data, std::string&)
+{
+    auto blob = reinterpret_cast<const TlBlob*>(&rx_data[0]);
+    size_t blobSize = rx_data.size() - sizeof(*blob);
+    return mcRegistryStoreTrustletCon(&blob->uuid, blob->spid, blob->blob, blobSize);
+}
+
+uint32_t MobiCoreDriverDaemon::reg_store_so_data(
+        const std::string& rx_data, std::string&)
+{
+    return mcRegistryStoreData(&rx_data[0], rx_data.size());
+}
+
+uint32_t MobiCoreDriverDaemon::reg_store_ta_blob(
+        const std::string& rx_data, std::string&)
+{
+    auto blob = reinterpret_cast<const TaBlob*>(&rx_data[0]);
+    if (rx_data.size() < sizeof(*blob)) {
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    size_t blobSize = rx_data.size() - sizeof(*blob);
+    if (m_secure_world.LoadCheck(blob->spid, blob->blob,
+                                 static_cast<uint32_t>(blobSize)) < 0) {
+        return MC_DRV_ERR_TRUSTLET_NOT_FOUND;
+    }
+    return mcRegistryStoreTABlob(blob->spid, blob->blob, blobSize);
+}
+
+uint32_t MobiCoreDriverDaemon::reg_read_auth_token(
+        const std::string&, std::string& tx_data)
+{
+    // Make buffer big enough
+    tx_data.resize(sizeof(mcSoAuthTokenCont_t));
+    return mcRegistryReadAuthToken(reinterpret_cast<mcSoAuthTokenCont_t*>(&tx_data[0]));
+}
+
+uint32_t MobiCoreDriverDaemon::reg_read_root_cont(
+        const std::string&, std::string& tx_data)
+{
+    // Make buffer big enough
+    tx_data.resize(MAX_DATA_SIZE);
+    uint32_t size = MAX_DATA_SIZE;
+    uint32_t ret = mcRegistryReadRoot(&tx_data[0], &size);
+    if (ret == MC_DRV_OK) {
+        tx_data.resize(size);
+    }
+    return ret;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_read_sp_cont(
+        const std::string& rx_data, std::string& tx_data)
+{
+    const mcSpid_t &spid = *reinterpret_cast<const mcSpid_t *>(&rx_data[0]);
+    // Make buffer big enough
+    tx_data.resize(MAX_DATA_SIZE);
+    uint32_t size = MAX_DATA_SIZE;
+    uint32_t ret = mcRegistryReadSp(spid, &tx_data[0], &size);
+    if (ret == MC_DRV_OK) {
+        tx_data.resize(size);
+    }
+    return ret;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_read_tl_cont(
+        const std::string& rx_data, std::string& tx_data)
+{
+    auto blob = reinterpret_cast<const TlBlob*>(&rx_data[0]);
+    // Make buffer big enough
+    tx_data.resize(MAX_DATA_SIZE);
+    uint32_t size = MAX_DATA_SIZE;
+    uint32_t ret = mcRegistryReadTrustletCon(&blob->uuid, blob->spid, &tx_data[0], &size);
+    if (ret == MC_DRV_OK) {
+        tx_data.resize(size);
+    }
+    return ret;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_delete_auth_token(
+        const std::string&, std::string&)
+{
+    return mcRegistryDeleteAuthToken();
+}
+
+uint32_t MobiCoreDriverDaemon::reg_delete_root_cont(
+        const std::string&, std::string&)
+{
+    mcResult_t mcRet = mcRegistryCleanupRoot();
+
+    // Look for tokens and send it to <t-base if any
+    if (MC_DRV_OK == mcRet)
+        installEndorsementToken();
+
+    return mcRet;
+}
+
+uint32_t MobiCoreDriverDaemon::reg_delete_sp_cont(
+        const std::string& rx_data, std::string&)
+{
+    const mcSpid_t &spid = *reinterpret_cast<const mcSpid_t *>(&rx_data[0]);
+    return mcRegistryCleanupSp(spid);
+}
+
+uint32_t MobiCoreDriverDaemon::reg_delete_tl_cont(
+        const std::string& rx_data, std::string&)
+{
+    auto blob = reinterpret_cast<const TlBlob*>(&rx_data[0]);
+    return mcRegistryCleanupTrustlet(&blob->uuid, blob->spid);
+}
+
+uint32_t MobiCoreDriverDaemon::reg_delete_ta_objs(
+        const std::string& rx_data, std::string&)
+{
+    const mcUuid_t *uuid = reinterpret_cast<const mcUuid_t *>(&rx_data[0]);
+    return mcRegistryCleanupGPTAStorage(uuid);
+}
+
+bool MobiCoreDriverDaemon::handleConnection(Connection &conn)
+{
+    LOG_D("handleConnection()==== %p", &conn);
+
+    CommandHeader cmd;
+    switch (conn.readData(&cmd, sizeof(cmd))) {
+    case sizeof(cmd):
+        break;
+    case 0:
+        LOG_D(" handleConnection(): Connection closed.");
+        return false;
+    case -1:
+        LOG_E("Socket error.");
+        return false;
+    case -2:
+        LOG_E("Timeout.");
+        return false;
+    default:
+        LOG_E("Insufficient data arrived.");
+        return false;
+    }
+
+    ResponseHeader result = { 0, MC_DRV_OK, 0 };
+    std::string rx_data;
+    std::string tx_data;
+
+    if (MC_DRV_REG_END > cmd.cmd) {
+        if (cmd.data_size) {
+            if (cmd.data_size >= reg_cmd_map[cmd.cmd].min_rx_size) {
+                rx_data.resize(cmd.data_size);
+                size_t total = 0;
+                while (total < rx_data.size()) {
+                    ssize_t sz = conn.readData(&rx_data[total], cmd.data_size - total);
+                    if (sz <= 0) {
+                        LOG_E("Payload reading failed for command %d expected=%zu received=%zd", cmd.cmd, cmd.data_size - total, sz);
+                        result.result = MC_DRV_ERR_UNKNOWN;
+                        break;
+                    }
+                    total += sz;
+                }
+            } else {
+                LOG_E("Invalid payload size for command %d", cmd.cmd);
+            }
+        }
+
+        if (result.result == MC_DRV_OK) {
+            result.result = (this->*(reg_cmd_map[cmd.cmd].handler))(rx_data, tx_data);
+        }
+    } else {
+        LOG_E("Unknown command %d", cmd.cmd);
+        result.result = MC_DRV_ERR_INVALID_OPERATION;
+    }
+
+    struct iovec iov[2];
+    iov[0].iov_len  = sizeof(result);
+    iov[0].iov_base = const_cast<ResponseHeader *>(&result);
+    int count = 1;
+    ssize_t write_sz = sizeof(result);
+
+    if ((result.result == MC_DRV_OK) && !tx_data.empty()) {
+        iov[1].iov_len = tx_data.size();
+        iov[1].iov_base = &tx_data[0];
+        count++;
+        write_sz += tx_data.size();
+    }
+
+    LOG_D("handleConnection()<-------");
+    return conn.writeMsg(iov, count) == write_sz;
+}
+
+int MobiCoreDriverDaemon::run()
+{
+    LOG_D("run()====");
+
+    // Start File Storage Daemon and registry server
+#ifndef WITHOUT_FSD
+    m_filesystem.open();
+#endif
+    m_reg_server.start();
+
+    /* Exy SP: To let the other daemon which calls TA know
+       if secureOS daemon is loaded or not */
+   LOG_I("McDaemon.Server was loaded");
+   property_set("secure_os.init", "done");
+
+#ifndef WITHOUT_PROXY
+    m_proxy_server.open();
+#endif
+
+    g_secure_world = &m_secure_world;
+    // This call blocks
+    int ret = m_secure_world.listen();
+
+#ifndef WITHOUT_PROXY
+    m_proxy_server.close();
+#endif
+    m_reg_server.terminate();
+    m_reg_server.kill(SIGUSR1);
+    m_reg_server.stop();
+    m_reg_server.join();
+
+#ifndef WITHOUT_FSD
+    m_filesystem.close();
+#endif
+    LOG_I("run()<-------");
+
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+/**
+ * Main entry of the <t-base Driver Daemon.
+ */
+int main(int argc, char *args[])
+{
+    int ret;
+
+    // Read the Command line options
+    extern char *optarg;
+    extern int optopt;
+    int c, errFlag = 0;
+
+    std::vector<std::string> drivers;
+    std::vector<std::string> registry_paths;
+
+    // By default don't fork
+    bool is_daemon = false;
+
+    while ((c = getopt(argc, args, "r:bhp:")) != -1) {
+        switch (c) {
+        case 'h': /* Help */
+            errFlag++;
+            break;
+        case 'b': /* Fork to background */
+            is_daemon = true;
+            break;
+        case 'p': /* Search paths for registry */
+            registry_paths.push_back(optarg);
+            LOG_D("registry search path %s added", optarg);
+            break;
+        case 'r': /* Load <t-base driver at start-up */
+            drivers.push_back(optarg);
+            LOG_D("driver %s enqueued for loading", optarg);
+            break;
+        case ':': /* -r operand */
+            fprintf(stderr, "Option -%c requires an operand\n", optopt);
+            errFlag++;
+            break;
+        case '?':
+            fprintf(stderr, "Unrecognized option: -%c\n", optopt);
+            errFlag++;
+        }
+    }
+
+    if (errFlag)
+        return printUsage(args[0]);
+
+    // Default registry paths if none specified (for Android)
+    if (registry_paths.empty()) {
+        registry_paths.push_back("/data/app/mcRegistry");
+        registry_paths.push_back("/system/app/mcRegistry");
+    }
+    setSearchPaths(registry_paths);
+    LOG_D("Registry search paths:");
+    for (auto path = registry_paths.begin(); path != registry_paths.end(); path++) {
+        LOG_D("  %s", path->c_str());
+    }
+
+    // Open the device before becoming a daemon
+    MobiCoreDriverDaemon mobiCoreDriverDaemon;
+    if (mobiCoreDriverDaemon.init(drivers)) {
+        return EXIT_FAILURE;
+    }
+
+    // We should fork the daemon to background
+    if (is_daemon) {
+        /* ignore "terminal has been closed" signal */
+        signal(SIGHUP, SIG_IGN);
+
+        if (daemon(0, 0) < 0) {
+            fprintf(stderr, "Fork failed, exiting...\n");
+            return 1;
+        }
+        LOG_D("Daemon's fork was done");
+
+        /* ignore tty signals */
+        signal(SIGTSTP, SIG_IGN);
+        signal(SIGTTOU, SIG_IGN);
+        signal(SIGTTIN, SIG_IGN);
+    }
+
+    // Process signal action
+    struct sigaction action;
+
+    // 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(SIGTERM, &action, NULL);
+    sigaction(SIGUSR1, &action, NULL);
+
+    signal(SIGPIPE, SIG_IGN);
+
+    LOG_I("Daemon starting up...");
+    LOG_I("Interface version is %u.%u", DAEMON_VERSION_MAJOR,
+            DAEMON_VERSION_MINOR);
+
+    LOG_I("%s", MOBICORE_COMPONENT_BUILD_TAG);
+    LOG_I("Build timestamp is %s %s", __DATE__, __TIME__);
+
+    ret = mobiCoreDriverDaemon.run();
+
+    LOG_D("Daemon exit with code %d...", ret);
+    return ret;
+}
+
+void MobiCoreDriverDaemon::installEndorsementToken(void)
+{
+       /* Look for tokens in the registry and pass them to <t-base for endorsement
+        * purposes.
+        */
+       LOG_D("Looking for suitable tokens");
+
+       mcSoAuthTokenCont_t authtoken;
+       mcSoAuthTokenCont_t authtokenbackup;
+       mcSoRootCont_t rootcont;
+       uint32_t sosize;
+       const void *p = NULL;
+
+       // Search order:  1. authtoken 2. authtoken backup 3. root container
+       sosize = 0;
+       mcResult_t ret = mcRegistryReadAuthToken(&authtoken);
+       if (ret != MC_DRV_OK) {
+           LOG_D("Failed to read AuthToken (ret=%u). Trying AuthToken backup", ret);
+
+           ret = mcRegistryReadAuthTokenBackup(&authtokenbackup);
+           if (ret != MC_DRV_OK) {
+               LOG_D("Failed to read AuthToken backup (ret=%u). Trying Root Cont", ret);
+
+           sosize = sizeof(rootcont);
+           ret = mcRegistryReadRoot(&rootcont, &sosize);
+           if (ret != MC_DRV_OK) {
+                   LOG_D("Failed to read Root Cont, (ret=%u).", ret);
+                   LOG_W("Device endorsements not supported!");
+                   sosize = 0;
+               } else {
+                   LOG_D("Found Root Cont.");
+                   p = &rootcont;
+               }
+
+           } else {
+               LOG_D("Found AuthToken backup.");
+               p = &authtokenbackup;
+               sosize = sizeof(authtokenbackup);
+           }
+
+       } else {
+           LOG_D("Found AuthToken.");
+           p = &authtoken;
+           sosize = sizeof(authtoken);
+       }
+
+       if (sosize) {
+           LOG_D("Found token of size: %u", sosize);
+           if (m_secure_world.loadToken(p, sosize) < 0) {
+               LOG_E("Failed to pass token to <t-base. "
+                     "Device endorsements disabled");
+           }
+       }
+}
diff --git a/mobicore/Daemon/src/MobiCoreDriverDaemon.h b/mobicore/Daemon/src/MobiCoreDriverDaemon.h
new file mode 100644 (file)
index 0000000..0c6ab2e
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICOREDRIVER_H_
+#define MOBICOREDRIVER_H_
+
+#include <string>
+#include <vector>
+
+#include "ConnectionHandler.h"
+#include "Server.h"
+#ifndef WITHOUT_FSD
+#include "FSD2.h"
+#endif
+#include "SecureWorld.h"
+#ifndef WITHOUT_PROXY
+#include "proxy_server.h"
+#endif
+
+class MobiCoreDriverDaemon: public ConnectionHandler
+{
+    struct cmd_map_item_t {
+        uint32_t (MobiCoreDriverDaemon:: *handler)(
+            const std::string& rx_data,
+            std::string& tx_data);
+        uint32_t min_rx_size;
+    };
+
+    /**
+     * installEndorsementToken
+     * Look for tokens in the registry and pass them to <t-base for endorsement purposes
+     * Search order:  1. authtoken 2. authtoken backup 3. root container
+     */
+    void installEndorsementToken(void);
+
+    bool handleConnection(Connection &connection);
+    void dropConnection(Connection&) {}
+
+    /* Registry commands, arrived through socket */
+    uint32_t reg_store_auth_token(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_store_root_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_store_sp_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_store_tl_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_store_so_data(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_store_ta_blob(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_read_auth_token(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_read_root_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_read_sp_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_read_tl_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_delete_auth_token(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_delete_root_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_delete_sp_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_delete_tl_cont(
+        const std::string& rx_data,
+        std::string& tx_data);
+    uint32_t reg_delete_ta_objs(
+        const std::string& rx_data,
+        std::string& tx_data);
+
+    static const cmd_map_item_t reg_cmd_map[];
+    static const uint MAX_DATA_SIZE = 512;
+
+    SecureWorld m_secure_world;
+#ifndef WITHOUT_PROXY
+    ProxyServer m_proxy_server;
+#endif
+#ifndef WITHOUT_FSD
+    FileSystem m_filesystem;
+#endif
+    Server  m_reg_server;
+public:
+    MobiCoreDriverDaemon();
+    int init(const std::vector<std::string>& drivers);
+    int run (void);
+};
+
+#endif /* MOBICOREDRIVER_H_ */
diff --git a/mobicore/Daemon/src/PrivateRegistry.cpp b/mobicore/Daemon/src/PrivateRegistry.cpp
new file mode 100644 (file)
index 0000000..e4f40fb
--- /dev/null
@@ -0,0 +1,1337 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** Mobicore Driver Registry.
+ *
+ * Implements the MobiCore driver registry which maintains trustlets.
+ *
+ * @file
+ * @ingroup MCD_MCDIMPL_DAEMON_REG
+ */
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <string.h>
+#include <string>
+#include <cstring>
+#include <cstddef>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+
+#include "mcLoadFormat.h"
+#include "mcSpid.h"
+#include "mcVersionHelper.h"
+
+#include "PrivateRegistry.h"
+
+#include <tee_client_api.h>
+#include "uuid_attestation.h"
+
+#include <log.h>
+
+/** Maximum size of a shared object container in bytes. */
+#define MAX_SO_CONT_SIZE  (512)
+
+#define MC_REGISTRY_ALL      0
+#define MC_REGISTRY_WRITABLE 1
+
+#define AUTH_TOKEN_FILE_NAME "00000000.authtokcont"
+#define AUTH_TOKEN_FILE_NAME_BACKUP_SUFFIX ".backup"
+#define ENV_MC_AUTH_TOKEN_PATH "MC_AUTH_TOKEN_PATH"
+#define ROOT_FILE_NAME "00000000.rootcont"
+#define SP_CONT_FILE_EXT ".spcont"
+#define TL_CONT_FILE_EXT ".tlcont"
+#define DATA_CONT_FILE_EXT ".datacont"
+#define TL_BIN_FILE_EXT ".tlbin"
+#define GP_TA_BIN_FILE_EXT ".tabin"
+#define GP_TA_SPID_FILE_EXT ".spid"
+
+static std::vector<std::string> search_paths;
+static std::string tb_storage_path;
+
+//------------------------------------------------------------------------------
+static std::string byteArrayToString(const void *bytes, size_t elems)
+{
+    auto cbytes = static_cast<const char *>(bytes);
+    char hx[elems * 2 + 1];
+
+    for (size_t i = 0; i < elems; i++) {
+        sprintf(&hx[i * 2], "%02x", cbytes[i]);
+    }
+    return std::string(hx);
+}
+
+//------------------------------------------------------------------------------
+static std::string uint32ToString(uint32_t value)
+{
+    char hx[8 + 1];
+    snprintf(hx, sizeof(hx), "%08X", value);
+    std::string str(hx);
+    return std::string(str.rbegin(), str.rend());
+}
+
+//------------------------------------------------------------------------------
+static bool dirExists(const char *path)
+{
+    struct stat ss;
+
+    return (path != NULL) && (stat(path, &ss) == 0) && S_ISDIR(ss.st_mode);
+}
+
+//------------------------------------------------------------------------------
+const std::string& getTbStoragePath()
+{
+    return tb_storage_path;
+}
+
+//------------------------------------------------------------------------------
+static std::string getAuthTokenFilePath()
+{
+    const char *path;
+    std::string authTokenPath;
+
+    // First, attempt to use regular auth token path environment variable.
+    path = getenv(ENV_MC_AUTH_TOKEN_PATH);
+    if (dirExists(path)) {
+        LOG_D("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path);
+        authTokenPath = path;
+    } else {
+        authTokenPath = search_paths[0];
+        LOG_D("getAuthTokenFilePath(): Using path %s", authTokenPath.c_str());
+    }
+
+    return authTokenPath + "/" + AUTH_TOKEN_FILE_NAME;
+}
+
+//------------------------------------------------------------------------------
+static std::string getAuthTokenFilePathBackup()
+{
+    return getAuthTokenFilePath() + AUTH_TOKEN_FILE_NAME_BACKUP_SUFFIX;
+}
+
+//------------------------------------------------------------------------------
+static std::string getRootContFilePath()
+{
+    return search_paths[0] + "/" + ROOT_FILE_NAME;
+}
+
+//------------------------------------------------------------------------------
+static std::string getSpDataPath(mcSpid_t spid)
+{
+    return search_paths[0] + "/" + uint32ToString(spid);
+}
+
+//------------------------------------------------------------------------------
+static std::string getSpContFilePath(mcSpid_t spid)
+{
+    return search_paths[0] + "/" + uint32ToString(spid) + SP_CONT_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static std::string getTlContFilePath(const mcUuid_t *uuid, const mcSpid_t spid)
+{
+    return search_paths[0] + "/" + byteArrayToString(uuid, sizeof(*uuid))
+           + "." + uint32ToString(spid) + TL_CONT_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static std::string getTlDataPath(const mcUuid_t *uuid)
+{
+    return search_paths[0] + "/" + byteArrayToString(uuid, sizeof(*uuid));
+}
+
+//------------------------------------------------------------------------------
+static std::string getTlDataFilePath(const mcUuid_t *uuid, mcPid_t pid)
+{
+    return getTlDataPath(uuid) + "/" + uint32ToString(pid.data) + DATA_CONT_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static std::string getTlBinFilePath(const mcUuid_t *uuid, int registry)
+{
+    std::string path_rw_registry = search_paths[0] + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT;
+
+    if ((registry == MC_REGISTRY_ALL) && (search_paths.size() > 1)) {
+        std::string path_ro_registry = search_paths[1] + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT;
+        struct stat tmp;
+        if (stat(path_ro_registry.c_str(), &tmp) == 0) {
+            return path_ro_registry;
+        }
+    }
+    return path_rw_registry;
+}
+
+//------------------------------------------------------------------------------
+static std::string getTABinFilePath(const mcUuid_t *uuid, int registry)
+{
+    std::string path_rw_registry = search_paths[0] + "/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_BIN_FILE_EXT;
+
+    if ((registry == MC_REGISTRY_ALL) && (search_paths.size() > 1)) {
+        std::string path_ro_registry = search_paths[1] + "/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_BIN_FILE_EXT;
+        struct stat tmp;
+        if (stat(path_ro_registry.c_str(), &tmp) == 0) {
+            return path_ro_registry;
+        }
+    }
+    return path_rw_registry;
+}
+
+//------------------------------------------------------------------------------
+static std::string getTASpidFilePath(const mcUuid_t *uuid, int registry)
+{
+    std::string path_rw_registry = search_paths[0] + "/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_SPID_FILE_EXT;
+
+    if ((registry == MC_REGISTRY_ALL) && (search_paths.size() > 1)) {
+        std::string path_ro_registry = search_paths[1] + "/" + byteArrayToString(uuid, sizeof(*uuid)) + GP_TA_SPID_FILE_EXT;
+        struct stat tmp;
+        if (stat(path_ro_registry.c_str(), &tmp) == 0) {
+            return path_ro_registry;
+        }
+    }
+    return path_rw_registry;
+}
+
+//------------------------------------------------------------------------------
+void setSearchPaths(const std::vector<std::string>& paths)
+{
+    search_paths = paths;
+    tb_storage_path = search_paths[0] + "/TbStorage";
+}
+
+static inline bool isAllZeros(const unsigned char *so, uint32_t size)
+{
+    for (uint32_t i = 0; i < size; i++) {
+        if (so[i]) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreAuthToken(const void *so, size_t size)
+{
+    int res = 0;
+    if (so == NULL || size > 3 * MAX_SO_CONT_SIZE) {
+        LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const std::string &authTokenFilePath = getAuthTokenFilePath();
+    LOG_D("store AuthToken: %s", authTokenFilePath.c_str());
+
+    /*
+     * This special handling is needed because some of our OEM partners do not
+     * supply the AuthToken to Kinibi Sphere. Instead, they retain the
+     * AuthToken in a dedicated (reliable) storage area on the device. And in
+     * that case, Kinibi Sphere is populated with a all-zero-padded AuthToken.
+     * (Obviously the zero-padded AuthToken won't work, so we use that zero-
+     * padding as an indicator to trigger the special behaviour.)
+     *
+     * When Kinibi Sphere supplies the device with the zero-padded AuthToken,
+     * the device must look retrieve the AuthToken from its dedicated storage,
+     * and use it in place of the zero-padded AuthToken supplied by Kinibi
+     * Sphere. Since the AuthToken Backup will already have been retrieved from
+     * the dedicated storage area by the time this method is called, using the
+     * AuthToken Backup as our source is an acceptable proxy for retrieving it
+     * from the dedicated storage area directly.
+     *
+     * This behaviour is triggered following Root.PA detecting a Factory Reset.
+     */
+    void *backup = NULL;
+    if (isAllZeros((const unsigned char*)so, size)) {
+        const std::string &authTokenFilePathBackup = getAuthTokenFilePathBackup();
+
+        LOG_D("AuthToken is all zeros");
+        FILE *backupfs = fopen(authTokenFilePathBackup.c_str(), "rb");
+        if (backupfs) {
+            backup = malloc(size);
+            if (backup) {
+                size_t readsize = fread(backup, 1, size, backupfs);
+                if (readsize == size) {
+                    LOG_D("AuthToken reset backup");
+                    so = backup;
+                } else {
+                    LOG_E("AuthToken read size = %zu (%zu)", readsize, size);
+                }
+            }
+            fclose(backupfs);
+        } else {
+            LOG_W("can't open AuthToken %s", authTokenFilePathBackup.c_str());
+        }
+    }
+
+    mcResult_t ret = MC_DRV_OK;
+    FILE *fs = fopen(authTokenFilePath.c_str(), "wb");
+    if (fs == NULL) {
+        ret = MC_DRV_ERR_INVALID_DEVICE_FILE;
+    } else {
+        res = fseek(fs, 0, SEEK_SET);
+        if (res != 0) {
+            ret = MC_DRV_ERR_INVALID_PARAMETER;
+        } else {
+            fwrite(so, 1, size, fs);
+            if (ferror(fs)) {
+                ret = MC_DRV_ERR_OUT_OF_RESOURCES;
+            }
+        }
+        fclose(fs);
+    }
+    if (ret != MC_DRV_OK) {
+        LOG_ERRNO("mcRegistry store So.Soc failed");
+    }
+    free(backup);
+
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadAuthToken(mcSoAuthTokenCont_t *so)
+{
+    int res = 0;
+    if (NULL == so) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const std::string &authTokenFilePath = getAuthTokenFilePath();
+    LOG_D("read AuthToken: %s", authTokenFilePath.c_str());
+
+    FILE *fs = fopen(authTokenFilePath.c_str(), "rb");
+    if (fs==NULL) {
+        LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_END);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    long filesize = ftell(fs);
+    // We ensure that mcSoAuthTokenCont_t matches with filesize, as ferror (during fread operation) can't
+    // handle the case where mcSoAuthTokenCont_t < filesize
+    if (sizeof(mcSoAuthTokenCont_t) != filesize) {
+        fclose(fs);
+        LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    size_t read_res = fread(so, 1, sizeof(mcSoAuthTokenCont_t), fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if (read_res<sizeof(mcSoAuthTokenCont_t)) {
+        //File is shorter than expected
+        if (feof(fs)) {
+            LOG_E("%s(): EOF reached: res is %zu, size of mcSoAuthTokenCont_t is %zu", __func__, read_res, sizeof(mcSoAuthTokenCont_t));
+        }
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadAuthTokenBackup(mcSoAuthTokenCont_t *so)
+{
+    int res = 0;
+    if (NULL == so) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const std::string &authTokenFilePath = getAuthTokenFilePathBackup();
+    LOG_D("read AuthToken: %s", authTokenFilePath.c_str());
+
+    FILE *fs = fopen(authTokenFilePath.c_str(), "rb");
+    if (fs==NULL) {
+        LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_END);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    long filesize = ftell(fs);
+    // We ensure that mcSoAuthTokenCont_t matches with filesize, as ferror (during fread operation) can't
+    // handle the case where mcSoAuthTokenCont_t < filesize
+    if (sizeof(mcSoAuthTokenCont_t) != filesize) {
+        fclose(fs);
+        LOG_W("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    size_t read_res = fread(so, 1, sizeof(mcSoAuthTokenCont_t), fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if (read_res<sizeof(mcSoAuthTokenCont_t)) {
+        //File is shorter than expected
+        if (feof(fs)) {
+            LOG_E("%s(): EOF reached: res is %zu, size of mcSoAuthTokenCont_t is %zu", __func__,
+            read_res, sizeof(mcSoAuthTokenCont_t));
+        }
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryDeleteAuthToken(void)
+{
+    if (rename(getAuthTokenFilePath().c_str(), getAuthTokenFilePathBackup().c_str())) {
+        LOG_ERRNO("Rename Auth token file!");
+        return MC_DRV_ERR_UNKNOWN;
+    } else
+        return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreRoot(const void *so, size_t size)
+{
+    int res = 0;
+    if (so == NULL || size > 3 * MAX_SO_CONT_SIZE) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    const std::string &rootContFilePath = getRootContFilePath();
+    LOG_D("store Root: %s", rootContFilePath.c_str());
+
+    FILE *fs = fopen(rootContFilePath.c_str(), "wb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fwrite(so, 1, size, fs);
+    if (ferror(fs)) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        fclose(fs);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fflush(fs);
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadRoot(void *so, uint32_t *size)
+{
+    const std::string &rootContFilePath = getRootContFilePath();
+    size_t readBytes;
+
+    if (so == NULL) {
+        LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    LOG_D(" Opening %s", rootContFilePath.c_str());
+
+    FILE *fs = fopen(rootContFilePath.c_str(), "rb");
+    if (fs==NULL) {
+        LOG_W("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    readBytes = fread(so, 1, *size, fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fclose(fs);
+
+    if (readBytes > 0) {
+        *size = static_cast<uint32_t>(readBytes);
+        return MC_DRV_OK;
+    } else {
+        LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreSp(mcSpid_t spid, const void *so, size_t size)
+{
+    int res = 0;
+    if ((spid == 0) || (so == NULL) || size > 3 * MAX_SO_CONT_SIZE) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    const std::string &spContFilePath = getSpContFilePath(spid);
+    LOG_D("store SP: %s", spContFilePath.c_str());
+
+    FILE *fs = fopen(spContFilePath.c_str(), "wb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fwrite(so, 1, size, fs);
+    if (ferror(fs)) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        fclose(fs);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fflush(fs);
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadSp(mcSpid_t spid, void *so, uint32_t *size)
+{
+    const std::string &spContFilePath = getSpContFilePath(spid);
+    size_t readBytes;
+    if ((spid == 0) || (so == NULL)) {
+        LOG_E("mcRegistry read So.Sp(SpId=0x%x) failed", spid);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    LOG_D(" Reading %s", spContFilePath.c_str());
+
+    FILE *fs = fopen(spContFilePath.c_str(), "rb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    readBytes = fread(so, 1, *size, fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fclose(fs);
+
+    if (readBytes > 0) {
+        *size = static_cast<uint32_t>(readBytes);
+        return MC_DRV_OK;
+    } else {
+        LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, const void *so, size_t size)
+{
+    int res = 0;
+    if ((uuid == NULL) || (so == NULL) || size > 3 * MAX_SO_CONT_SIZE) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    const std::string &tlContFilePath = getTlContFilePath(uuid, spid);
+    LOG_D("store TLc: %s", tlContFilePath.c_str());
+
+    FILE *fs = fopen(tlContFilePath.c_str(), "wb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fwrite(so, 1, size, fs);
+    if (ferror(fs)) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        fclose(fs);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fflush(fs);
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+static uint32_t getAsUint32BE(
+    const void *pValueUnaligned
+)
+{
+    auto p = static_cast<const uint8_t *>(pValueUnaligned);
+    uint32_t val = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24);
+    return val;
+}
+
+mcResult_t mcRegistryStoreTABlob(mcSpid_t spid, const void *blob, size_t size)
+{
+    int res = 0;
+    LOG_D("mcRegistryStoreTABlob started");
+
+    // Check blob size
+    if (size < sizeof(mclfHeaderV24_t)) {
+        LOG_E("RegistryStoreTABlob failed - TA blob length is less then header size");
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    auto header24 = reinterpret_cast<const mclfHeaderV24_t *>(blob);
+    auto header20 = reinterpret_cast<const mclfHeaderV2_t *>(blob);
+
+    // Check header version
+    if (header20->intro.version < MC_MAKE_VERSION(2, 4)) {
+        LOG_E("RegistryStoreTABlob failed - TA blob header version is less than 2.4");
+        return MC_DRV_ERR_TA_HEADER_ERROR;
+    }
+
+    //Check GP version
+    if (header24->gp_level != 1) {
+        LOG_E("RegistryStoreTABlob failed - TA blob header gp_level is not equal to 1");
+        return MC_DRV_ERR_TA_HEADER_ERROR;
+    }
+
+    mcUuid_t uuid;
+    switch (header20->serviceType) {
+    case SERVICE_TYPE_SYSTEM_TRUSTLET: {
+        // Check spid
+        if (spid != MC_SPID_SYSTEM) {
+            LOG_E("RegistryStoreTABlob failed - SPID is not equal to %d for System TA", spid);
+            return MC_DRV_ERR_INVALID_PARAMETER;
+        }
+        memcpy(&uuid, &header20->uuid, sizeof(mcUuid_t));
+        break;
+    }
+    case SERVICE_TYPE_SP_TRUSTLET: {
+        // Check spid
+        if (spid >= MC_SPID_SYSTEM) {
+            LOG_E("RegistryStoreTABlob failed - SPID is equal to %u ", spid);
+            return MC_DRV_ERR_INVALID_PARAMETER;
+        }
+
+        auto pUa = reinterpret_cast<const uuid_attestation*>(&static_cast<const uint8_t*>(blob)[header24->attestationOffset]);
+        // Check attestation size
+        if ((header24->attestationOffset > size) && (header24->attestationOffset + getAsUint32BE(&pUa->size) > size)) {
+            LOG_E("RegistryStoreTABlob failed - Attestation size is not correct");
+            return MC_DRV_ERR_TA_HEADER_ERROR;
+        }
+
+        // Check attestation size
+        if (getAsUint32BE(&pUa->size) < sizeof(uuid_attestation)) {
+            LOG_E("RegistryStoreTABlob failed - Attestation size is equal to %d and is less then %zu", getAsUint32BE(&pUa->size), sizeof(uuid_attestation));
+            return MC_DRV_ERR_TA_ATTESTATION_ERROR;
+        }
+
+        // Check magic word
+        if (memcmp(pUa->magic, MAGIC, AT_MAGIC_SIZE)) {
+            LOG_E("RegistryStoreTABlob failed - Attestation magic word is not correct");
+            return MC_DRV_ERR_TA_ATTESTATION_ERROR;
+        }
+
+        // Check version
+        if (getAsUint32BE(&pUa->version) != AT_VERSION) {
+            LOG_E("RegistryStoreTABlob failed - Attestation version is equal to %08X. It has to be equal to %08X", getAsUint32BE(&pUa->version), AT_VERSION);
+            return MC_DRV_ERR_TA_ATTESTATION_ERROR;
+        }
+
+        memcpy(&uuid, &pUa->uuid, sizeof(mcUuid_t));
+        break;
+    }
+    default: {
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    }
+    const std::string taBinFilePath = getTABinFilePath(&uuid, MC_REGISTRY_WRITABLE);
+
+    LOG_D("Store TA blob at: %s", taBinFilePath.c_str());
+
+    FILE *fs = fopen(taBinFilePath.c_str(), "wb");
+    if (fs==NULL) {
+        LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fwrite(blob, 1, size, fs);
+    if (ferror(fs)) {
+        LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        fclose(fs);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fflush(fs);
+    fclose(fs);
+
+    if (header20->serviceType == SERVICE_TYPE_SP_TRUSTLET) {
+        const std::string taspidFilePath = getTASpidFilePath(&uuid, MC_REGISTRY_WRITABLE);
+
+        LOG_D("Store spid file at: %s", taspidFilePath.c_str());
+
+        FILE *fs = fopen(taspidFilePath.c_str(), "wb");
+        if (fs==NULL) {
+            LOG_E("RegistryStoreTABlob failed - TA blob file open error: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+            return MC_DRV_ERR_INVALID_DEVICE_FILE;
+        }
+        res = fseek(fs, 0, SEEK_SET);
+        if (res!=0) {
+            LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+            fclose(fs);
+            return MC_DRV_ERR_INVALID_PARAMETER;
+        }
+        fwrite(&spid, 1, sizeof(mcSpid_t), fs);
+        if (ferror(fs)) {
+            LOG_E("RegistryStoreTABlob failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+            fclose(fs);
+            return MC_DRV_ERR_OUT_OF_RESOURCES;
+        }
+        fflush(fs);
+        fclose(fs);
+    }
+    return MC_DRV_OK;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t *size)
+{
+    int res = 0;
+    if ((uuid == NULL) || (so == NULL)) {
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    size_t readBytes;
+    const std::string &tlContFilePath = getTlContFilePath(uuid, spid);
+    LOG_D("read TLc: %s", tlContFilePath.c_str());
+
+    FILE *fs = fopen(tlContFilePath.c_str(), "rb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    readBytes = fread(so, 1, *size, fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fclose(fs);
+
+    if (readBytes > 0) {
+        *size = static_cast<uint32_t>(readBytes);
+        return MC_DRV_OK;
+    } else {
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreData(const void *so, size_t size)
+{
+    const mcSoDataCont_t *dataCont = reinterpret_cast<const mcSoDataCont_t*>(so);
+    int res = 0;
+
+    if (dataCont == NULL || size != sizeof(mcSoDataCont_t)) {
+        LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    std::string pathname, filename;
+
+    switch (dataCont->cont.type) {
+    case CONT_TYPE_SPDATA:
+        LOG_E("SPDATA not supported");
+        return MC_DRV_ERR_INVALID_PARAMETER;
+        break;
+    case CONT_TYPE_TLDATA:
+        pathname = getTlDataPath(&dataCont->cont.uuid);
+        filename = getTlDataFilePath(&dataCont->cont.uuid, dataCont->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;
+    }
+    if (mkdir(pathname.c_str(), 0777) < 0)
+    {
+        LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    LOG_D("store DT: %s", filename.c_str());
+
+    FILE *fs = fopen(filename.c_str(), "wb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fwrite(dataCont, 1, MC_SO_SIZE(dataCont->soHeader.plainLen, dataCont->soHeader.encryptedLen), fs);
+    if (ferror(fs)) {
+        LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        fclose(fs);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fflush(fs);
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadData(uint32_t context, const mcCid_t *cid, mcPid_t,
+                              mcSoDataCont_t *so, uint32_t maxLen)
+{
+    int res = 0;
+
+    if ((NULL == cid) || (NULL == so)) {
+        LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    std::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_D("read DT: %s", filename.c_str());
+
+    FILE *fs = fopen(filename.c_str(), "rb");
+    if (fs==NULL) {
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    res = fseek(fs, 0, SEEK_END);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    long filesize = ftell(fs);
+    if (static_cast<long>(maxLen) < filesize) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    res = fseek(fs, 0, SEEK_SET);
+    if (res!=0) {
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    char *p = reinterpret_cast<char*>(so);
+    size_t read_res = fread(p, 1, sizeof(mcSoHeader_t), fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if (read_res<sizeof(mcSoHeader_t)) {
+        //File is shorter than expected
+        if (feof(fs)) {
+            LOG_E("%s(): EOF reached: res is %zu, size of mcSoHeader_t is %zu", __func__, read_res, sizeof(mcSoHeader_t));
+        }
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    p += sizeof(mcSoHeader_t);
+    read_res = fread(p, 1, MC_SO_SIZE(so->soHeader.plainLen,
+                so->soHeader.encryptedLen)
+                - sizeof(mcSoHeader_t), fs);
+    if (ferror(fs)) {
+        fclose(fs);
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if (read_res<(MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t))) {
+        //File is shorter than expected
+        if (feof(fs)) {
+            LOG_E("%s(): EOF reached: res is %zu, size of secure object is %zu", __func__, read_res,
+            MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t));
+        }
+        fclose(fs);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    fclose(fs);
+
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+static uint32_t getFileContent(
+    const char *pPath,
+    uint8_t **ppContent)
+{
+    FILE   *pStream;
+    long    filesize;
+    uint8_t *content = NULL;
+    size_t res = 0;
+
+    /* Open the file */
+    pStream = fopen(pPath, "rb");
+    if (pStream == NULL) {
+        LOG_E("Error: Cannot open file: %s.", pPath);
+        return 0;
+    }
+
+    if (fseek(pStream, 0L, SEEK_END) != 0) {
+        LOG_E("Error: Cannot read file: %s.", pPath);
+        goto error;
+    }
+
+    filesize = ftell(pStream);
+    if (filesize < 0) {
+        LOG_E("Error: Cannot get the file size: %s.", pPath);
+        goto error;
+    }
+
+    if (filesize == 0) {
+        LOG_E("Error: Empty file: %s.", pPath);
+        goto error;
+    }
+
+    /* Set the file pointer at the beginning of the file */
+    if (fseek(pStream, 0L, SEEK_SET) != 0) {
+        LOG_E("Error: Cannot read file: %s.", pPath);
+        goto error;
+    }
+
+    /* Allocate a buffer for the content */
+    content = new uint8_t[filesize];
+    if (content == NULL) {
+        LOG_E("Error: Cannot read file: Out of memory.");
+        goto error;
+    }
+
+    /* Read data from the file into the buffer */
+    res = fread(content, filesize, 1, pStream);
+    if (ferror(pStream)) {
+        LOG_E("Error: Cannot read file: %s.", pPath);
+        goto error;
+    }
+    if (res < 1) {
+        //File is shorter than expected
+        if (feof(pStream)) {
+            LOG_E("Error: EOF reached: %s.", pPath);
+        }
+        goto error;
+    }
+
+    /* Close the file */
+    fclose(pStream);
+    *ppContent = content;
+
+    /* Return number of bytes read */
+    return static_cast<uint32_t>(filesize);
+
+error:
+    if (content != NULL) {
+        delete[] content;
+    }
+    fclose(pStream);
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+static bool mcCheckUuid(const mcUuid_t *uuid, const char *filename)
+{
+    uint8_t    *pTAData = NULL;
+    uint32_t    nTASize;
+    bool        res;
+
+    nTASize = getFileContent(filename, &pTAData);
+    if (nTASize == 0) {
+        LOG_E("err: Trusted Application not found.");
+        return false;
+    }
+
+    // Check blob size
+    if (nTASize < sizeof(mclfHeaderV24_t)) {
+        delete[] pTAData;
+        LOG_E("getFileContent failed - TA length is less than header size");
+        return false;
+    }
+
+    mclfHeaderV2_t *header20 = reinterpret_cast<mclfHeaderV2_t *>(pTAData);
+
+    // Check header version
+    if (header20->intro.version < MC_MAKE_VERSION(2, 4)) {
+        delete[] pTAData;
+        LOG_E("mcCheckUuid() - TA blob header version is less than 2.4");
+        return false;
+    }
+
+    // Check uuid
+    if (memcmp(uuid, &header20->uuid, sizeof(mcUuid_t)) == 0) {
+        res = true;
+    } else {
+        res = false;
+    }
+
+    delete[] pTAData;
+
+    return res;
+}
+
+//this function deletes all the files owned by a GP TA and stored in the tbase secure storage dir.
+//then it deletes GP TA folder.
+static int CleanupGPTAStorage(const char *uuid)
+{
+       DIR            *dp;
+       struct dirent  *de;
+       int             e;
+       std::string TAPath = getTbStoragePath() + "/" + uuid;
+       if (NULL != (dp = opendir(TAPath.c_str()))) {
+               while (NULL != (de = readdir(dp))) {
+                       if (de->d_name[0] != '.') {
+                               std::string dname = TAPath + "/" + std::string(de->d_name);
+                               LOG_D("delete DT: %s", dname.c_str());
+                               if (0 != (e = remove(dname.c_str()))) {
+                                       LOG_E("remove UUID-files %s failed! error: %d", dname.c_str(), e);
+                               }
+                       }
+               }
+               if (dp) {
+                       closedir(dp);
+               }
+               LOG_D("delete dir: %s", TAPath.c_str());
+               if (0 != (e = rmdir(TAPath.c_str()))) {
+                       LOG_E("remove UUID-dir failed! errno: %d", e);
+                       return e;
+               }
+       }
+       return MC_DRV_OK;
+}
+
+
+mcResult_t mcRegistryCleanupGPTAStorage(const mcUuid_t *uuid)
+{
+    return CleanupGPTAStorage(byteArrayToString(uuid, sizeof(*uuid)).c_str());
+}
+
+static void deleteSPTA(const mcUuid_t *uuid, const mcSpid_t spid)
+{
+    DIR            *dp;
+    struct dirent  *de;
+    int             e;
+
+    // Delete TABIN and SPID files - we loop searching required spid file
+    if (NULL != (dp = opendir(search_paths[0].c_str()))) {
+        while (NULL != (de = readdir(dp))) {
+            std::string spidFile;
+            std::string tabinFile;
+            std::string tabinUuid;
+            size_t pch_dot, pch_slash;
+            spidFile = search_paths[0] + "/" + std::string(de->d_name);
+            pch_dot = spidFile.find_last_of('.');
+            if (pch_dot == std::string::npos) continue;
+            pch_slash = spidFile.find_last_of('/');
+            if ((pch_slash != std::string::npos) && (pch_slash > pch_dot))  continue;
+            if (spidFile.substr(pch_dot).compare(GP_TA_SPID_FILE_EXT) != 0) continue;
+
+            mcSpid_t curSpid = 0;
+
+            int fd = open(spidFile.c_str(), O_RDONLY);
+            if (fd != -1) {
+                if (read(fd, &curSpid, sizeof(mcSpid_t))!=sizeof(mcSpid_t)) {
+                    curSpid = 0;
+                }
+                close(fd);
+            }
+            if (spid == curSpid) {
+                tabinFile =  spidFile.substr(0, pch_dot) + GP_TA_BIN_FILE_EXT;
+                if (mcCheckUuid(uuid, tabinFile.c_str())) {
+                       tabinUuid = spidFile.substr(0, pch_dot);
+                       tabinUuid = tabinUuid.substr(tabinUuid.find_last_of('/')+1);
+                       LOG_D("Remove TA storage %s", tabinUuid.c_str());
+                       if (0 != (e = CleanupGPTAStorage(tabinUuid.c_str()))){
+                               LOG_E("Remove TA storage failed! errno: %d", e);
+                               /* Discard error */
+                       }
+                       LOG_D("Remove TA file %s", tabinFile.c_str());
+                    if (0 != (e = remove(tabinFile.c_str()))) {
+                        LOG_E("Remove TA file failed! errno: %d", e);
+                        /* Discard error */
+                    }
+                    LOG_D("Remove spid file %s", spidFile.c_str());
+                    if (0 != (e = remove(spidFile.c_str()))) {
+                        LOG_E("Remove spid file failed! errno: %d", e);
+                        /* Discard error */
+                    }
+                    break;
+                }
+            }
+        }
+        if (dp) {
+            closedir(dp);
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid, const mcSpid_t spid)
+{
+    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;
+    }
+
+    // Delete all TA related data
+    std::string pathname = getTlDataPath(uuid);
+    if (NULL != (dp = opendir(pathname.c_str()))) {
+        while (NULL != (de = readdir(dp))) {
+            if (de->d_name[0] != '.') {
+                std::string dname = pathname + "/" + std::string(de->d_name);
+                LOG_D("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);
+                }
+            }
+        }
+        if (dp) {
+            closedir(dp);
+        }
+        LOG_D("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;
+        }
+    }
+
+    std::string tlBinFilePath = getTlBinFilePath(uuid, MC_REGISTRY_WRITABLE);
+    struct stat tmp;
+    std::string tlContFilePath = getTlContFilePath(uuid, spid);;
+
+    if (stat(tlBinFilePath.c_str(), &tmp) == 0) {
+        /* Legacy TA */
+        LOG_D("Remove TA file %s", tlBinFilePath.c_str());
+        if (0 != (e = remove(tlBinFilePath.c_str()))) {
+            LOG_E("Remove TA file failed! errno: %d", e);
+        }
+    } else {
+        /* GP TA */
+        deleteSPTA(uuid, spid);
+    }
+
+    LOG_D("Remove TA container %s", tlContFilePath.c_str());
+    if (0 != (e = remove(tlContFilePath.c_str()))) {
+        LOG_E("Remove TA container failed! errno: %d", e);
+        return MC_DRV_ERR_UNKNOWN;
+    }
+
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupSp(mcSpid_t spid)
+{
+    DIR *dp;
+    struct dirent  *de;
+    mcResult_t ret;
+    mcSoSpCont_t data;
+    uint32_t i, len;
+    int e;
+
+    if (0 == spid) {
+        LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    len = sizeof(mcSoSpCont_t);
+    ret = mcRegistryReadSp(spid, &data, &len);
+    if (MC_DRV_OK != ret || len != sizeof(mcSoSpCont_t)) {
+        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(reinterpret_cast<const char*>(&data.cont.children[i]),
+                         reinterpret_cast<const char*>(&MC_UUID_FREE),
+                         sizeof(mcUuid_t))) {
+            ret = mcRegistryCleanupTrustlet(&(data.cont.children[i]), spid);
+        }
+    }
+    if (MC_DRV_OK != ret) {
+        LOG_E("delete SP->UUID failed! Return code: %d", ret);
+        return ret;
+    }
+
+    std::string pathname = getSpDataPath(spid);
+
+    if (NULL != (dp = opendir(pathname.c_str()))) {
+        while (NULL != (de = readdir(dp))) {
+            if (de->d_name[0] != '.') {
+                std::string dname = pathname + "/" + std::string(de->d_name);
+                LOG_D("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);
+                }
+            }
+        }
+        if (dp) {
+            closedir(dp);
+        }
+        LOG_D("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;
+        }
+    }
+    std::string spContFilePath = getSpContFilePath(spid);
+    LOG_D("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, len;
+    int e;
+    len = sizeof(mcSoRootCont_t);
+    ret = mcRegistryReadRoot(&data, &len);
+    if (MC_DRV_OK != ret || len != sizeof(mcSoRootCont_t)) {
+        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;
+            }
+        }
+    }
+
+    std::string rootContFilePath = getRootContFilePath();
+    LOG_D("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;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryGetTrustletInfo(const mcUuid_t *uuid, bool isGpUuid, mcSpid_t *spid, std::string& path)
+{
+    // Ensure that a UUID is provided.
+    if (NULL == uuid) {
+        LOG_E("No UUID given");
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    if (isGpUuid) {
+        path = getTABinFilePath(uuid, MC_REGISTRY_ALL);
+    } else {
+        path = getTlBinFilePath(uuid, MC_REGISTRY_ALL);
+    }
+
+    *spid = 0;
+    if (isGpUuid) {
+        std::string taspidFilePath = getTASpidFilePath(uuid, MC_REGISTRY_ALL);
+        int fd = open(taspidFilePath.c_str(), O_RDONLY);
+        if (fd >= 0) {
+            bool failed = read(fd, spid, sizeof(*spid)) != sizeof(*spid);
+            close(fd);
+            if (failed) {
+                LOG_E("Could not read SPID (%d)", errno);
+                return MC_DRV_ERR_TRUSTLET_NOT_FOUND;
+            }
+        }
+    }
+
+    LOG_D("Returning %s", path.c_str());
+    return MC_DRV_OK;
+}
diff --git a/mobicore/Daemon/src/PrivateRegistry.h b/mobicore/Daemon/src/PrivateRegistry.h
new file mode 100644 (file)
index 0000000..3232d16
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICORE_REGISTRY_H_
+#define MOBICORE_REGISTRY_H_
+
+#include <string>
+#include <vector>
+
+#include "MobiCoreDriverApi.h"
+#include "mcContainer.h"
+#include "MobiCoreDriverCmd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//-----------------------------------------------------------------
+
+    void setSearchPaths(const std::vector<std::string>& paths);
+
+    /** Stores an authentication token in registry.
+     * @param  so Authentication token secure object.
+     * @param size Authentication token secure object size.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreAuthToken(const void *so, size_t size);
+
+    /** 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);
+
+    /** Reads an authentication token backup from registry.
+     * @param[out] so Authentication token secure object.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadAuthTokenBackup(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.
+     * @param size Root container secure object size.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreRoot(const void *so, size_t size);
+
+    /** Reads a root container secure object from the registry.
+     * @param[out] so Root container secure object.
+     * @param[out] size Root container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadRoot(void *so, uint32_t *size);
+
+    /** Stores a service provider container secure object in the registry.
+     * @param spid Service provider ID.
+     * @param so Service provider container secure object.
+     * @param size Service provider container secure object size.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreSp(mcSpid_t spid, const void *so, size_t size);
+
+    /** Reads a service provider container secure object from the registry.
+     * @param spid Service provider ID.
+     * @param[out] so Service provider container secure object.
+     * @param[out] size Service provider container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadSp(mcSpid_t spid, void *so, uint32_t *size);
+
+    /** 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.
+     * @param size Trustlet container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, const void *so, size_t size);
+
+    /** Reads a trustlet container secure object from the registry.
+     * @param uuid Trustlet UUID.
+     * @param spid SPID of the trustlet container
+     * @param[out] so Trustlet container secure object.
+     * @param[out] size Trustlet container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, const mcSpid_t spid, void *so, uint32_t *size);
+
+    /** Deletes a trustlet container secure object and all of its associated data.
+     * @param uuid Trustlet UUID.
+     * @param spid Service provider ID
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid, const mcSpid_t spid);
+
+    /**
+     * mcRegistryCleanupGPTAStorage()
+     *
+     * Removes all associated data of the target UUID. This function is called
+     * by FSD when cleaning up after a TA has been uninstalled.
+     *
+     * @param [in] uuid the UUID of the target TA
+     * @retval MC_DRV_OK if successful, otherwise and error code from mcResult_t
+     */
+    mcResult_t mcRegistryCleanupGPTAStorage(const mcUuid_t *uuid);
+
+    /** Stores a data container secure object in the registry.
+     * @param so Data container secure object.
+     * @param size Data container secure object size
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreData(const void *so, size_t size);
+
+    /** 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
+     * @param isGpUuid UUID is for a GP trustlet
+     * @param[out] spid SPID for secure object.
+     * @param[out] path The trustlet file path.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryGetTrustletInfo(const mcUuid_t *uuid, bool isGpUuid, mcSpid_t *spid, std::string& path);
+
+    /** Stores a Trustlet Application blob in the registry.
+     * @param spid SPID of the trustlet container.
+     * @param blob Trustlet Application blob.
+     * @param size Trustlet Application blob size.
+     * @return MC_DRV_OK if successful, otherwise error code.
+     */
+    mcResult_t mcRegistryStoreTABlob(mcSpid_t spid, const void *blob, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MOBICORE_REGISTRY_H_
+
diff --git a/mobicore/Daemon/src/Registry.cpp b/mobicore/Daemon/src/Registry.cpp
new file mode 100644 (file)
index 0000000..ae7b772
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** Mobicore Driver Registry Interface
+ *
+ * Implements the MobiCore registry interface for the ROOT-PA
+ *
+ * @file
+ * @ingroup MCD_MCDIMPL_DAEMON_REG
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include "log.h"
+
+#include "mcSpid.h"
+#include "MobiCoreRegistry.h"
+#include "MobiCoreDriverCmd.h"
+#include "Connection.h"
+#include "buildTag.h"
+
+static const __attribute__((used)) char* buildtag = MOBICORE_COMPONENT_BUILD_TAG;
+
+#define DAEMON_TIMEOUT  30000
+#define ARRAY_SIZE(a)   (sizeof(a)/sizeof((a)[0]))
+
+struct cmd_t: public CommandHeader
+{
+       cmd_t(const uint32_t c)
+       {
+               id = 0;
+               cmd = c;
+               data_size = 0;
+       }
+};
+
+static
+mcResult_t check_iov(const struct iovec *iov, size_t iovcnt, size_t *pay_size)
+{
+    size_t sz = 0;
+    if(iov == NULL || iov[0].iov_len != sizeof(cmd_t))
+       return MC_DRV_ERR_INVALID_PARAMETER;
+
+    for(size_t i = 0; i < iovcnt; i++) {
+       if(iov[i].iov_base == NULL || iov[i].iov_len == 0)
+           return MC_DRV_ERR_INVALID_PARAMETER;
+       sz += iov[i].iov_len;
+    }
+    *pay_size = sz - iov[0].iov_len;
+    return MC_DRV_OK;
+}
+
+
+static mcResult_t send_cmd_recv_data(struct iovec *out_iov,
+        size_t out_iovcnt, void *rbuff = NULL, uint32_t *rlen = NULL)
+{
+    uint32_t nsegs;
+    ResponseHeader rsp;
+    size_t payload_sz;
+    ssize_t length;
+
+    if( (rbuff == NULL && rlen != NULL) ||
+        (rbuff != NULL && rlen == NULL) ||
+         out_iov == NULL || out_iovcnt == 0) {
+       LOG_E("Invalid buffer length!");
+       return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    memset(&rsp, 0, sizeof(rsp));
+    rsp.result = check_iov(out_iov, out_iovcnt, &payload_sz);
+    if(rsp.result != MC_DRV_OK)
+           return rsp.result;
+
+    struct iovec in_iov[2] = {
+            { &rsp, sizeof(rsp) }
+    };
+
+    if(rbuff != NULL) {
+           nsegs = 2;
+           in_iov[1].iov_base = rbuff;
+           in_iov[1].iov_len  = *rlen;
+    } else {
+           nsegs = 1;
+    }
+
+    cmd_t &cmd = *static_cast<cmd_t *>(out_iov[0].iov_base);
+    cmd.data_size = static_cast<uint32_t>(payload_sz);
+    LOG_D("Sending command %d", cmd.cmd);
+
+    Connection con;
+
+    if (!con.connect(SOCK_PATH)) {
+        LOG_E("Failed to connect to daemon!");
+        return MC_DRV_ERR_DAEMON_SOCKET;
+    }
+
+    if (con.writeMsg(out_iov, static_cast<uint32_t>(out_iovcnt)) <= 0) {
+       LOG_E("Failed to send data to daemon");
+        return MC_DRV_ERR_DAEMON_SOCKET;
+    }
+
+    length = con.readMsg(in_iov, nsegs, DAEMON_TIMEOUT);
+    if (length <= 0) {
+        LOG_E("Failed to get answer from daemon!");
+        return MC_DRV_ERR_DAEMON_SOCKET;
+    }
+    if (length < (ssize_t)sizeof(ResponseHeader)) {
+        LOG_E("Invalid length received from daemon!");
+        return MC_DRV_ERR_DAEMON_SOCKET;
+    }
+    length -= sizeof(ResponseHeader);
+
+    LOG_D("result is %x", rsp.result);
+
+    // Return also the read size
+    if(rsp.result == MC_DRV_OK && rlen != NULL)
+       *rlen = length;
+
+    return rsp.result;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreAuthToken(void *so, uint32_t size)
+{
+    cmd_t cmd(MC_DRV_REG_WRITE_AUTH_TOKEN);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)},
+            {so, size}
+    };
+    LOG_D("execute MC_DRV_REG_WRITE_AUTH_TOKEN");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadAuthToken(void *so, uint32_t *size)
+{
+    cmd_t cmd(MC_DRV_REG_READ_AUTH_TOKEN);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)}
+    };
+    //__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s", MOBICORE_COMPONENT_BUILD_TAG);
+    LOG_D("execute MC_DRV_REG_READ_AUTH_TOKEN");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov), so, size);
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryDeleteAuthToken(void)
+{
+    cmd_t cmd(MC_DRV_REG_DELETE_AUTH_TOKEN);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)}
+    };
+    LOG_D("execute MC_DRV_REG_DELETE_AUTH_TOKEN");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreRoot(void *so, uint32_t size)
+{
+    cmd_t cmd(MC_DRV_REG_WRITE_ROOT_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)},
+            {so, size}
+    };
+    LOG_D("execute MC_DRV_REG_WRITE_ROOT_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadRoot(void *so, uint32_t *size)
+{
+    cmd_t cmd(MC_DRV_REG_READ_ROOT_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)}
+    };
+    LOG_D("execute MC_DRV_REG_READ_ROOT_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov), so, size);
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupRoot(void)
+{
+    cmd_t cmd(MC_DRV_REG_DELETE_ROOT_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)}
+    };
+    LOG_D("execute MC_DRV_REG_DELETE_ROOT_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreSp(mcSpid_t spid, void *so, uint32_t size)
+{
+    cmd_t cmd(MC_DRV_REG_WRITE_SP_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)},
+            {&spid, sizeof(spid)},
+            {so, size}
+    };
+    LOG_D("execute MC_DRV_REG_WRITE_SP_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadSp(mcSpid_t spid, void *so, uint32_t *size)
+{
+    cmd_t cmd(MC_DRV_REG_READ_SP_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)},
+            {&spid, sizeof(spid)}
+    };
+    LOG_D("execute MC_DRV_REG_READ_SP_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov), so, size);
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupSp(mcSpid_t spid)
+{
+    cmd_t cmd(MC_DRV_REG_DELETE_SP_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)},
+            {&spid, sizeof(spid)},
+    };
+    LOG_D("execute MC_DRV_REG_DELETE_SP_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid,
+        mcSpid_t spid, void *so, uint32_t size)
+{
+    cmd_t cmd(MC_DRV_REG_WRITE_TL_CONT);
+    struct iovec iov[] = {
+            {&cmd,  sizeof(cmd)},
+            {const_cast<mcUuid_t *>(uuid),  sizeof(*uuid)},
+            {&spid, sizeof(spid)},
+            {so,    size}
+    };
+    LOG_D("execute MC_DRV_REG_WRITE_TL_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreTABlob(mcSpid_t spid, void *blob, uint32_t size)
+{
+    cmd_t cmd(MC_DRV_REG_STORE_TA_BLOB);
+    struct iovec iov[] = {
+            {&cmd,  sizeof(cmd)},
+            {&spid, sizeof(spid)},
+            {blob,  size}
+    };
+    LOG_D("execute MC_DRV_REG_STORE_TA_BLOB");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, mcSpid_t spid,
+        void *so, uint32_t *size)
+{
+    cmd_t cmd(MC_DRV_REG_READ_TL_CONT);
+    struct iovec iov[] = {
+            {&cmd, sizeof(cmd)},
+            {const_cast<mcUuid_t *>(uuid),  sizeof(*uuid)},
+            {&spid, sizeof(spid)}
+    };
+    LOG_D("execute MC_DRV_REG_READ_TL_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov), so, size);
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid, const mcSpid_t spid)
+{
+    cmd_t cmd(MC_DRV_REG_DELETE_TL_CONT);
+    struct iovec iov[] = {
+            {&cmd,  sizeof(cmd)},
+            {const_cast<mcUuid_t *>(uuid),  sizeof(*uuid)},
+            {const_cast<mcSpid_t *>(&spid), sizeof(spid)},
+    };
+    LOG_D("execute MC_DRV_REG_DELETE_TL_CONT");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupTA(const mcUuid_t *uuid)
+{
+    cmd_t cmd(MC_DRV_REG_DELETE_TA_OBJS);
+    struct iovec iov[] = {
+           {&cmd,  sizeof(cmd)},
+           {const_cast<mcUuid_t *>(uuid),  sizeof(*uuid)},
+    };
+    LOG_D("execute MC_DRV_REG_DELETE_TA_OBJS");
+    return send_cmd_recv_data(iov, ARRAY_SIZE(iov));
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreData(void *, uint32_t)
+{
+    return MC_DRV_ERR_INVALID_PARAMETER;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadData(uint32_t, const mcCid_t *, mcPid_t,
+                              mcSoDataCont_t *, uint32_t)
+{
+    return MC_DRV_ERR_INVALID_PARAMETER;
+}
diff --git a/mobicore/Daemon/src/SecureWorld.cpp b/mobicore/Daemon/src/SecureWorld.cpp
new file mode 100644 (file)
index 0000000..de558e7
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Standard
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fstream>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+// <t-base
+#include "Mci/mcimcp.h"
+#include "mcVersionHelper.h"
+// Logging
+#include <log.h>
+// Driver
+#include "mc_user.h"
+#include "mc_admin.h"
+// Registry
+#include "PrivateRegistry.h"
+// Self
+#include "SecureWorld.h"
+
+MC_CHECK_VERSION(MCDRVMODULEAPI, 2, 1);
+#define MAX_SO_CONT_SIZE 512
+#define CRASHDUMP_PATH "/sys/kernel/debug/trustonic_tee/crashdump"
+
+#define MY_LOG_ERRNO(fmt, ...) \
+    LOG_E("%s: %s " fmt, __func__, strerror(errno), ##__VA_ARGS__)
+
+struct SecureWorld::Impl {
+    int device_fd;
+    uint32_t command_id;
+    bool keep_running;
+    Impl(): device_fd(-1), command_id(0), keep_running(true) {}
+};
+
+SecureWorld::SecureWorld(): pimpl_(new Impl) {}
+
+SecureWorld::~SecureWorld() {
+    delete pimpl_;
+}
+
+static void* getRootContainer(const struct mc_admin_request*,
+                              struct mc_admin_response* response,
+                              bool*) {
+    void* data = ::malloc(MAX_SO_CONT_SIZE);
+    uint32_t length = MAX_SO_CONT_SIZE;
+
+    switch (mcRegistryReadRoot(data, &length)) {
+        case MC_DRV_OK:
+            response->length = length;
+            response->error_no = 0;
+            break;
+        case MC_DRV_ERR_INVALID_PARAMETER:
+            response->error_no = EINVAL;
+            break;
+        case MC_DRV_ERR_INVALID_DEVICE_FILE:
+            response->error_no = ENOENT;
+            break;
+        default:
+            // Some kind of default
+            response->error_no = EPERM;
+    }
+
+    if (response->error_no) {
+        ::free(data);
+        return NULL;
+    }
+
+    LOG_D("Read root container, size: %u", response->length);
+    return data;
+}
+
+static void* getSpContainer(const struct mc_admin_request* request,
+                            struct mc_admin_response* response,
+                            bool*) {
+    void* data = ::malloc(MAX_SO_CONT_SIZE);
+    uint32_t length = MAX_SO_CONT_SIZE;
+
+    switch (mcRegistryReadSp(request->spid, data, &length)) {
+        case MC_DRV_OK:
+            response->length = length;
+            response->error_no = 0;
+            break;
+        case MC_DRV_ERR_INVALID_PARAMETER:
+            response->error_no = EINVAL;
+            break;
+        case MC_DRV_ERR_INVALID_DEVICE_FILE:
+            response->error_no = ENOENT;
+            break;
+        default:
+            // Some kind of default
+            response->error_no = EPERM;
+    }
+
+    if (response->error_no) {
+        ::free(data);
+        return NULL;
+    }
+
+    LOG_D("Read SP container for %u, size: %u", request->spid, response->length);
+    return data;
+}
+
+static void* getTrustletContainer(const struct mc_admin_request* request,
+                                  struct mc_admin_response* response,
+                                  bool*) {
+    void* data = ::malloc(MAX_SO_CONT_SIZE);
+    uint32_t length = MAX_SO_CONT_SIZE;
+
+    const mcUuid_t* uuid = reinterpret_cast<const mcUuid_t*>(&request->uuid);
+    switch (mcRegistryReadTrustletCon(uuid, request->spid, data, &length)) {
+        case MC_DRV_OK:
+            response->length = length;
+            response->error_no = 0;
+            break;
+        case MC_DRV_ERR_INVALID_PARAMETER:
+            response->error_no = EINVAL;
+            break;
+        case MC_DRV_ERR_INVALID_DEVICE_FILE:
+            response->error_no = ENOENT;
+            break;
+        case MC_DRV_ERR_OUT_OF_RESOURCES:
+            response->error_no = ENOMEM;
+            break;
+        default:
+            // Some kind of default
+            response->error_no = EPERM;
+    }
+
+    if (response->error_no) {
+        ::free(data);
+        return NULL;
+    }
+
+    LOG_D("Read trustlet container for %u, size: %u", response->spid, response->length);
+    return data;
+}
+
+static void* mapTrustlet(const char* path, uint32_t* length,
+                         uint32_t* service_type) {
+    int fd = ::open(path, O_RDONLY);
+    if (fd < 0) {
+        LOG_W("Cannot open trustlet %s (%d)", path, errno);
+        return NULL;
+    }
+
+    void* data = NULL;
+    *service_type = SERVICE_TYPE_ILLEGAL;
+    do {
+        struct stat stat;
+        if (::fstat(fd, &stat) < 0) {
+            MY_LOG_ERRNO("getting size for trustlet %s", path);
+            break;
+        }
+
+        data = ::mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+        if (data == MAP_FAILED) {
+            data = NULL;
+            MY_LOG_ERRNO("mapping file to memory");
+            break;
+        }
+
+        /* Give service type to driver so it knows how to allocate and copy */
+        mclfHeaderV2_t* header = static_cast<mclfHeaderV2_t*>(data);
+        *service_type = header->serviceType;
+        *length = static_cast<uint32_t>(stat.st_size);
+    } while (false);
+
+    ::close(fd);
+
+    return data;
+}
+
+static void* getTrustlet(const struct mc_admin_request* request,
+                         struct mc_admin_response* response,
+                         bool* is_mmapped) {
+    *is_mmapped = true;
+    const mcUuid_t* uuid = reinterpret_cast<const mcUuid_t*>(&request->uuid);
+    std::string path;
+
+    mcResult_t res = mcRegistryGetTrustletInfo(uuid, request->is_gp, &response->spid, path);
+    switch (res) {
+        case MC_DRV_OK:
+            response->error_no = 0;
+            break;
+        case MC_DRV_ERR_INVALID_PARAMETER:
+            response->error_no = EINVAL;
+            break;
+        case MC_DRV_ERR_TRUSTLET_NOT_FOUND:
+            response->error_no = ENOENT;
+            break;
+        default:
+            // Some kind of default
+            response->error_no = EPERM;
+    }
+
+    if (response->error_no) {
+        return NULL;
+    }
+
+    void* data = mapTrustlet(path.c_str(), &response->length,
+                             &response->service_type);
+    if (!data) {
+        response->error_no = errno;
+    } else {
+        LOG_D("Read spid %u and mmap'd trustlet from %s, total size: %u", response->spid, path.c_str(), response->length);
+    }
+    return data;
+}
+
+static void* logCrashDump(const struct mc_admin_request*,
+                          struct mc_admin_response* response,
+                          bool*) {
+    std::ifstream crashdump(CRASHDUMP_PATH);
+    if (!crashdump.is_open()) {
+        MY_LOG_ERRNO("opening crash dump");
+        response->error_no = errno;
+        return NULL;
+    }
+
+    LOG_E("<t-base halted. Status dump:");
+    std::string line;
+    while (std::getline(crashdump, line)) {
+        LOG_I("%s", line.c_str());
+    }
+
+    return NULL;
+}
+
+int SecureWorld::open() {
+    pimpl_->device_fd = ::open("/dev/" MC_ADMIN_DEVNODE, O_RDWR);
+    if (pimpl_->device_fd < 0) {
+        MY_LOG_ERRNO("opening admin device");
+        return -1;
+    }
+
+    LOG_D("Check version of <t-base driver");
+    struct mc_admin_driver_info info;
+    if (ioctl(pimpl_->device_fd, MC_ADMIN_IO_GET_INFO, &info) != 0) {
+        LOG_ERRNO("ioctl MC_ADMIN_IO_GET_INFO");
+        ::close(pimpl_->device_fd);
+        return -1;
+    }
+
+    char *errmsg;
+    if (!checkVersionOkMCDRVMODULEAPI(info.drv_version, &errmsg)) {
+        LOG_E("%s", errmsg);
+        ::close(pimpl_->device_fd);
+        return -1;
+    }
+
+    LOG_D("%s", errmsg);
+    pimpl_->command_id = info.initial_cmd_id;
+
+    // We wait 10 times 100ms for the device file to appear
+    int counter = 10;
+    do {
+        struct stat st;
+
+        int ret = ::stat("/dev/" MC_USER_DEVNODE, &st);
+        if (!ret) {
+            break;
+        }
+
+        if (errno != ENOENT) {
+            MY_LOG_ERRNO("stat'ing user device");
+            return -1;
+        }
+
+        /* Device driver didn't appear yet: give some time */
+        usleep(100000);
+    } while (counter--);
+
+    if (counter == 0) {
+        LOG_E("timed out while waiting for user device to appear");
+        return -1;
+    }
+
+    LOG_D("TEE is ready");
+    return 0;
+}
+
+void SecureWorld::close() {
+    ::close(pimpl_->device_fd);
+}
+
+int SecureWorld::loadDriver(const char* path) {
+    struct mc_admin_load_info info;
+    uint32_t service_type;
+
+    void* data = mapTrustlet(path, &info.length, &service_type);
+    if (!data) {
+        return -1;
+    }
+
+    LOG_D("Load secure driver %s of size %d", path, info.length);
+    info.address = reinterpret_cast<uintptr_t>(data);
+    info.spid = 0;
+
+    int ret = ioctl(pimpl_->device_fd, MC_ADMIN_IO_LOAD_DRIVER, &info);
+    if (ret != 0) {
+        LOG_ERRNO("ioctl MC_ADMIN_IO_LOAD_DRIVER");
+    }
+
+    // Free memory occupied by Trustlet data
+    ::munmap(data, info.length);
+    return ret == 0;
+}
+
+int SecureWorld::loadToken(const void *data, uint32_t length) {
+    struct mc_admin_load_info token;
+
+    LOG_D("Load authentication token %p of size %u", data, length);
+    token.address = reinterpret_cast<uintptr_t>(data);
+    token.length = length;
+
+    int rc = ioctl(pimpl_->device_fd, MC_ADMIN_IO_LOAD_TOKEN, &token);
+    if (rc != 0) {
+        LOG_ERRNO("ioctl MC_ADMIN_IO_LOAD_TOKEN");
+        return -1;
+    }
+
+    return 0;
+}
+
+int SecureWorld::LoadCheck(mcSpid_t spid, const void *data, uint32_t length) {
+    struct mc_admin_load_info info;
+
+    LOG_D("Load secure object %p, length %u, spid %x", data, length, spid);
+    info.spid = spid;
+    info.address = reinterpret_cast<uintptr_t>(data);
+    info.length = length;
+
+    int rc = ioctl(pimpl_->device_fd, MC_ADMIN_IO_LOAD_CHECK, &info);
+    if (rc != 0) {
+        LOG_ERRNO("ioctl MC_ADMIN_IO_LOAD_CHECK");
+        return -1;
+    }
+
+    return 0;
+}
+
+int SecureWorld::listen()
+{
+    int rc = 0;
+
+    while (pimpl_->keep_running) {
+        struct mc_admin_request request;
+
+        rc = ioctl(pimpl_->device_fd, MC_ADMIN_IO_GET_DRIVER_REQUEST, &request);
+        if (rc) {
+            if (errno == EINTR) {
+                LOG_D("Giving up on signal");
+            } else {
+                LOG_ERRNO("Getting request from driver");
+            }
+            break;
+        }
+
+        LOG_D("Request %d received (ID %u)", request.command, request.request_id);
+        if (pimpl_->command_id != request.request_id) {
+            LOG_E("Request ID counters are not synchronised (expected %u, got %u)", pimpl_->command_id, request.request_id);
+            break;
+        }
+
+        struct mc_admin_response response;
+        memset(&response, 0, sizeof(response));
+        response.request_id = pimpl_->command_id++;
+        void* response_data = NULL;
+        bool is_mmapped = false; // Response data needs freeing
+        switch (request.command) {
+            case MC_DRV_GET_ROOT_CONTAINER:
+                response_data = getRootContainer(&request, &response, &is_mmapped);
+                break;
+            case MC_DRV_GET_SP_CONTAINER:
+                response_data = getSpContainer(&request, &response, &is_mmapped);
+                break;
+            case MC_DRV_GET_TRUSTLET_CONTAINER:
+                response_data = getTrustletContainer(&request, &response, &is_mmapped);
+                break;
+            case MC_DRV_GET_TRUSTLET:
+                response_data = getTrustlet(&request, &response, &is_mmapped);
+                break;
+            case MC_DRV_SIGNAL_CRASH:
+                logCrashDump(&request, &response, &is_mmapped);
+                break;
+            default:
+                LOG_E("Unknown command");
+                response.error_no = EBADRQC;
+        }
+
+        ssize_t ret = ::write(pimpl_->device_fd, &response, sizeof(response));
+        if (ret != sizeof(response)) {
+            LOG_ERRNO("Sending response to driver");
+            ret = -1;
+        } else if (response.length > 0) {
+            ssize_t expected_length = response.length;
+            ret = ::write(pimpl_->device_fd, response_data, response.length);
+            if (ret != expected_length) {
+                LOG_ERRNO("Sending response data to driver");
+                ret = -1;
+            }
+        }
+
+        if (response_data && is_mmapped) {
+            ::munmap(response_data, response.length);
+        } else {
+            ::free(response_data);
+        }
+    }
+
+    return rc;
+}
+
+void SecureWorld::stopListening() {
+    pimpl_->keep_running = false;
+}
diff --git a/mobicore/Daemon/src/SecureWorld.h b/mobicore/Daemon/src/SecureWorld.h
new file mode 100644 (file)
index 0000000..b42f521
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MOBICORE_SECURE_WORLD_H_
+#define MOBICORE_SECURE_WORLD_H_
+
+#include <memory>
+
+#include <mcSpid.h>
+
+class SecureWorld {
+    struct Impl;
+    Impl* const pimpl_;
+public:
+    SecureWorld();
+    ~SecureWorld();
+    int open();
+    void close();
+    int loadDriver(
+        const char* path);
+    int loadToken(
+        const void* data,
+        uint32_t length);
+    int LoadCheck(
+        mcSpid_t spid,
+        const void *data,
+        uint32_t length);
+    // Does not exit until stopListening() is called
+    int listen();
+    void stopListening();
+};
+
+#endif // MOBICORE_SECURE_WORLD_H_
+
diff --git a/mobicore/Daemon/src/Server.cpp b/mobicore/Daemon/src/Server.cpp
new file mode 100644 (file)
index 0000000..c6e8391
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * Connection server.
+ *
+ * Handles incoming socket connections from registry library clients.
+ */
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <log.h>
+
+#include "Server.h"
+
+const char * const Server::m_server_name = "McDaemon.Server";
+
+class LockGuard {
+    pthread_mutex_t* mutex_;
+public:
+    LockGuard(pthread_mutex_t* mutex): mutex_(mutex) {
+        pthread_mutex_lock(mutex_);
+    }
+    ~LockGuard() {
+        pthread_mutex_unlock(mutex_);
+    }
+};
+
+//------------------------------------------------------------------------------
+Server::Server(ConnectionHandler *handler, const char *localAddr,
+        const int listen_queue_sz) :
+    m_serverSock(-1),
+    m_connectionHandler(handler)
+{
+    // Fill in address structure and bind to socket
+    struct sockaddr_un serverAddr;
+    int sock;
+
+    pthread_mutex_init(&m_close_lock, NULL);
+    if(localAddr == NULL || strlen(localAddr) == 0 || listen_queue_sz <= 0)
+        return;
+
+    LOG_D("Server: start listening on socket %s", localAddr);
+
+    // Open a socket (a UNIX domain stream socket)
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        LOG_ERRNO("Can't open stream socket, because socket");
+        return;
+    }
+
+    serverAddr.sun_family = AF_UNIX;
+    strncpy(serverAddr.sun_path, localAddr, sizeof(serverAddr.sun_path) - 1);
+
+    socklen_t len = static_cast<socklen_t>(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(sock, reinterpret_cast<struct sockaddr*>(&serverAddr), len) == 0) {
+        if (listen(sock, listen_queue_sz) == 0) {
+            m_serverSock = sock;
+            return;
+        }
+        else
+            LOG_ERRNO("listen");
+    } else
+        LOG_ERRNO("Binding to server socket failed, because bind");
+
+    close(sock);
+}
+
+//------------------------------------------------------------------------------
+void Server::run()
+{
+    sigset_t sigmask;
+    sigemptyset(&sigmask);
+    sigaddset(&sigmask, SIGUSR1);
+    pthread_sigmask(SIG_UNBLOCK, &sigmask, NULL);
+
+    LOG_D("Server::run()====");
+
+    while ( valid() && !shouldTerminate() ) {
+        fd_set fdReadSockets;
+
+        // Clear FD for select()
+        FD_ZERO(&fdReadSockets);
+
+        LockGuard lock(&m_close_lock);
+
+        // Select server socket descriptor
+        FD_SET(m_serverSock, &fdReadSockets);
+        int maxSocketDescriptor = m_serverSock;
+
+        // Select socket descriptor of all connections
+        for (auto it = m_peerConnections.begin(); it != m_peerConnections.end(); it++) {
+            auto& conn = *it;
+            int peerSocket = conn->socket();
+            FD_SET(peerSocket, &fdReadSockets);
+            if (peerSocket > maxSocketDescriptor)
+                maxSocketDescriptor = peerSocket;
+        }
+
+        // Wait for activities, select() returns the number of sockets
+        // which require processing
+        LOG_D(" Server: waiting on sockets");
+        int numSockets = select(maxSocketDescriptor + 1,
+                                    &fdReadSockets, NULL, NULL, NULL);
+        // Check if select failed
+        if (numSockets < 0) {
+            int err = errno;
+            if (err == EINTR) {
+                LOG_D("Giving up on signal");
+            } else {
+                LOG_ERRNO("select failed");
+            }
+            continue;
+        }
+
+        // actually, this should not happen.
+        if (0 == numSockets) {
+            LOG_W(" Server: select() returned 0, spurious event?.");
+            continue;
+        }
+
+        LOG_D(" Server: events on %d socket(s).", numSockets);
+
+        // Check if a new client connected to the server socket
+        if (FD_ISSET(m_serverSock, &fdReadSockets)) {
+            LOG_D(" Server: new connection attempt.");
+            numSockets--;
+
+            int clientSock = ::accept(m_serverSock, NULL, NULL);
+            if (clientSock > 0) {
+                Connection *connection = new Connection(clientSock);
+                m_peerConnections.push_back(connection);
+                LOG_D(" Server: new socket connection established and start listening.");
+            } else
+                LOG_ERRNO("accept");
+
+            // 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
+        auto it = m_peerConnections.begin();
+        while ((it != m_peerConnections.end()) && (numSockets > 0)) {
+            Connection *connection = *it;
+
+            if (!FD_ISSET(connection->socket(), &fdReadSockets)) {
+                ++it;
+                continue;
+            }
+
+            numSockets--;
+
+            // the connection will be terminated if command processing
+            // fails
+            if (!m_connectionHandler->handleConnection(*connection)) {
+                LOG_D(" Server: dropping connection.");
+
+                //Inform the driver
+                m_connectionHandler->dropConnection(*connection);
+
+                // Remove connection from list
+                it = m_peerConnections.erase(it);
+                delete connection;
+            } else
+                it++;
+        }
+    }
+
+    stop();
+
+    LOG_D("Exiting Server");
+}
+
+//------------------------------------------------------------------------------
+Server::~Server()
+{
+    LOG_D("Destroying Server object");
+    stop();
+}
+
+void Server::stop()
+{
+        LockGuard lock(&m_close_lock);
+
+       // Destroy all client connections
+       while(!m_peerConnections.empty()) {
+            Connection *c = m_peerConnections.front();
+           m_peerConnections.pop_front();
+           delete c;
+       }
+
+        // Shut down the server socket
+        if(m_serverSock != -1) {
+            close(m_serverSock);
+            m_serverSock = -1;
+        }
+}
diff --git a/mobicore/Daemon/src/Server.h b/mobicore/Daemon/src/Server.h
new file mode 100644 (file)
index 0000000..1d777c7
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SERVER_H_
+#define SERVER_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string>
+#include <cstdio>
+#include <pthread.h>
+
+#include <list>
+
+#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    8
+
+typedef std::list<Connection *>        connectionList_t;
+typedef connectionList_t::iterator     connectionIterator_t;
+
+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, const int listen_queue_sz = LISTEN_QUEUE_LEN);
+
+    /**
+     * Server destructor.
+     * All available connections will be terminated. Resources will be freed.
+     */
+    virtual ~Server();
+
+    /**
+     * Start server and listen for incoming connections.
+     * Implements the central socket server loop.
+     * Incoming connections will be stored.
+     */
+    virtual void run();
+
+    void start()
+    {
+        CThread::start(Server::m_server_name);
+    }
+
+    void stop();
+
+    bool valid() const
+    {
+        return m_serverSock != -1;
+    }
+protected:
+
+    int m_serverSock;
+    /**< Connection handler registered to the server */
+    ConnectionHandler   * const m_connectionHandler;
+
+private:
+    pthread_mutex_t     m_close_lock;
+    connectionList_t    m_peerConnections; /**< Connections to devices */
+    static const char * const m_server_name;
+};
+
+#endif /* SERVER_H_ */
+
diff --git a/mobicore/Daemon/src/buildTag.h b/mobicore/Daemon/src/buildTag.h
new file mode 100644 (file)
index 0000000..d8a4859
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICORE_COMPONENT_BUILD_TAG
+#define MOBICORE_COMPONENT_BUILD_TAG \
+       "t-base-EXYNOS64-Android-310B-V006-20160331_140301_7136"
+#endif
diff --git a/mobicore/Daemon/src/drSecureFS_Api.h b/mobicore/Daemon/src/drSecureFS_Api.h
new file mode 100644 (file)
index 0000000..4541b36
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file   drSecureFS_Api.h
+ * @brief  Contains TCI definitions shared with FSD2 daemon and SPT2 TA
+ *
+ */
+
+#ifndef __DRSFSAPI_H__
+#define __DRSFSAPI_H__
+
+#include "service_delegation_protocol.h"
+
+
+/*
+ *  Driver ID. This is managed by Trustonic
+ */
+#define DRV_STH2_ID 0x0104
+
+/**
+ * Driver UUID. Update accordingly after reserving UUID
+ */
+#define DRV_SFS_UUID { { 0x07, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20 } }
+
+/*
+ * TCI definitions, relayed by SPT2 TA from FSD2 daemon
+ */
+#define EXCHANGE_BUFFER_INSTRUCTIONS_NB     1000
+
+/**
+ * This type indicates the state of the daemon
+ */
+typedef enum {
+    STH2_DAEMON_LISTENING = 0,
+    STH2_DAEMON_PROCESSING = 1,
+} STH2_daemon_state;
+
+/**
+ * TCI message data.
+ */
+typedef struct {
+    /* indicates that the secure driver has sent instructions to the normal world daemon.
+     * This variable is updated in the following ways:
+     *      - Initially set to LISTENING by the daemon before it connects to the secure driver.
+     *      - The secure driver switches the state from LISTENING to PROCESSING when it wants the daemon to process instructions.
+     *      - The daemon switches the state from PROCESSING to LISTENING when it has finished processing the instructions.
+     */
+    STH2_daemon_state               nDaemonState;
+    /* sector size
+     * set initially by the secure world.
+     * In TF: `g_nSectorSize`.
+     */
+    uint32_t                        nSectorSize;
+
+    /* workspace length
+     * set initially by the daemon.
+     * In TF: calculated from the exchange buffer size.
+     */
+    uint32_t                        nWorkspaceLength;
+    /* administrative data
+     * written by the normal world.
+     * In TF: `g_pExchangeBuffer->sAdministrativeData`.
+     */
+    DELEGATION_ADMINISTRATIVE_DATA  sAdministrativeData;
+    /* number of instructions to be executed by the daemon.
+     * Set by the secure world for each command.
+     * In TF: the output `size` of `params[1]`
+     */
+    uint32_t                        nInstructionsBufferSize;
+    /* instruction list
+     * set by the secure world.
+     * In TF: `g_pExchangeBuffer->sInstructions`.
+     */
+    uint32_t                        sInstructions[EXCHANGE_BUFFER_INSTRUCTIONS_NB];
+    /* sectors content, set by either side depending on the instruction.
+     * The workspace size is hard-coded based on the maximum sector size (4096).
+     *  In TF: `g_pExchangeBuffer->sWorkspace'
+     */
+    uint8_t                         sWorkspace[];
+} STH2_delegation_exchange_buffer_t;
+
+
+#endif // __DRSFSAPI_H__
diff --git a/mobicore/Daemon/src/mcVersion.h b/mobicore/Daemon/src/mcVersion.h
new file mode 100644 (file)
index 0000000..a0c3bdd
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DAEMON_VERSION_H_
+#define DAEMON_VERSION_H_
+
+#define DAEMON_VERSION_MAJOR 0
+#define DAEMON_VERSION_MINOR 4
+
+#endif /** DAEMON_VERSION_H_ */
+
diff --git a/mobicore/Daemon/src/mc_admin.h b/mobicore/Daemon/src/mc_admin.h
new file mode 100644 (file)
index 0000000..5c9bf1d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MC_ADMIN_IOCTL_H__
+#define __MC_ADMIN_IOCTL_H__
+
+#include <linux/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MC_ADMIN_DEVNODE "mobicore"
+
+/* Driver/daemon commands */
+enum {
+       /* Command 0 is reserved */
+       MC_DRV_GET_ROOT_CONTAINER = 1,
+       MC_DRV_GET_SP_CONTAINER = 2,
+       MC_DRV_GET_TRUSTLET_CONTAINER = 3,
+       MC_DRV_GET_TRUSTLET = 4,
+       MC_DRV_SIGNAL_CRASH = 5,
+};
+
+/* MobiCore IOCTL magic number */
+#define MC_IOC_MAGIC    'M'
+
+struct mc_admin_request {
+       __u32           request_id;     /* Unique request identifier */
+       __u32           command;        /* Command to daemon */
+       struct mc_uuid_t uuid;          /* UUID of trustlet, if relevant */
+       __u32           is_gp;          /* Whether trustlet is GP */
+       __u32           spid;           /* SPID of trustlet, if relevant */
+};
+
+struct mc_admin_response {
+       __u32           request_id;     /* Unique request identifier */
+       __u32           error_no;       /* Errno from daemon */
+       __u32           spid;           /* SPID of trustlet, if relevant */
+       __u32           service_type;   /* Type of trustlet being returned */
+       __u32           length;         /* Length of data to get */
+       /* Any data follows */
+};
+
+struct mc_admin_driver_info {
+       /* Version, and something else..*/
+       __u32           drv_version;
+       __u32           initial_cmd_id;
+};
+
+struct mc_admin_load_info {
+       __u32           spid;           /* SPID of trustlet, if relevant */
+       __u64           address;        /* Address of the data */
+       __u32           length;         /* Length of data to get */
+};
+
+#define MC_ADMIN_IO_GET_DRIVER_REQUEST \
+       _IOR(MC_IOC_MAGIC, 0, struct mc_admin_request)
+#define MC_ADMIN_IO_GET_INFO  \
+       _IOR(MC_IOC_MAGIC, 1, struct mc_admin_driver_info)
+#define MC_ADMIN_IO_LOAD_DRIVER \
+       _IOW(MC_IOC_MAGIC, 2, struct mc_admin_load_info)
+#define MC_ADMIN_IO_LOAD_TOKEN \
+       _IOW(MC_IOC_MAGIC, 3, struct mc_admin_load_info)
+#define MC_ADMIN_IO_LOAD_CHECK \
+       _IOW(MC_IOC_MAGIC, 4, struct mc_admin_load_info)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MC_ADMIN_IOCTL_H__ */
diff --git a/mobicore/Daemon/src/mc_user.h b/mobicore/Daemon/src/mc_user.h
new file mode 100644 (file)
index 0000000..e8ac3d6
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MC_USER_H_
+#define _MC_USER_H_
+
+#define MCDRVMODULEAPI_VERSION_MAJOR 2
+#define MCDRVMODULEAPI_VERSION_MINOR 10
+
+#include <linux/types.h>
+
+#define MC_USER_DEVNODE                "mobicore-user"
+
+/** Maximum length of MobiCore product ID string. */
+#define MC_PRODUCT_ID_LEN      64
+
+/** Number of buffers that can be mapped at once */
+#define MC_MAP_MAX             4
+
+/** Max length for buffers */
+#define BUFFER_LENGTH_MAX      0x100000
+
+/** Flags for buffers to map (aligned on GP) */
+#define MC_IO_MAP_INPUT                0x1
+#define MC_IO_MAP_OUTPUT       0x2
+#define MC_IO_MAP_INPUT_OUTPUT (MC_IO_MAP_INPUT | MC_IO_MAP_OUTPUT)
+
+/*
+ * Universally Unique Identifier (UUID) according to ISO/IEC 11578.
+ */
+struct mc_uuid_t {
+       __u8            value[16];      /* Value of the UUID. */
+};
+
+/*
+ * GP TA login types.
+ */
+enum mc_login_type {
+       LOGIN_PUBLIC = 0,
+       LOGIN_USER,
+       LOGIN_GROUP,
+       LOGIN_APPLICATION = 4,
+       LOGIN_USER_APPLICATION,
+       LOGIN_GROUP_APPLICATION,
+};
+
+/*
+ * GP TA identity structure.
+ */
+struct mc_identity {
+       enum mc_login_type      login_type;
+       union {
+               __u8            login_data[16];
+               gid_t           gid;            /* Requested group id */
+               struct {
+                       uid_t   euid;
+                       uid_t   ruid;
+               } uid;
+       };
+       pid_t                   pid;            /* Client, when using proxy */
+};
+
+/*
+ * Data exchange structure of the MC_IO_OPEN_SESSION ioctl command.
+ */
+struct mc_ioctl_open_session {
+       struct mc_uuid_t uuid;          /* trustlet uuid */
+       __u32           is_gp_uuid;     /* uuid is for GP TA */
+       __u32           sid;            /* session id (out) */
+       __u64           tci;            /* tci buffer pointer */
+       __u32           tcilen;         /* tci length */
+       struct mc_identity identity;    /* GP TA identity */
+};
+
+/*
+ * Data exchange structure of the MC_IO_OPEN_TRUSTLET ioctl command.
+ */
+struct mc_ioctl_open_trustlet {
+       __u32           sid;            /* session id (out) */
+       __u32           spid;           /* trustlet spid */
+       __u64           buffer;         /* trustlet binary pointer */
+       __u32           tlen;           /* binary length  */
+       __u64           tci;            /* tci buffer pointer */
+       __u32           tcilen;         /* tci length */
+};
+
+/*
+ * Data exchange structure of the MC_IO_WAIT ioctl command.
+ */
+struct mc_ioctl_wait {
+       __u32           sid;            /* session id (in) */
+       __s32           timeout;        /* notification timeout */
+       __u32           partial;        /* for proxy server to retry silently */
+};
+
+/*
+ * Data exchange structure of the MC_IO_ALLOC ioctl command.
+ */
+struct mc_ioctl_alloc {
+       __u32           len;            /* buffer length  */
+       __u32           handle;         /* user handle for the buffer (out) */
+};
+
+/*
+ * Buffer mapping incoming and outgoing information.
+ */
+struct mc_ioctl_buffer {
+       __u64           va;             /* user space address of buffer */
+       __u32           len;            /* buffer length  */
+       __u64           sva;            /* SWd virt address of buffer (out) */
+       __u32           flags;          /* buffer flags  */
+};
+
+/*
+ * Data exchange structure of the MC_IO_MAP and MC_IO_UNMAP ioctl commands.
+ */
+struct mc_ioctl_map {
+       __u32           sid;            /* session id */
+       struct mc_ioctl_buffer bufs[MC_MAP_MAX]; /* buffers info */
+};
+
+/*
+ * Data exchange structure of the MC_IO_ERR ioctl command.
+ */
+struct mc_ioctl_geterr {
+       __u32           sid;            /* session id */
+       __s32           value;          /* error value (out) */
+};
+
+/*
+ * Global MobiCore Version Information.
+ */
+struct mc_version_info {
+       char product_id[MC_PRODUCT_ID_LEN]; /** Product ID string */
+       __u32 version_mci;              /** Mobicore Control Interface */
+       __u32 version_so;               /** Secure Objects */
+       __u32 version_mclf;             /** MobiCore Load Format */
+       __u32 version_container;        /** MobiCore Container Format */
+       __u32 version_mc_config;        /** MobiCore Config. Block Format */
+       __u32 version_tl_api;           /** MobiCore Trustlet API */
+       __u32 version_dr_api;           /** MobiCore Driver API */
+       __u32 version_nwd;              /** This Driver */
+};
+
+/*
+ * defines for the ioctl mobicore driver module function call from user space.
+ */
+/* MobiCore IOCTL magic number */
+#define MC_IOC_MAGIC   'M'
+
+/*
+ * Implement corresponding functions from user api
+ */
+#define MC_IO_OPEN_SESSION     \
+       _IOWR(MC_IOC_MAGIC, 0, struct mc_ioctl_open_session)
+#define MC_IO_OPEN_TRUSTLET    \
+       _IOWR(MC_IOC_MAGIC, 1, struct mc_ioctl_open_trustlet)
+#define MC_IO_CLOSE_SESSION    _IO(MC_IOC_MAGIC, 2)
+#define MC_IO_NOTIFY           _IO(MC_IOC_MAGIC, 3)
+#define MC_IO_WAIT             _IOW(MC_IOC_MAGIC, 4, struct mc_ioctl_wait)
+#define MC_IO_MAP              _IOWR(MC_IOC_MAGIC, 5, struct mc_ioctl_map)
+#define MC_IO_UNMAP            _IOW(MC_IOC_MAGIC, 6, struct mc_ioctl_map)
+#define MC_IO_ERR              _IOWR(MC_IOC_MAGIC, 7, struct mc_ioctl_geterr)
+#define MC_IO_HAS_SESSIONS     _IO(MC_IOC_MAGIC, 8)
+#define MC_IO_VERSION          _IOR(MC_IOC_MAGIC, 9, struct mc_version_info)
+
+#endif /* _MC_USER_H_ */
diff --git a/mobicore/Daemon/src/service_delegation_protocol.h b/mobicore/Daemon/src/service_delegation_protocol.h
new file mode 100644 (file)
index 0000000..123662e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file   service_delegation_protocol.h
+ * @brief  Delegation protocol definitions
+ *
+ */
+
+#ifndef __SERVICE_DELEGATION_PROTOCOL_H__
+#define __SERVICE_DELEGATION_PROTOCOL_H__
+
+
+
+/* Instruction codes */
+#define DELEGATION_INSTRUCTION_SHUTDOWN             0xF0
+#define DELEGATION_INSTRUCTION_NOTIFY               0xE0
+
+/* Partition-specific instruction codes (high-nibble encodes the partition identifier) */
+#define DELEGATION_INSTRUCTION_PARTITION_CREATE     0x01
+#define DELEGATION_INSTRUCTION_PARTITION_OPEN       0x02
+#define DELEGATION_INSTRUCTION_PARTITION_READ       0x03
+#define DELEGATION_INSTRUCTION_PARTITION_WRITE      0x04
+#define DELEGATION_INSTRUCTION_PARTITION_SET_SIZE   0x05
+#define DELEGATION_INSTRUCTION_PARTITION_SYNC       0x06
+#define DELEGATION_INSTRUCTION_PARTITION_CLOSE      0x07
+#define DELEGATION_INSTRUCTION_PARTITION_DESTROY    0x08
+
+#define DELEGATION_NOTIFY_TYPE_ERROR                0x000000E1
+#define DELEGATION_NOTIFY_TYPE_WARNING              0x000000E2
+#define DELEGATION_NOTIFY_TYPE_INFO                 0x000000E3
+#define DELEGATION_NOTIFY_TYPE_DEBUG                0x000000E4
+
+typedef struct
+{
+   uint32_t nInstructionID;
+} DELEGATION_GENERIC_INSTRUCTION;
+
+typedef struct
+{
+   uint32_t nInstructionID;
+   uint32_t nMessageType;
+   uint32_t nMessageSize;
+   char     nMessage[4];
+} DELEGATION_NOTIFY_INSTRUCTION;
+
+typedef struct
+{
+   uint32_t nInstructionID;
+   uint32_t nSectorID;
+   uint32_t nWorkspaceOffset;
+} DELEGATION_RW_INSTRUCTION;
+
+typedef struct
+{
+   uint32_t nInstructionID;
+   uint32_t nNewSize;
+} DELEGATION_SET_SIZE_INSTRUCTION;
+
+typedef union
+{
+   DELEGATION_GENERIC_INSTRUCTION    sGeneric;
+   DELEGATION_NOTIFY_INSTRUCTION     sNotify;
+   DELEGATION_RW_INSTRUCTION         sReadWrite;
+   DELEGATION_SET_SIZE_INSTRUCTION   sSetSize;
+} DELEGATION_INSTRUCTION;
+
+typedef struct
+{
+   uint32_t    nSyncExecuted;
+   uint32_t    nPartitionErrorStates[16];
+   uint32_t    nPartitionOpenSizes[16];
+} DELEGATION_ADMINISTRATIVE_DATA;
+
+#endif /* __SERVICE_DELEGATION_PROTOCOL_H__ */
diff --git a/mobicore/Daemon/src/sfs_error.h b/mobicore/Daemon/src/sfs_error.h
new file mode 100644 (file)
index 0000000..090a7ed
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file   sfs_error.h
+ * @brief  error codes used for levels 0-2
+ *
+ */
+
+#ifndef __SFS_ERROR_H__
+#define __SFS_ERROR_H__
+
+#include "sfs_type.h"
+
+#if defined (DRIVER)
+
+#include "tee_error.h"
+
+/* Existing TEE codes */
+#define S_SUCCESS                       TEE_SUCCESS
+#define S_ERROR_GENERIC                 TEE_ERROR_GENERIC
+#define S_ERROR_CANCEL                  TEE_ERROR_CANCEL
+#define S_ERROR_ACCESS_CONFLICT         TEE_ERROR_ACCESS_CONFLICT
+#define S_ERROR_BAD_PARAMETERS          TEE_ERROR_BAD_PARAMETERS
+#define S_ERROR_BAD_STATE               TEE_ERROR_BAD_STATE
+#define S_ERROR_ITEM_NOT_FOUND          TEE_ERROR_ITEM_NOT_FOUND
+#define S_ERROR_NOT_SUPPORTED           TEE_ERROR_NOT_SUPPORTED
+#define S_ERROR_OUT_OF_MEMORY           TEE_ERROR_OUT_OF_MEMORY
+#define S_ERROR_COMMUNICATION           TEE_ERROR_COMMUNICATION
+#define S_ERROR_SHORT_BUFFER            TEE_ERROR_SHORT_BUFFER
+#define S_ERROR_STORAGE_NO_SPACE        TEE_ERROR_STORAGE_NO_SPACE
+
+/* Implementation-specific errors  */
+#define S_ERROR_STORAGE_ITEM_EXISTS     ((S_RESULT)TEE_TBASE_ERROR_STORAGE_ITEM_EXISTS)
+#define S_ERROR_STORAGE_CORRUPTED       ((S_RESULT)TEE_TBASE_ERROR_STORAGE_CORRUPTED)
+#define S_ERROR_STORAGE_UNREACHABLE     ((S_RESULT)TEE_TBASE_ERROR_STORAGE_UNREACHABLE)
+#define S_ERROR_NO_MORE_HANDLES         ((S_RESULT)TEE_TBASE_ERROR_NO_MORE_HANDLES)
+#define S_ERROR_ITEM_EXISTS             ((S_RESULT)TEE_TBASE_ERROR_ITEM_EXISTS)
+
+#else
+
+#include "tee_client_error.h"
+
+/* Existing TEEC codes */
+#define S_SUCCESS                       TEEC_SUCCESS
+#define S_ERROR_GENERIC                 TEEC_ERROR_GENERIC
+#define S_ERROR_CANCEL                  TEEC_ERROR_CANCEL
+#define S_ERROR_ACCESS_CONFLICT         TEEC_ERROR_ACCESS_CONFLICT
+#define S_ERROR_BAD_PARAMETERS          TEEC_ERROR_BAD_PARAMETERS
+#define S_ERROR_BAD_STATE               TEEC_ERROR_BAD_STATE
+#define S_ERROR_ITEM_NOT_FOUND          TEEC_ERROR_ITEM_NOT_FOUND
+#define S_ERROR_NOT_SUPPORTED           TEEC_ERROR_NOT_SUPPORTED
+#define S_ERROR_OUT_OF_MEMORY           TEEC_ERROR_OUT_OF_MEMORY
+#define S_ERROR_COMMUNICATION           TEEC_ERROR_COMMUNICATION
+#define S_ERROR_SHORT_BUFFER            TEEC_ERROR_SHORT_BUFFER
+#define S_ERROR_STORAGE_NO_SPACE        TEEC_ERROR_STORAGE_NO_SPACE
+
+/* Implementation-specific errors  */
+#define S_ERROR_STORAGE_ITEM_EXISTS     ((S_RESULT)TEEC_TBASE_ERROR_STORAGE_ITEM_EXISTS)
+#define S_ERROR_STORAGE_CORRUPTED       ((S_RESULT)TEEC_TBASE_ERROR_STORAGE_CORRUPTED)
+#define S_ERROR_STORAGE_UNREACHABLE     ((S_RESULT)TEEC_TBASE_ERROR_STORAGE_UNREACHABLE)
+#define S_ERROR_NO_MORE_HANDLES         ((S_RESULT)TEEC_TBASE_ERROR_NO_MORE_HANDLES)
+#define S_ERROR_ITEM_EXISTS             ((S_RESULT)TEEC_TBASE_ERROR_ITEM_EXISTS)
+
+#endif /* #if defined (DRIVER) */
+
+
+#endif //__SFS_ERROR_H__
diff --git a/mobicore/Daemon/src/sfs_type.h b/mobicore/Daemon/src/sfs_type.h
new file mode 100644 (file)
index 0000000..6bfbfa2
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SFS_TYPES_H__
+#define __SFS_TYPES_H__
+
+#if defined (DRIVER)
+#include "tee_type.h"
+#endif
+
+/* These definitions are for common port */
+typedef uint32_t                S_RESULT;
+typedef uint32_t                S_HANDLE;
+typedef S_HANDLE                SM_HANDLE;
+#define S_HANDLE_NULL           ((S_HANDLE)0)
+#define SM_HANDLE_INVALID       S_HANDLE_NULL
+
+/** Definition of an UUID (from RFC 4122 http://www.ietf.org/rfc/rfc4122.txt) */
+typedef struct S_UUID
+{
+   uint32_t timeLow;
+   uint16_t timeMid;
+   uint16_t timeHiAndVersion;
+   uint8_t clockSeqAndNode[8];
+} S_UUID;
+
+/* Static SFS configuration */
+typedef struct
+{
+
+   uint32_t nFileSystemCacheSize;        /* filesystem.cache.size */
+   uint32_t nFileSystemSectorSize;       /* filesystem.sector.size */
+   uint32_t nFileSystemSizeMax;          /* filesystem.size.max in KB */
+}
+SYSTEM_STATIC_CFG;
+
+
+extern SYSTEM_STATIC_CFG g_sSystemStaticCfg;
+
+/**
+ * Return the difference {p1}-{p2} in bytes
+ **/
+#define SPointerDiff(p1, p2)    ((int32_t)(((uint32_t)p1) - ((uint32_t)p2)))
+
+/**
+ * Add an offset of {n} bytes to the pointer {p}
+ **/
+#define SPointerAdd(p, n)       ((void*)(((uint8_t*)(p)) + (int32_t)(n)))
+
+
+#if defined (DRIVER)
+    #include "DrApi/DrApi.h"
+
+/* These definitions are for TDriver port */
+    #define _SLogTrace(...)         drDbgPrintLnf(__VA_ARGS__)
+    #define SLogTrace(...)          drDbgPrintLnf(__VA_ARGS__)
+    #define SLogError(...)          drDbgPrintLnf(__VA_ARGS__)
+    //#define SLogError(...)          drApiPrintLnf(__VA_ARGS__)
+    #define SLogWarning(...)        drDbgPrintLnf(__VA_ARGS__)
+    #define __INCLUDE_DEBUG
+    _EXTERN_C _NORETURN void _doAssert(
+        const char      *expr,
+        const char      *file,
+        const uint32_t  line
+    );
+    #define SAssert(cond) \
+            do{if (!(cond)){_doAssert(NULL,__FILE__, __LINE__);}} while(FALSE)
+
+    _DRAPI_EXTERN_C _DRAPI_NORETURN void drApiExit(uint32_t exitCode);
+    #define SPanic(exitCode)        drApiExit(exitCode)
+
+    #define SMemAllocEx(param,size) drApiMalloc(size,0)
+    #define SMemAlloc(size)         drApiMalloc(size,0)
+    #define SMemFree(ptr)           drApiFree(ptr)
+    #define SMemMove(a,b,c)         memmove(a,b,c)
+    #define SMemCompare(a,b,c)      memcmp(a,b,c)
+    #define SMemFill(a,b,c)         memset(a,b,c)
+    #define SMemRealloc(a, b)       drApiRealloc(a, b)
+
+    #define setError(...)           drDbgPrintLnf(__VA_ARGS__)
+    #define exosTraceError(...)     drDbgPrintLnf(__VA_ARGS__)
+
+    #define Trace(...)              drDbgPrintLnf(__VA_ARGS__)
+
+    #define Error(...)              drDbgPrintLnf(__VA_ARGS__)
+
+#elif defined (TEST_SUITE_NAME)
+/* These definitions are for Test Suite port */
+/* Olivier, this is your part to update */
+    #include <stdlib.h>
+    #include <stdio.h>
+//    #include "ssdi.h"
+
+    #ifndef LOG_TAG
+    #define LOG_TAG "sfs"
+    #endif
+
+    #include <log.h>
+//    #undef LOG_I
+//    #define LOG_I(fmt, args...) DUMMY_FUNCTION()
+
+    #ifdef NDEBUG
+    #define LOG(fmt, args...) DUMMY_FUNCTION()
+    #else
+    #define LOG(...) \
+        (void) fprintf(stdout, __VA_ARGS__); (void) fflush(stdout)
+    #endif
+
+    #define setError(...)           LOG(__VA_ARGS__)
+    #define Trace(...)              LOG(__VA_ARGS__)
+
+#endif /* #if defined (DRIVER) */
+
+#endif //__SFS_TYPES_H__
diff --git a/mobicore/Daemon/src/sth2ProxyApi.h b/mobicore/Daemon/src/sth2ProxyApi.h
new file mode 100644 (file)
index 0000000..e01240f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef STH2_PROXY_API_H_
+#define STH2_PROXY_API_H_
+
+
+#include "drSecureFS_Api.h"
+
+
+/**
+ * Termination codes
+ */
+#define EXIT_ERROR ((uint32_t)(-1))
+
+/**
+ * TA UUID.
+ */
+#define SERVICE_DELEGATION_UUID { { 0x07, 0x05, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20 } }
+
+#endif // STH2_PROXY_API_H_
diff --git a/mobicore/TuiService/Android.mk b/mobicore/TuiService/Android.mk
new file mode 100644 (file)
index 0000000..d1b62b1
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# build TuiService
+#
+
+# ExySp: Choice TUI availability
+#_SUPPORT_TUI := true
+ifdef _SUPPORT_TUI
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Module name (sets name of output binary / library)
+LOCAL_MODULE := libTui
+
+# Add your source files here (relative paths)
+LOCAL_SRC_FILES += \
+       jni/tlcTui.cpp \
+       jni/tlcTuiJni.cpp
+
+# Enable logging to logcat per default
+LOCAL_CFLAGS += -DLOG_ANDROID
+LOCAL_LDLIBS += -llog
+
+# Undefine NDEBUG to enable LOG_D in log
+LOCAL_CFLAGS += -UNDEBUG
+
+# Needed to use Trustonic logging macros
+LOCAL_SHARED_LIBRARIES := libMcClient
+LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JNI_SHARED_LIBRARIES := libTui
+
+LOCAL_PACKAGE_NAME := TuiService
+LOCAL_MODULE_TAGS := debug eng optional
+LOCAL_CERTIFICATE := platform
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard-project.txt
+
+include $(BUILD_PACKAGE)
+
+# =============================================================================
+
+# adding the root folder to the search path appears to make absolute paths
+# work for import-module - lets see how long this works and what surprises
+# future developers get from this.
+$(call import-add-path,/)
+$(call import-module,$(COMP_PATH_MobiCoreClientLib_module))
+endif
diff --git a/mobicore/TuiService/AndroidManifest.xml b/mobicore/TuiService/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..f7de043
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.trustonic.tuiservice"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="23" />
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+    <uses-permission android:name="android.permission.WAKE_LOCK"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/sym_def_app_icon"
+        android:label="@string/app_name"
+        android:theme="@style/Theme.Transparent" >
+
+        <receiver
+            android:name="com.trustonic.tuiservice.TuiServiceAutoStart"
+            android:enabled="true"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED">
+                </action>
+                <category android:name="android.intent.category.DEFAULT">
+                </category>
+            </intent-filter>
+        </receiver>
+
+        <service
+            android:name="com.trustonic.tuiservice.TuiService"
+            android:enabled="true"
+            android:exported="false" >
+        </service>
+
+        <!-- noHistory and excludeFromRecents property are used to remove
+         this activity from the task manager menu -->
+        <activity
+            android:name="com.trustonic.tuiservice.TuiActivity"
+            android:configChanges="orientation|keyboardHidden|screenSize"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait"
+            android:theme="@style/Theme.Transparent"
+            android:noHistory="true"
+            android:excludeFromRecents="true">
+        </activity>
+    </application>
+</manifest>
diff --git a/mobicore/TuiService/NOTICE b/mobicore/TuiService/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/TuiService/ant.properties b/mobicore/TuiService/ant.properties
new file mode 100644 (file)
index 0000000..1ac0097
--- /dev/null
@@ -0,0 +1,12 @@
+out.dir=out
+java.compilerargs="-Xlint:unchecked"
+
+debug.key.store=google_certificate.keystore
+debug.key.alias=platform
+debug.key.store.password=android
+debug.key.alias.password=android
+
+key.store=google_certificate.keystore
+key.alias=platform
+key.store.password=android
+key.alias.password=android
diff --git a/mobicore/TuiService/build.xml b/mobicore/TuiService/build.xml
new file mode 100644 (file)
index 0000000..38cdd9f
--- /dev/null
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="TuiService" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <target name="test" depends="debug">
+    </target>
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+
+
+    <!-- the version tag is set to custom in order to avoid regenerating this file. The file has been modifies to make the project name different from the folder name -->
+    <!-- version-tag: custom -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+</project>
diff --git a/mobicore/TuiService/google_certificate.keystore b/mobicore/TuiService/google_certificate.keystore
new file mode 100644 (file)
index 0000000..759f6d2
Binary files /dev/null and b/mobicore/TuiService/google_certificate.keystore differ
diff --git a/mobicore/TuiService/jni/tlcTui.cpp b/mobicore/TuiService/jni/tlcTui.cpp
new file mode 100644 (file)
index 0000000..966201e
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <jni.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/syscall.h>   /* For SYS_xxx definitions */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "tui_ioctl.h"
+
+#include "tlcTui.h"
+#include "tlcTuiJni.h"
+
+#define LOG_TAG "TlcTui"
+#include "log.h"
+
+/* ------------------------------------------------------------- */
+/* Globals */
+bool testGetEvent = false;
+/* ------------------------------------------------------------- */
+/* Static */
+static pthread_t threadId;
+static int32_t drvFd = -1;
+
+/* ------------------------------------------------------------- */
+/* Static functions */
+static void *mainThread(void *);
+
+/* Functions */
+/* ------------------------------------------------------------- */
+/**
+ * TODO.
+ */
+static void *mainThread(void *) {
+//     int32_t fd;
+//    struct stat st;
+//    uint32_t size;
+//    void *address;
+    uint32_t cmdId;
+
+    LOG_D("mainThread: TlcTui start!");
+
+/* Android APP has no right to load a .ko. It must be loaded prior to starting the app.
+    // Load the k-TLC
+    fd = open("/data/app/tlckTuiPlay.ko", O_RDONLY);
+    if (fd < 0) {
+       LOG_E("mainThread: Could not find k-tlc file!");
+        exit(1);
+    }
+    else {
+               fstat(fd, &st);
+               size = st.st_size;
+               address = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
+       if (syscall(__NR_init_module, address, size, NULL)) {
+               int32_t errsv = errno;
+                       LOG_E("mainThread: Load k-tlc failed with errno %s!", strerror(errsv));
+                       exit(1);
+        }
+        close(fd);
+    }
+*/
+    drvFd = open("/dev/" TUI_DEV_NAME, O_NONBLOCK);
+    if (drvFd < 0) {
+       LOG_E("mainThread: open k-tlc device failed with errno %s.", strerror(errno));
+        exit(1);
+    }
+
+    /* TlcTui main thread loop */
+    for (;;) {
+        /* Wait for a command from the k-TLC*/
+        if (false == tlcWaitCmdFromDriver(&cmdId)) {
+            break;
+        }
+        /* Something has been received, process it. */
+        if (false == tlcProcessCmd(cmdId)) {
+            break;
+        }
+    }
+
+    // Close
+    close(drvFd);
+
+    // close_module() ?
+    return NULL;
+}
+/* ------------------------------------------------------------- */
+bool tlcLaunch(void) {
+
+    bool ret = false;
+    /* Create the TlcTui Main thread */
+    if (pthread_create(&threadId, NULL, &mainThread, NULL) != 0) {
+        LOG_E("tlcLaunch: pthread_create failed!");
+        ret = false;
+    } else {
+        ret = true;
+    }
+
+    return ret;
+}
+
+/* ------------------------------------------------------------- */
+bool tlcWaitCmdFromDriver(uint32_t *pCmdId) {
+    uint32_t cmdId = 0;
+    int ioctlRet = 0;
+
+    /* Wait for ioctl to return from k-tlc with a command ID */
+    /* Loop if ioctl has been interrupted. */
+    do {
+        ioctlRet = ioctl(drvFd, TUI_IO_WAITCMD, &cmdId);
+    } while((EINTR == errno) && (-1 == ioctlRet));
+
+    if (-1 == ioctlRet) {
+        LOG_E("TUI_IO_WAITCMD ioctl failed with errno %s.", strerror(errno));
+        return false;
+    }
+    *pCmdId = cmdId;
+    return true;
+}
+
+/* ------------------------------------------------------------- */
+bool tlcNotifyEvent(uint32_t eventType) {
+
+    if (-1 == ioctl(drvFd, TUI_IO_NOTIFY, eventType)) {
+       LOG_E("TUI_IO_NOTIFY ioctl failed with errno %s.", strerror(errno));
+        return false;
+    }
+
+    return true;
+}
+
+/* ------------------------------------------------------------- */
+bool tlcProcessCmd(uint32_t commandId) {
+    uint32_t ret = TLC_TUI_ERROR;
+    struct tlc_tui_response_t response;
+
+    bool acknowledge = true;
+
+        switch (commandId) {
+            case TLC_TUI_CMD_NONE:
+                LOG_I("tlcProcessCmd: TLC_TUI_CMD_NONE.");
+                acknowledge = false;
+                break;
+
+            case TLC_TUI_CMD_START_ACTIVITY:
+                LOG_D("tlcProcessCmd: TLC_TUI_CMD_START_ACTIVITY.");
+                ret = tlcStartTuiSession();
+                LOG_D("tlcStartTuiSession returned %d", ret);
+                if (ret == TUI_JNI_OK) {
+                    ret = TLC_TUI_OK;
+                } else {
+                    ret = TLC_TUI_ERROR;
+                    acknowledge = false;
+                }
+                break;
+
+            case TLC_TUI_CMD_STOP_ACTIVITY:
+                LOG_D("tlcProcessCmd: TLC_TUI_CMD_STOP_ACTIVITY.");
+                ret = tlcFinishTuiSession();
+                LOG_D("tlcFinishTuiSession returned %d", ret);
+                if (ret == TUI_JNI_OK) {
+                    ret = TLC_TUI_OK;
+                } else {
+                    ret = TLC_TUI_ERROR;
+                }
+                break;
+
+            default:
+                LOG_E("tlcProcessCmd: Unknown command %d", commandId);
+                acknowledge = false;
+                ret = TLC_TUI_ERR_UNKNOWN_CMD;
+                break;
+        }
+
+    // Send command return code to the k-tlc
+    response.id = commandId;
+    response.return_code = ret;
+    if (acknowledge) {
+        if (-1 == ioctl(drvFd, TUI_IO_ACK, &response)) {
+            LOG_E("TUI_IO_ACK ioctl failed with errno %s.", strerror(errno));
+            return false;
+        }
+    }
+
+    LOG_D("tlcProcessCmd: ret = %d", ret);
+    return true;
+}
+
diff --git a/mobicore/TuiService/jni/tlcTui.h b/mobicore/TuiService/jni/tlcTui.h
new file mode 100644 (file)
index 0000000..9089ccb
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TLCTUI_H__
+#define __TLCTUI_H__
+
+bool tlcLaunch(void);
+bool tlcOpen(void);
+bool tlcProcessCmd(uint32_t);
+bool tlcWaitCmdFromDriver(uint32_t *);
+bool tlcNotifyEvent(uint32_t eventType);
+void tlcClose(void);
+
+#endif /* __TLCTUI_H__ */
+
diff --git a/mobicore/TuiService/jni/tlcTuiJni.cpp b/mobicore/TuiService/jni/tlcTuiJni.cpp
new file mode 100644 (file)
index 0000000..9cfc81e
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include <stdint.h>
+#include <jni.h>
+#include <android/log.h>
+
+#include "tui_ioctl.h"
+
+#include "tlcTui.h"
+#include "tlcTuiJni.h"
+
+#define LOG_TAG "TlcTuiJni"
+#include "log.h"
+
+/* See for more help about JNI:
+ * http://java.sun.com/docs/books/jni/html/jniTOC.html
+ * http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html
+ * http://developer.android.com/training/articles/perf-jni.html
+ */
+
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#else
+#define EXTERN_C
+#endif
+
+JNIEnv *gEnv = NULL;
+JavaVM *gVm = NULL;
+jclass gTuiTlcWrapperClass = NULL;
+
+static uint32_t setByteArrayField(const char * field, const void *ptr,
+                                  uint32_t length, jclass cls,
+                                  jobject instance) {
+    jfieldID    fid = NULL; /* store the field ID */
+    jbyteArray  bytearray = NULL;
+
+    LOG_D("setByteArrayField: {%s}, length=%u", field, length);
+    /* Look for the static field in class */
+    fid = gEnv->GetFieldID(cls, field, "[B");
+    if (fid == NULL) {
+        LOG_E("setByteArrayField: cannot find field [%s]", field);
+        return TUI_JNI_ERROR; /* field not found */
+    }
+    bytearray = gEnv->NewByteArray(length); /* TODO : free */
+    if (bytearray == NULL) {
+        LOG_E("setByteArrayField: not enough memory");
+        return TUI_JNI_ERROR; /* out of memory */
+    }
+    gEnv->SetByteArrayRegion(bytearray, (jint)0, (jint)length, (jbyte*)ptr);
+    gEnv->SetObjectField(instance, fid, bytearray);
+    gEnv->DeleteLocalRef(bytearray);
+
+    return TUI_JNI_OK;
+}
+
+uint32_t tlcStartTuiSession(void) {
+
+    uint32_t    nResult = TUI_JNI_ERROR;
+    jmethodID   midStartTuiSession = NULL;
+
+    if (gTuiTlcWrapperClass == NULL) {
+        LOG_E("tlcStartTuiSession: Missing parameter gTuiTlcWrapperClass");
+        nResult = TUI_JNI_ERROR;
+        goto exit;
+    }
+
+    /* Attach the thread to the VM */
+    if (gVm->AttachCurrentThread(&gEnv, 0) != JNI_OK) {
+        LOG_E("tlcStartTuiSession: AttachCurrentThread failed");
+        return 1;
+    }
+
+    if (gEnv != NULL) {
+        /* ------------------------------------------------------------- */
+        /* Get the method ID for startTuiSession */
+        midStartTuiSession = gEnv->GetStaticMethodID(gTuiTlcWrapperClass,
+                                                      "startTuiSession",
+                                                      "()Z");
+        if (midStartTuiSession == NULL) {
+            LOG_E("tlcStartTuiSession: Method startTuiSession not found");
+            nResult = TUI_JNI_ERROR;
+            goto exit;
+        }
+        /* Call startTuiSession */
+        jboolean success = gEnv->CallStaticBooleanMethod(gTuiTlcWrapperClass,
+                                                        midStartTuiSession);
+        /* ------------------------------------------------------------- */
+        if (!success) {
+            LOG_E("tlcStartTuiSession: timeout in activity creation");
+            nResult = TUI_JNI_ERROR;
+            goto exit;
+        }
+        nResult = TUI_JNI_OK;
+    } else {
+        LOG_E("tlcStartTuiSession: gEnv is null!");
+        nResult = TUI_JNI_ERROR;
+        goto exit;
+    }
+
+    exit: if (gEnv != NULL) {
+        if (gEnv->ExceptionCheck()) {
+            LOG_E("tlcStartTuiSession: Java exception");
+            gEnv->ExceptionClear();
+        }
+    } else {
+        LOG_E("tlcStartTuiSession: exit gEnv is NULL");
+    }
+
+    if (gVm->DetachCurrentThread() != 0) {
+        LOG_E("tlcStartTuiSession: DetachCurrentThread failed");
+    }
+    return nResult;
+}
+
+uint32_t tlcFinishTuiSession(void) {
+
+    uint32_t    nResult = TUI_JNI_ERROR;
+    jmethodID   midFinishTuiSession = NULL;
+
+    if (gTuiTlcWrapperClass == NULL) {
+        LOG_E("tlcFinishTuiSession: Missing parameter gTuiTlcWrapperClass");
+        nResult = TUI_JNI_ERROR;
+        goto exit;
+    }
+
+    /* Attach the thread to the VM */
+    if (gVm->AttachCurrentThread(&gEnv, 0) != JNI_OK) {
+        LOG_E("tlcFinishTuiSession: AttachCurrentThread failed");
+        return 1;
+    }
+
+    if (gEnv != NULL) {
+        /* ------------------------------------------------------------- */
+        /* Get the method ID for finishTuiSession */
+        midFinishTuiSession = gEnv->GetStaticMethodID(gTuiTlcWrapperClass,
+                                                       "finishTuiSession",
+                                                       "()V");
+        if (midFinishTuiSession == NULL) {
+            LOG_E("tlcFinishTuiSession: Method finishTuiSession not found");
+            nResult = TUI_JNI_ERROR;
+            goto exit;
+        }
+        /* Call finishTuiSession */
+        gEnv->CallStaticVoidMethod(gTuiTlcWrapperClass, midFinishTuiSession);
+        /* ------------------------------------------------------------- */
+        nResult = TUI_JNI_OK;
+    } else {
+        LOG_E("tlcFinishTuiSession: gEnv is null!");
+        nResult = TUI_JNI_ERROR;
+        goto exit;
+    }
+
+    exit: if (gEnv != NULL) {
+        if (gEnv->ExceptionCheck()) {
+            LOG_E("tlcFinishTuiSession: Java exception");
+            gEnv->ExceptionClear();
+        }
+    } else {
+        LOG_E("tlcFinishTuiSession: exit gEnv is NULL");
+    }
+
+    if (gVm->DetachCurrentThread() != 0) {
+        LOG_E("tlcFinishTuiSession: DetachCurrentThread failed");
+    }
+
+    return nResult;
+}
+
+
+EXTERN_C JNIEXPORT bool JNICALL
+Java_com_trustonic_tuiservice_TuiTlcWrapper_startTlcTui(JNIEnv *env,
+        jobject obj) {
+    (void) env;
+    (void) obj;
+    bool ret = false;
+
+    LOG_D("calling tlcLaunch()");
+    ret = tlcLaunch();
+    if(!ret) {
+        LOG_E("tlcLaunch: failed to start TlcTui!");
+    }
+
+    return ret;
+}
+
+EXTERN_C JNIEXPORT bool JNICALL
+Java_com_trustonic_tuiservice_TuiTlcWrapper_notifyEvent(JNIEnv *env,
+        jobject obj, jint eventType) {
+    (void) env;
+    (void) obj;
+    bool ret = false;
+
+    LOG_D("calling tlcNotifyEvent()");
+    ret = tlcNotifyEvent(eventType);
+    if (!ret) {
+        LOG_E("tlcNotifyEvent: failed to notify an event!");
+    }
+
+    return ret;
+}
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    (void) reserved;
+    JNIEnv  *env = NULL;
+    jclass  TuiTlcWrapperClass = NULL;
+
+    LOG_D("JNI_OnLoad");
+
+    if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) {
+        LOG_E("JNI_OnLoad: GetEnv failed!");
+        return -1;
+    }
+
+    TuiTlcWrapperClass = env->FindClass(
+            "com/trustonic/tuiservice/TuiTlcWrapper");
+    if (TuiTlcWrapperClass == NULL) {
+        LOG_E("JNI_OnLoad: FindClass on class TuiTlcWrapperClass failed!");
+        return -1;
+    }
+
+    LOG_D("JNI_OnLoad: TuiTlcWrapperClass = %p", TuiTlcWrapperClass);
+
+    /* Cache the TlcTuiWrapper class in a global reference */
+    /* Use the cached gTuiTlcWrapperClass.
+     * As we called the AttachCurrentThread to get the java environnement from
+     * a native thread, the FindClass will always fail. This is a ClassLoader issue.
+     * This call (AttachCurrentThread) changes the call stack, so when the FindClass
+     * try to start the class search in the class loader associated with this method,
+     * FindClass find the ClassLoader associated with the a wrong class, so FindClass fails.*/
+    gTuiTlcWrapperClass = (jclass)env->NewGlobalRef(TuiTlcWrapperClass);
+
+    /* Cache the javaVM to get back a JNIEnv reference from native code*/
+    gVm = vm;
+    LOG_D("JNI_OnLoad: gVm = %p vm = %p", gVm, vm);
+
+    return JNI_VERSION_1_6;
+}
+
diff --git a/mobicore/TuiService/jni/tlcTuiJni.h b/mobicore/TuiService/jni/tlcTuiJni.h
new file mode 100644 (file)
index 0000000..40d2e4a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TLCTUIJNI_H__
+#define __TLCTUIJNI_H__
+
+#define TUI_JNI_OK              0
+#define TUI_JNI_ERROR           1
+#define TUI_JNI_ERROR_IN_JAVA   2
+
+uint32_t tlcStartTuiSession(void);
+uint32_t tlcFinishTuiSession(void);
+
+#endif /* __TLCTUIJNI_H__ */
diff --git a/mobicore/TuiService/jni/tui_ioctl.h b/mobicore/TuiService/jni/tui_ioctl.h
new file mode 100644 (file)
index 0000000..3643541
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TUI_IOCTL_H_
+#define TUI_IOCTL_H_
+
+
+
+/* Response header */
+struct tlc_tui_response_t {
+       uint32_t        id;
+       uint32_t        return_code;
+};
+
+/* Command IDs */
+#define TLC_TUI_CMD_NONE                0
+#define TLC_TUI_CMD_START_ACTIVITY      1
+#define TLC_TUI_CMD_STOP_ACTIVITY       2
+
+/* Return codes */
+#define TLC_TUI_OK                  0
+#define TLC_TUI_ERROR               1
+#define TLC_TUI_ERR_UNKNOWN_CMD     2
+
+
+/*
+ * defines for the ioctl TUI driver module function call from user space.
+ */
+#define TUI_DEV_NAME           "t-base-tui"
+
+#define TUI_IO_MAGIC           't'
+
+#define TUI_IO_NOTIFY  _IOW(TUI_IO_MAGIC, 1, uint32_t)
+#define TUI_IO_WAITCMD _IOR(TUI_IO_MAGIC, 2, uint32_t)
+#define TUI_IO_ACK     _IOW(TUI_IO_MAGIC, 3, struct tlc_tui_response_t)
+
+#ifdef INIT_COMPLETION
+#define reinit_completion(x) INIT_COMPLETION(*(x))
+#endif
+
+#endif /* TUI_IOCTL_H_ */
diff --git a/mobicore/TuiService/proguard-project.txt b/mobicore/TuiService/proguard-project.txt
new file mode 100644 (file)
index 0000000..f2fe155
--- /dev/null
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/mobicore/TuiService/project.properties b/mobicore/TuiService/project.properties
new file mode 100644 (file)
index 0000000..4ab1256
--- /dev/null
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
diff --git a/mobicore/TuiService/res/drawable-hdpi/sym_def_app_icon.png b/mobicore/TuiService/res/drawable-hdpi/sym_def_app_icon.png
new file mode 100644 (file)
index 0000000..96a442e
Binary files /dev/null and b/mobicore/TuiService/res/drawable-hdpi/sym_def_app_icon.png differ
diff --git a/mobicore/TuiService/res/drawable-ldpi/sym_def_app_icon.png b/mobicore/TuiService/res/drawable-ldpi/sym_def_app_icon.png
new file mode 100644 (file)
index 0000000..2c205c8
Binary files /dev/null and b/mobicore/TuiService/res/drawable-ldpi/sym_def_app_icon.png differ
diff --git a/mobicore/TuiService/res/drawable-mdpi/sym_def_app_icon.png b/mobicore/TuiService/res/drawable-mdpi/sym_def_app_icon.png
new file mode 100644 (file)
index 0000000..359047d
Binary files /dev/null and b/mobicore/TuiService/res/drawable-mdpi/sym_def_app_icon.png differ
diff --git a/mobicore/TuiService/res/drawable-xhdpi/sym_def_app_icon.png b/mobicore/TuiService/res/drawable-xhdpi/sym_def_app_icon.png
new file mode 100644 (file)
index 0000000..71c6d76
Binary files /dev/null and b/mobicore/TuiService/res/drawable-xhdpi/sym_def_app_icon.png differ
diff --git a/mobicore/TuiService/res/drawable-xxhdpi/sym_def_app_icon.png b/mobicore/TuiService/res/drawable-xxhdpi/sym_def_app_icon.png
new file mode 100644 (file)
index 0000000..20a47a0
Binary files /dev/null and b/mobicore/TuiService/res/drawable-xxhdpi/sym_def_app_icon.png differ
diff --git a/mobicore/TuiService/res/layout/activity_tui.xml b/mobicore/TuiService/res/layout/activity_tui.xml
new file mode 100644 (file)
index 0000000..2a29587
--- /dev/null
@@ -0,0 +1,11 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/tuiLayout"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical"
+    android:gravity="center_vertical|center_horizontal"
+    android:keepScreenOn="true"
+    tools:context=".TuiActivity">
+
+</LinearLayout>
diff --git a/mobicore/TuiService/res/menu/tui_manager.xml b/mobicore/TuiService/res/menu/tui_manager.xml
new file mode 100644 (file)
index 0000000..d227c49
--- /dev/null
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+</menu>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values-v11/styles.xml b/mobicore/TuiService/res/values-v11/styles.xml
new file mode 100644 (file)
index 0000000..5f7ad80
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+    <style name="FullscreenTheme" parent="android:Theme.Holo">
+        <item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
+        <item name="android:windowActionBarOverlay">true</item>
+        <item name="android:windowBackground">@null</item>
+        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
+        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
+    </style>
+
+    <style name="FullscreenActionBarStyle" parent="android:Widget.Holo.ActionBar">
+        <item name="android:background">@color/black_overlay</item>
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values-v14/styles.xml b/mobicore/TuiService/res/values-v14/styles.xml
new file mode 100644 (file)
index 0000000..f20e015
--- /dev/null
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values/attrs.xml b/mobicore/TuiService/res/values/attrs.xml
new file mode 100644 (file)
index 0000000..50e474b
--- /dev/null
@@ -0,0 +1,14 @@
+<resources>
+
+    <!--
+         Declare custom theme attributes that allow changing which styles are
+         used for button bars depending on the API level.
+         ?android:attr/buttonBarStyle is new as of API 11 so this is
+         necessary to support previous API levels.
+    -->
+    <declare-styleable name="ButtonBarContainerTheme">
+        <attr name="buttonBarStyle" format="reference" />
+        <attr name="buttonBarButtonStyle" format="reference" />
+    </declare-styleable>
+
+</resources>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values/colors.xml b/mobicore/TuiService/res/values/colors.xml
new file mode 100644 (file)
index 0000000..5841565
--- /dev/null
@@ -0,0 +1,28 @@
+<resources>
+
+    <color name="black_overlay">#66000000</color>
+    <color name="status">#fafafa</color>
+    <color name="button_off_bgd">#fafafa</color>
+    <color name="button_off_txt">#5b5b5b</color>
+    <color name="button_on_bgd">#5b5b5b</color>
+    <color name="button_on_txt">#fafafa</color>
+    <color name="white">#FFFFFF</color>
+
+    <color 
+        name="trustonic_blue">#00A9E0</color>
+    <color 
+        name="trustonic_light_blue">#81B2D7</color>
+    <color 
+        name="trustonic_dark_blue">#0C6CB1</color>
+    <color 
+        name="trustonic_very_dark_blue">#237AB1</color>
+    <color 
+        name="trustonic_grey">#AAACAB</color>
+    <color 
+        name="trustonic_very_light_grey">#EFEFEF</color>
+    <color 
+        name="trustonic_light_grey">#CFCFCF</color>
+    <color 
+        name="trustonic_dark_grey">#615F5F</color>
+
+</resources>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values/dimens.xml b/mobicore/TuiService/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..dc72173
--- /dev/null
@@ -0,0 +1,12 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+    <!-- ARNDALE board screen size. -->
+    <dimen name="arndale_screen_width">600px</dimen>
+    <dimen name="arndale_screen_height">1024px</dimen>
+    <dimen name="arndale_screen_density">168px</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values/strings.xml b/mobicore/TuiService/res/values/strings.xml
new file mode 100644 (file)
index 0000000..6eb8407
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">tuiService</string>
+    <string name="dummy_button">Dummy Button</string>
+    <string name="dummy_content">DUMMY\nCONTENT</string>
+    <string name="title_activity_tui_manager">TuiManager</string>
+    <string name="action_settings">Settings</string>
+    <string name="button">Start/Stop</string>
+    <string name="tui_manager_start">Start</string>
+    <string name="tui_manager_stop">Stop</string>
+    <string name="tui_enabled">TUI service is running!</string>
+    <string name="tui_disabled">TUI service is not running!</string>
+    <string name="slogan">Secured by Trustonic!</string>
+
+</resources>
\ No newline at end of file
diff --git a/mobicore/TuiService/res/values/styles.xml b/mobicore/TuiService/res/values/styles.xml
new file mode 100644 (file)
index 0000000..1e866d5
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+    <style name="FullscreenTheme" parent="android:Theme.NoTitleBar">
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowBackground">@null</item>
+        <item name="buttonBarStyle">@style/ButtonBar</item>
+        <item name="buttonBarButtonStyle">@style/ButtonBarButton</item>
+    </style>
+
+    <style name="ButtonBar">
+        <item name="android:paddingLeft">2dp</item>
+        <item name="android:paddingTop">5dp</item>
+        <item name="android:paddingRight">2dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:background">@android:drawable/bottom_bar</item>
+    </style>
+
+    <style name="ButtonBarButton" />
+
+    <style name="Theme.Transparent" parent="android:Theme">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:backgroundDimEnabled">false</item>
+    </style>
+</resources>
diff --git a/mobicore/TuiService/src/com/trustonic/tuiapi/TUI_Event.java b/mobicore/TuiService/src/com/trustonic/tuiapi/TUI_Event.java
new file mode 100644 (file)
index 0000000..79c04d6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiapi;
+
+public class TUI_Event {
+    private TUI_EventType type;
+
+    public TUI_Event() {
+        super();
+        this.type = new TUI_EventType(TUI_EventType.TUI_UNKNOW_EVENT);
+    }
+
+    public TUI_Event(int type) {
+        super();
+        this.type = new TUI_EventType(type);
+    }
+
+    public int getType(){
+        return this.type.is();
+    }
+
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiapi/TUI_EventData.java b/mobicore/TuiService/src/com/trustonic/tuiapi/TUI_EventData.java
new file mode 100644 (file)
index 0000000..3351484
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiapi;
+
+public class TUI_EventData {
+
+    public TUI_EventData() {
+        // TODO Auto-generated constructor stub
+    }
+
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiapi/TUI_EventType.java b/mobicore/TuiService/src/com/trustonic/tuiapi/TUI_EventType.java
new file mode 100644 (file)
index 0000000..a10b1b1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiapi;
+
+public class TUI_EventType {
+
+    private int is;
+    public static int TUI_UNKNOW_EVENT = 0;
+    public static int TUI_CANCEL_EVENT = 1;
+
+    public TUI_EventType(int type) {
+        this.is = type;
+    }
+
+    public int is(){
+        return this.is;
+    }
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiservice/BuildTag.java b/mobicore/TuiService/src/com/trustonic/tuiservice/BuildTag.java
new file mode 100644 (file)
index 0000000..5f3f0c8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.trustonic.tuiservice;
+public interface BuildTag {
+    public static final String BUILD_TAG = "t-base-EXYNOS64-Android-310B-V006-20160331_140301_7136";
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiservice/TuiActivity.java b/mobicore/TuiService/src/com/trustonic/tuiservice/TuiActivity.java
new file mode 100644 (file)
index 0000000..dfdc2e5
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiservice;
+
+import com.trustonic.tuiapi.TUI_Event;
+import com.trustonic.tuiapi.TUI_EventType;
+import com.trustonic.util.tLog;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.drawable.BitmapDrawable;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+public class TuiActivity extends Activity {
+
+    private static final String TAG = TuiActivity.class.getSimpleName();
+
+    private LinearLayout mainView;
+    private PerformActionInBackground mTuiHandler;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        android.util.Log.i(TAG, BuildTag.BUILD_TAG);
+        super.onCreate(savedInstanceState);
+        tLog.d(TAG, "onCreate()");
+        setContentView(R.layout.activity_tui);
+
+        mTuiHandler = new PerformActionInBackground();
+        TuiTlcWrapper.setHandler(mTuiHandler);
+
+        try {
+            mainView = (LinearLayout) findViewById(R.id.tuiLayout);
+            mainView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        TuiTlcWrapper.setIsActivityCreated(true);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if(hasFocus) {
+            tLog.d(TAG, "Focus gained");
+            synchronized(TuiTlcWrapper.getStartSignal()){
+                TuiTlcWrapper.setIsActityAlive(true);
+                TuiTlcWrapper.getStartSignal().notify();
+            }
+        } else {
+//            tLog.d(TAG, "Focus lost");
+//            synchronized(TuiTlcWrapper.getFinishSignal()){
+//                TuiTlcWrapper.getFinishSignal().notify();
+//            }
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        tLog.d(TAG, "onDestroy()");
+        super.onDestroy();
+
+        TuiTlcWrapper.setIsActivityCreated(false);
+        TuiTlcWrapper.setIsActityAlive(false);
+        synchronized(TuiTlcWrapper.getFinishSignal()){
+            TuiTlcWrapper.getFinishSignal().notify();
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        // Cancel the TUI session when the back key is pressed during a TUI 
+        // session
+        final TUI_Event cancel = new TUI_Event(TUI_EventType.TUI_CANCEL_EVENT);
+        if(!TuiTlcWrapper.notifyEvent(cancel.getType())) {
+            tLog.e(TAG, "notifyEvent failed!");
+        }
+    }
+
+    /*
+     * Handler that receives messages from the TimerTask, to adapt the UI.
+     */
+    class PerformActionInBackground extends Handler {
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what){
+            case TuiTlcWrapper.CLOSE_SESSION:
+                tLog.d(TAG, " handle message CLOSE_SESSION");
+                // Call the finish method to close the activity
+                finish();
+                /* Remove the animation when the activity is finished */
+                overridePendingTransition(0, 0);
+                break;
+
+            default:
+                tLog.d(TAG, " handle unknown message");
+                break;
+            }
+        }
+    }
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiservice/TuiService.java b/mobicore/TuiService/src/com/trustonic/tuiservice/TuiService.java
new file mode 100644 (file)
index 0000000..12acfca
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiservice;
+
+import com.trustonic.tuiapi.TUI_Event;
+import com.trustonic.tuiapi.TUI_EventType;
+import com.trustonic.util.tLog;
+
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.telephony.TelephonyManager;
+
+public class TuiService extends Service{
+    private static final String TAG = TuiService.class.getSimpleName();
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    // Executed if the service is not running, before OnStartCommand
+    @Override
+    public void onCreate()
+    {
+        tLog.d(TAG, "onCreate!!");
+        TuiTlcWrapper.init(this);
+
+        IntentFilter filter = new IntentFilter();
+        Intent screenIntent = new Intent(Intent.ACTION_SCREEN_OFF);
+        Intent batteryIntent = new Intent(Intent.ACTION_BATTERY_LOW);
+        filter.addAction(screenIntent.getAction());
+        filter.addAction(batteryIntent.getAction());
+        filter.addAction("android.intent.action.PHONE_STATE");
+        registerReceiver(mReceiver, filter);
+
+    }
+
+    // Executed each time startservice is called
+    @Override
+    public int onStartCommand(Intent  intent, int flags, int startId)
+    {
+        tLog.d(TAG, "onStartCommand!!");
+        return Service.START_STICKY;
+    }
+
+    private BroadcastReceiver mReceiver= new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+
+            Runnable notifyEvent = new Runnable() {
+                public void run() {
+                    final TUI_Event cancel = new TUI_Event(TUI_EventType.TUI_CANCEL_EVENT);
+                    if(!TuiTlcWrapper.notifyEvent(cancel.getType())) {
+                        tLog.e(TAG, "notifyEvent failed!");
+                    }
+                }
+            };
+
+            if (TuiTlcWrapper.isSessionOpened()) {
+
+                   if((intent.getAction() == Intent.ACTION_SCREEN_OFF)){
+                       tLog.d(TAG,"event screen off!");
+                       TuiTlcWrapper.acquireWakeLock();
+                       notifyEvent.run();
+                   }
+                if(intent.getAction() == "android.intent.action.PHONE_STATE"){
+                    Bundle bundle = intent.getExtras();
+                    if(bundle != null){
+                        if(bundle.getString(TelephonyManager.EXTRA_STATE).
+                                equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)){
+                            tLog.d(TAG,"event incoming call!");
+                            notifyEvent.run();
+                        }
+                    }
+                }
+                if((intent.getAction() == Intent.ACTION_BATTERY_LOW)){
+                    tLog.d(TAG,"event battery low!");
+                    /* TODO: get the battery level and only send a cancel event
+                     * if this level is below a threshold that will be defined */
+                    notifyEvent.run();
+                   }
+            }
+        }
+    };
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiservice/TuiServiceAutoStart.java b/mobicore/TuiService/src/com/trustonic/tuiservice/TuiServiceAutoStart.java
new file mode 100644 (file)
index 0000000..48bec0e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiservice;
+
+import com.trustonic.util.tLog;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningServiceInfo;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import com.trustonic.tuiservice.TuiService;
+
+public class TuiServiceAutoStart extends BroadcastReceiver {
+    private static final String TAG = TuiServiceAutoStart.class.getSimpleName();
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+
+        if (this.isServiceRunning(context)) {
+            tLog.d(TAG, "Start of service is not necessary, it is already running");
+            return;
+        }
+
+        Intent service = new Intent(context, TuiService.class);
+        context.startService(service);
+    }
+
+    private boolean isServiceRunning(Context context) {
+
+        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE))
+            if ("com.trustonic.tuiservice.TuiService".equals(service.service.getClassName()))
+                return true;
+
+        return false;
+    }
+
+}
diff --git a/mobicore/TuiService/src/com/trustonic/tuiservice/TuiTlcWrapper.java b/mobicore/TuiService/src/com/trustonic/tuiservice/TuiTlcWrapper.java
new file mode 100644 (file)
index 0000000..f436416
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2013-2015 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.tuiservice;
+
+import java.util.LinkedList;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.trustonic.tuiservice.TuiActivity.PerformActionInBackground;
+import com.trustonic.util.tLog;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+//import android.os.Build;
+//import android.util.DisplayMetrics;
+import android.os.PowerManager;
+//import android.view.Surface;
+
+public class TuiTlcWrapper {
+    private static final String TAG = TuiTlcWrapper.class.getSimpleName();
+
+//    public static final int INIT_SESSION    = 1;
+    public static final int CLOSE_SESSION   = 2;
+
+    private static Context context                      = null;
+    private static PerformActionInBackground handler    = null;
+    private static final Object sessionSignal           = new Object();
+    private static final Object startSignal             = new Object();
+    private static final Object finishSignal            = new Object();
+    private static boolean sessionOpened                = false;
+    private static AtomicBoolean isActityAlive = new AtomicBoolean();
+    private static AtomicBoolean isActivityCreated = new AtomicBoolean();
+
+    private static PowerManager pm;
+    private static PowerManager.WakeLock wl;
+
+
+    public static boolean isSessionOpened() {
+        synchronized (sessionSignal) {
+            return sessionOpened;
+        }
+    }
+    public static void setSessionOpened(boolean sessionOpened) {
+        synchronized (sessionSignal) {
+            TuiTlcWrapper.sessionOpened = sessionOpened;
+        }
+    }
+
+    public static Object getStartSignal() {
+        return startSignal;
+    }
+    public static Object getFinishSignal() {
+        return finishSignal;
+    }
+
+    public static PerformActionInBackground getHandler() {
+        return handler;
+    }
+    public static void setHandler(PerformActionInBackground handler) {
+        TuiTlcWrapper.handler = handler;
+    }
+
+    public static void setIsActityAlive(boolean status) {
+        TuiTlcWrapper.isActityAlive.set(status);
+    }
+
+    public static void setIsActivityCreated(boolean status) {
+        TuiTlcWrapper.isActivityCreated.set(status);
+    }
+
+    public static boolean startTuiSession(){
+
+           try {
+            synchronized (startSignal) {
+                /* create activities */
+                Intent myIntent = new Intent(context, TuiActivity.class);
+                myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_DEBUG_LOG_RESOLUTION
+                        | Intent.FLAG_ACTIVITY_NO_ANIMATION);
+                       context.startActivity(myIntent);
+                /* Wait activity created*/
+                startSignal.wait(5000);
+                if( ! TuiTlcWrapper.isActityAlive.get()) {
+                    tLog.d(TAG, "ERROR ACTIVITY timout");
+                    finishTuiSession();
+                    return false;
+                }
+               }
+           } catch (InterruptedException e) {
+               // TODO Auto-generated catch block
+               e.printStackTrace();
+           }
+
+        /* Enable cancel events catching */
+        synchronized (sessionSignal) {
+            TuiTlcWrapper.sessionOpened = true;
+        }
+
+        return true;
+    }
+
+    public static void acquireWakeLock() {
+           /* Ensure that CPU is still running */
+           try {
+               wl.acquire();
+           } catch (Exception e1) {
+               // TODO Auto-generated catch block
+               e1.printStackTrace();
+           }
+    }
+
+    public static void finishTuiSession(){
+        tLog.d(TAG, "finishTuiSession!");
+        if(TuiTlcWrapper.isActivityCreated.get()) {
+            /* Disable cancel events catching */
+            synchronized (sessionSignal) {
+                TuiTlcWrapper.sessionOpened = false;
+            }
+
+            try{
+                synchronized (finishSignal) {
+                    /* Send a message to the activity UI thread */
+                    handler.sendMessage(handler.obtainMessage(CLOSE_SESSION));
+                    /* Wait activity closed */
+                    finishSignal.wait(5000);
+                    if(TuiTlcWrapper.isActivityCreated.get()) {
+                        tLog.d(TAG, "ERROR ACTIVITY timout");
+                    }
+                }
+            }catch (Exception e) {
+                // TODO: handle exception
+                e.printStackTrace();
+            }
+        }
+        try {
+            if (wl.isHeld()) {
+                   wl.release();
+            }
+        } catch (Exception e2) {
+            // TODO Auto-generated catch block
+            e2.printStackTrace();
+        }
+    }
+
+
+    /* Initialize static members */
+    public static void init(Context ctxt) {
+        /* Save context */
+        context = ctxt;
+
+        pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE);
+        wl  = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TuiService");
+
+        /* Start the TlcTui native thread */
+        startTlcTui();
+    }
+
+    /* Native functions */
+    public static native int startTlcTui();
+    public static native boolean notifyEvent(int eventType);
+
+    /**
+     * this is used to load the library on application startup. The
+     * library has already been unpacked to the app specific folder
+     * at installation time by the package manager.
+     */
+    static {
+        System.loadLibrary("Tui");
+    }
+}
diff --git a/mobicore/TuiService/src/com/trustonic/util/tLog.java b/mobicore/TuiService/src/com/trustonic/util/tLog.java
new file mode 100644 (file)
index 0000000..bc93a10
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.trustonic.util;
+
+import android.util.Log;
+
+public class tLog {
+       /* Enable log with the command:
+        * adb shell setprop log.tag.YOUR_APP_TAG LEVEL
+        * e.g adb shell setprop log.tag.TuiActivity DEBUG
+        * */
+    public static void d(String tag, String msg) {
+        if (Log.isLoggable(tag, Log.DEBUG)) {
+            Log.d(tag, msg);
+        }
+    }
+
+    public static void i(String tag, String msg) {
+        if (Log.isLoggable(tag, Log.INFO)) {
+            Log.i(tag, msg);
+        }
+    }
+
+    public static void e(String tag, String msg) {
+        if (Log.isLoggable(tag, Log.ERROR)) {
+            Log.e(tag, msg);
+        }
+    }
+
+    public static void v(String tag, String msg) {
+        if (Log.isLoggable(tag, Log.VERBOSE)) {
+            Log.v(tag, msg);
+        }
+    }
+
+    public static void w(String tag, String msg) {
+        if (Log.isLoggable(tag, Log.WARN)) {
+            Log.w(tag, msg);
+        }
+    }
+}
+
diff --git a/mobicore/rootpa/Android.mk b/mobicore/rootpa/Android.mk
new file mode 100644 (file)
index 0000000..6331641
--- /dev/null
@@ -0,0 +1,7 @@
+LOCAL_ROOT_PATH := $(call my-dir)
+
+MOBICORE_DIR_INC := $(LOCAL_ROOT_PATH)/../curl/include
+include $(LOCAL_ROOT_PATH)/Code/Common/Android.mk
+include $(LOCAL_ROOT_PATH)/Code/Android/app/jni/Android.mk
+include $(LOCAL_ROOT_PATH)/Code/Android/lib/Android.mk
+include $(LOCAL_ROOT_PATH)/Code/Android/app/Android.mk
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/app/Android.mk b/mobicore/rootpa/Code/Android/app/Android.mk
new file mode 100644 (file)
index 0000000..a9c5aec
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# build RootPA.apk
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := rootpa_interface
+LOCAL_JNI_SHARED_LIBRARIES := libcommonpawrapper
+
+LOCAL_PACKAGE_NAME := RootPA
+LOCAL_MODULE_TAGS := debug eng optional
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard-project.txt
+
+APP_PIE := true
+LOCAL_32_BIT_ONLY := true
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
diff --git a/mobicore/rootpa/Code/Android/app/AndroidManifest.xml b/mobicore/rootpa/Code/Android/app/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..02cf95e
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" ?> 
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
+          package="com.gd.mobicore.pa"
+          android:versionCode="@integer/code" 
+          android:versionName="@string/name" >
+
+  <uses-sdk android:minSdkVersion="14"
+           android:targetSdkVersion="23" />
+
+  <uses-permission android:name="android.permission.INTERNET"/>
+  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />    
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+           android:maxSdkVersion="22" />
+    
+  <permission android:name="com.gd.mobicore.pa.permission.OEM_PERMISSION"
+        android:label="remove installed secure services"
+        android:description="@string/description_oempermission"
+        android:protectionLevel="signatureOrSystem" />
+
+  <permission android:name="com.gd.mobicore.pa.permission.DEVELOPER_PERMISSION"
+        android:label="install developer trustlet"
+        android:description="@string/description_developerpermission"
+        android:protectionLevel="normal"/>
+
+  <application 
+    android:label="RootPA" 
+    android:debuggable="false"
+    android:theme="@android:style/Theme.NoDisplay">
+    <service 
+        android:name="com.gd.mobicore.pa.service.ProvisioningService" 
+        android:enabled="true"
+        android:exported="true">
+        <intent-filter> 
+            <action android:name="com.gd.mobicore.pa.service.PROVISIONING_SERVICE" />   
+        </intent-filter>
+    </service>
+
+    <service 
+        android:name="com.gd.mobicore.pa.service.DeveloperService" 
+        android:enabled="true"
+        android:exported="true"
+        android:permission="com.gd.mobicore.pa.permission.DEVELOPER_PERMISSION">
+        <intent-filter> 
+            <action android:name="com.gd.mobicore.pa.service.DEVELOPER_SERVICE" />   
+        </intent-filter>
+    </service>    
+    
+    <service 
+        android:name="com.gd.mobicore.pa.service.OemService" 
+        android:enabled="true"
+        android:exported="true"
+        android:permission="com.gd.mobicore.pa.permission.OEM_PERMISSION">
+        <intent-filter> 
+            <action android:name="com.gd.mobicore.pa.service.OEM_SERVICE" />   
+        </intent-filter>
+    </service>        
+    
+  </application>
+
+</manifest>
diff --git a/mobicore/rootpa/Code/Android/app/NOTICE b/mobicore/rootpa/Code/Android/app/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/rootpa/Code/Android/app/ant.properties b/mobicore/rootpa/Code/Android/app/ant.properties
new file mode 100644 (file)
index 0000000..3f42c1c
--- /dev/null
@@ -0,0 +1,2 @@
+out.dir=out
+java.compilerargs="-Xlint:unchecked"
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/app/build.xml b/mobicore/rootpa/Code/Android/app/build.xml
new file mode 100644 (file)
index 0000000..c251281
--- /dev/null
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="RootPA" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+<!-- All the build information will be stored in a seperate logfile 
+     including a timestamp. -->
+<target name="log">
+<tstamp><format property="timestamp" pattern="yyyy-MM-dd_HH-mm-ss"/></tstamp>
+<property name="build.log.dir" location="${basedir}/buildlogs"/>
+<mkdir dir="${build.log.dir}"/>
+<property name="build.log.filename" value="build_${timestamp}.log"/>
+<record name="${build.log.dir}/${build.log.filename}" loglevel="verbose" append="false"/>
+<echo message="Build logged to ${build.log.filename}"/>
+</target>
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+<condition property="ndk.dir" value="${env.NDK_HOME}">
+     <isset property="env.NDK_HOME" />
+</condition>
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+<!-- 
+-Update android project
+-Running ndk-build to compile native android sources-->
+
+<target name="windows">
+
+<exec executable="cmd"
+    failonerror="true">
+        <arg value="/c"/>
+    <arg value="${env.ANDROID_HOME}/tools/android update project --path ./"/>
+</exec>
+
+<exec executable="${env.NDK_BUILD}/ndk-build.cmd"/>
+
+<antcall target="copy_libs"/>
+
+</target>
+
+<target name="linux">
+
+<exec
+    executable="${env.ANDROID_HOME}/tools/android"
+    failonerror="true">
+        <arg value="update"/>
+        <arg value="project"/>
+        <arg value="-p"/>
+        <arg value="."/>
+</exec>
+
+<exec executable="${env.NDK_BUILD}/ndk-build"/>
+</target>
+
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+<!-- quick check on ndk.dir -->
+
+<fail message="ndk.dir is missing. Make sure that the local.properties file defines it."
+          unless="ndk.dir" />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <target name="-pre-build">
+        <exec executable="ndk-build" dir="jni">    </exec>     
+    </target>
+
+
+    <target name="-pre-clean">
+        <exec executable="ndk-build" dir="jni">
+            <arg value="clean"/>  
+        </exec> 
+    </target>
+
+    <target name="test" depends="debug">
+    </target>    
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+
+
+    <!-- the version tag is set to custom in order to avoid regenerating this file. The file has been modifies to make the project name different from the folder name -->
+    <!-- version-tag: custom -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+</project>
diff --git a/mobicore/rootpa/Code/Android/app/generateCheaders.sh b/mobicore/rootpa/Code/Android/app/generateCheaders.sh
new file mode 100644 (file)
index 0000000..ca49378
--- /dev/null
@@ -0,0 +1,12 @@
+#/bin/sh
+
+#
+# this is helper script for recreating the jni header file when the interface 
+# changes. it is not executed every time when building
+#
+
+cd src
+export CLASSPATH=.:/usr/local/android-sdk/:/usr/local/android-sdk/platforms/android-16/android.jar:../out/classes:../../lib/bin/classes
+javac  com/gd/mobicore/pa/jni/CommonPAWrapper.java
+javah  -d ../jni/CommonPAWrapper/ com.gd.mobicore.pa.jni.CommonPAWrapper
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/Android.mk b/mobicore/rootpa/Code/Android/app/jni/Android.mk
new file mode 100644 (file)
index 0000000..16e2a11
--- /dev/null
@@ -0,0 +1,45 @@
+#
+# Copyright  Â© Trustonic Limited 2013
+#
+# All rights reserved.
+#
+#  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. Neither the name of the Trustonic Limited nor the names of its contributors 
+#     may be used to endorse or promote products derived from this software 
+#     without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+#
+# makefile for building the provisioning agent Common part and the jni wrapper 
+# for android. Build the components by executing 
+# $NDK_ROOT/ndk-build in the folder where this file resides
+#
+# Note that you have to have the whole RootPA source code 
+# (including RootPA/Common) checked out in order to sucessfully 
+# complete te build
+#
+APP_PIE := true
+LOCAL_32_BIT_ONLY := true
+include $(call all-subdir-makefiles)
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/Android.mk b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/Android.mk
new file mode 100644 (file)
index 0000000..82e67c6
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# Copyright Â© Trustonic Limited 2013
+#
+# All rights reserved.
+#
+#  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. Neither the name of the Trustonic Limited nor the names of its contributors 
+#     may be used to endorse or promote products derived from this software 
+#     without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+# makefile for building the provisioning agent JNI wrapper for using the Common part
+# from Android Java code. build the code by executing
+# $NDK_ROOT/ndk-build in the folder where this file resides
+# (or build all from one level up)
+#
+# Naturally the right way to build this is using build script in Build folder.
+# It then uses this file in turn.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS += -DANDROID_ARM=1
+LOCAL_CFLAGS +=-fstack-protector
+ifeq ($(DEBUG), 1)
+    LOCAL_CFLAGS += -D__DEBUG=1
+endif   
+
+LOCAL_SRC_FILES += commonwrapper.cpp
+LOCAL_SRC_FILES += JniHelpers.cpp
+LOCAL_SRC_FILES += CmpResponses.cpp
+LOCAL_SRC_FILES += CmpCommands.cpp
+LOCAL_SRC_FILES += CmpBase.cpp
+
+LOCAL_C_INCLUDES +=  $(MOBICORE_DIR_INC)
+LOCAL_C_INCLUDES +=  $(MOBICORE_DIR_INC)/TlCm
+LOCAL_C_INCLUDES +=  $(LOCAL_PATH)/../../../../Common/include
+
+LOCAL_MODULE    := libcommonpawrapper
+LOCAL_MODULE_TAGS := debug eng optional
+
+ifeq ($(ROOTPA_MODULE_TEST), 1)
+    LOCAL_STATIC_LIBRARIES += provisioningagent_test
+    LOCAL_STATIC_LIBRARIES += McStub    
+else
+    LOCAL_STATIC_LIBRARIES += provisioningagent
+    LOCAL_STATIC_LIBRARIES += MobiCoreTlcm
+    LOCAL_SHARED_LIBRARIES += libMcClient
+    LOCAL_SHARED_LIBRARIES += libMcRegistry
+endif
+
+#LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib
+
+LOCAL_SHARED_LIBRARIES += liblog
+LOCAL_SHARED_LIBRARIES += libz
+LOCAL_SHARED_LIBRARIES += libssl
+LOCAL_SHARED_LIBRARIES += libcrypto
+LOCAL_SHARED_LIBRARIES += libcurl
+LOCAL_STATIC_LIBRARIES += libxml2
+LOCAL_SHARED_LIBRARIES += libicuuc
+
+APP_PIE := true
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpBase.cpp b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpBase.cpp
new file mode 100644 (file)
index 0000000..4aece60
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "logging.h"
+#include "CmpBase.h"
+
+/*=================================================================================
+
+Public methods
+
+*/
+
+CmpBase::CmpBase(JNIEnv* env, jobject msgs): env_(env),
+                                             msgs_(msgs),
+                                             cls_(NULL),
+                                             objectCls_(NULL),
+                                             numberOfElements_(0),
+                                                                                        broken_(false)
+{
+    if((env_ != NULL) && (msgs_ != NULL))
+    {
+        cls_=env_->GetObjectClass(msgs_);
+        if(NULL==cls_)
+        {
+            LOGE("can not get object class");
+            broken_=true;
+        }
+    }
+    else
+    {
+        broken_=true;
+    }
+}
+
+/*
+*/
+CmpBase::~CmpBase()
+{
+    if(cls_!=NULL)
+    {
+        env_->DeleteLocalRef(cls_);
+    }
+
+    if(objectCls_!=NULL)
+    {
+        env_->DeleteLocalRef(objectCls_);
+    }
+}
+
+/*
+returns number of elements in the array. For the first time gets it from java
+*/
+int CmpBase::numberOfElements()
+{
+    if(!broken_ && (0 == numberOfElements_))
+    {
+        jmethodID mid =  env_->GetMethodID(cls_, "size", "()I");
+        if(mid !=0)
+        {
+            numberOfElements_ = (int) env_->CallIntMethod(msgs_, mid);
+        }
+        else
+        {
+            LOGE("no size ()I method");
+        }
+    }
+    return numberOfElements_;
+}
+
+
+
+
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpBase.h b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpBase.h
new file mode 100644 (file)
index 0000000..7a9e5f8
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CMPBASE_H
+#define CMPBASE_H
+
+#include <jni.h>
+#include "logging.h"
+#include "provisioningagent.h"
+
+class CmpBase
+{
+    public:
+        CmpBase(JNIEnv* env, jobject msgs);
+        virtual ~CmpBase();
+        int numberOfElements();
+    private:
+        CmpBase();
+        CmpBase(CmpBase&);
+    protected:
+       JNIEnv* env_;
+       jobject msgs_;
+       jclass cls_;
+       jclass objectCls_;
+       int numberOfElements_;
+       bool broken_;
+};
+
+#endif // CMPBASE_H
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpCommands.cpp b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpCommands.cpp
new file mode 100644 (file)
index 0000000..01263d5
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "logging.h"
+#include "CmpCommands.h"
+#include "JniHelpers.h"
+CmpCommands::CmpCommands(JNIEnv* env, jobject commands): CmpBase(env, commands), jObjectArray_(NULL)
+{
+    if(!broken_)
+    {
+        createObjectArray();
+    }
+}
+
+CmpCommands::~CmpCommands()
+{
+
+}
+
+
+/*
+Trusting that the caller has reserved long enough array
+*/
+bool CmpCommands::getCommands(CmpMessage* objectArray)
+{
+    if(!broken_)
+    {
+        if(NULL==objectCls_)
+        {
+            objectCls_ = env_->FindClass("com/gd/mobicore/pa/ifc/CmpCommand"); // element in array
+        }
+        if(objectCls_ != NULL)
+        {
+            jmethodID midToByteArray=env_->GetMethodID(objectCls_, "toByteArray", "()[B");
+            if(NULL==midToByteArray){
+                LOGE("<<CmpCommands::getCommands returning false, method toByteArray not found");
+                return false;
+            }
+            jmethodID midIgnoreError=env_->GetMethodID(objectCls_, "ignoreError", "()Z");
+            if(NULL==midIgnoreError){
+                LOGE("<<CmpCommands::getCommands returning false, method ignoreError not found");
+                return false;
+            }
+
+            jbyteArray jba=NULL;
+            jobject arrayElement=NULL;
+            for(int i=0; i<numberOfElements(); i++)
+            {
+                arrayElement = env_->GetObjectArrayElement(jObjectArray_, i);
+                jba = (jbyteArray) env_->CallObjectMethod(arrayElement, midToByteArray);
+
+                JniHelpers helper(env_);
+                objectArray[i].contentP=helper.jByteArrayToCByteArray(jba, &(objectArray[i].length));
+                objectArray[i].hdr.ignoreError=(JNI_TRUE==env_->CallBooleanMethod(arrayElement, midIgnoreError));
+                env_->DeleteLocalRef(jba);
+                env_->DeleteLocalRef(arrayElement);
+            }
+        return true;
+        }
+    }
+    return false;
+}
+
+
+/*
+
+*/
+void CmpCommands::createObjectArray()
+{
+    if(broken_) return;
+
+    jmethodID mid = env_->GetMethodID(cls_, "toArray", "()[Ljava/lang/Object;");
+    if (mid != 0)
+    {
+           jObjectArray_ = (jobjectArray) env_->CallObjectMethod(msgs_, mid);
+        if(NULL==jObjectArray_)
+        {
+               LOGE("error in getting jObjectArray_");
+            broken_= true;
+        }
+       }
+    else
+    {
+           LOGE("Sorry, but the method toArray()[Ljava/lang/Object cannot be found!");
+        broken_= true;
+    }
+    return;
+}
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpCommands.h b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpCommands.h
new file mode 100644 (file)
index 0000000..494b184
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CMPCOMMANDS_H
+#define CMPCOMMANDS_H
+
+#include "CmpBase.h"
+#include "provisioningagent.h"
+
+class CmpCommands : public CmpBase
+{
+    public:
+        CmpCommands(JNIEnv* env, jobject commands);
+        virtual ~CmpCommands();
+        /**
+        this trusts that the caller has reserved long enough array
+        */
+        bool getCommands(CmpMessage* objectArray);
+    private:
+        CmpCommands();
+        CmpCommands(CmpMessage&);
+        void createObjectArray();
+    private:
+       jobjectArray jObjectArray_;
+};
+
+#endif // CMPCOMMANDS_H
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpResponses.cpp b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpResponses.cpp
new file mode 100644 (file)
index 0000000..dc87184
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include "JniHelpers.h"
+#include "CmpResponses.h"
+
+CmpResponses::CmpResponses(JNIEnv* env, jobject responses): CmpBase(env, responses)
+{
+    if(!broken_)
+    {
+        jmethodID mid = env_->GetMethodID(cls_, "clear", "()V");
+        if(mid != NULL)
+        {
+            env_->CallVoidMethod(msgs_, mid);
+        }
+        else
+        {
+           LOGE("CmpResponses::CmpResponses: Sorry, but the method clear()V cannot be found!");
+        }
+    }
+}
+
+CmpResponses::~CmpResponses()
+{
+
+}
+
+
+int CmpResponses::update(CmpMessage* responses, int numberOfResponses)
+{
+    int ret=ROOTPA_OK;
+    if(broken_) return ROOTPA_ERROR_INTERNAL;
+
+    jmethodID mid=env_->GetMethodID(cls_, "add", "(Ljava/lang/Object;)Z");
+    if(NULL==mid)
+    {
+        LOGE("do not find add(Ljava/lang/Object)Z from List");
+        return ROOTPA_ERROR_INTERNAL;
+    }
+
+    jobject responseObject=NULL;
+    bool result;
+    for(int i=0; i<numberOfResponses; i++)
+    {
+        responseObject=createCmpResponseObject(responses[i]);
+        if(responseObject != NULL)
+        {
+            if((result=(bool) env_->CallBooleanMethod(msgs_, mid, responseObject))==false)
+            {
+                ret=ROOTPA_ERROR_INTERNAL;
+                LOGE("adding cmp response object %d failed", i);
+            }
+            env_->DeleteLocalRef(responseObject);
+        }
+        else
+        {
+            ret=ROOTPA_ERROR_INTERNAL;
+            LOGE("creating cmp response object failed");
+        }
+    }
+    return ret;
+}
+
+
+
+jobject CmpResponses::createCmpResponseObject(CmpMessage msg)
+{
+    jobject newObject=NULL;
+    if(!broken_)
+    {
+        objectCls_=env_->FindClass("com/gd/mobicore/pa/ifc/CmpResponse");
+        if(objectCls_!=NULL)
+        {
+            jmethodID constructor=NULL;
+            JniHelpers helper(env_);
+            jbyteArray rsp = helper.byteArrayToJByteArray(msg.contentP, msg.length);
+            if(rsp != NULL)
+            {
+                constructor = env_->GetMethodID(objectCls_, "<init>", "([B)V");
+            }
+            else
+            {
+                constructor = env_->GetMethodID(objectCls_, "<init>", "()V");
+                LOGE("CmpResponses::createCmpResponseObject no response received, using empty response object");
+            }
+
+            if(constructor != NULL)
+            {
+
+                if(rsp != NULL)
+                {
+                    newObject = env_->NewObject(objectCls_, constructor, rsp);
+                }
+                else
+                {
+                    newObject = env_->NewObject(objectCls_, constructor);
+                }
+
+                if(NULL==newObject)
+                {
+                    LOGE("CmpResponses::createCmpResponseObject creating new object failed %p %p", objectCls_, constructor);
+                }
+
+            }
+            else
+            {
+                LOGE("CmpResponses::createCmpResponseObject creating constructor failed");
+            }
+
+            if(rsp != NULL)
+            {
+                env_->DeleteLocalRef(rsp);
+            }
+
+        }
+        else
+        {
+            LOGE("CmpResponses::createCmpResponseObject did not find java side class /com/gd/mobicore/pa/ifc/CmpResponse");
+        }
+    }
+
+    if(objectCls_!=NULL)
+    {
+        env_->DeleteLocalRef(objectCls_);
+        objectCls_=NULL;
+    }
+
+    return newObject;
+}
+
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpResponses.h b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/CmpResponses.h
new file mode 100644 (file)
index 0000000..c3cc44d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CMPRESPONSES_H
+#define CMPRESPONSES_H
+
+#include "CmpBase.h"
+#include "provisioningagent.h"
+
+class CmpResponses : public CmpBase
+{
+    public:
+        CmpResponses(JNIEnv* env, jobject responses);
+        virtual ~CmpResponses();
+        int update(CmpMessage* responses, int numberOfResponses);
+    private:
+        CmpResponses();
+        CmpResponses(CmpResponses&);
+        jobject createCmpResponseObject(CmpMessage msg);
+};
+
+#endif // CMPRESPONSES_H
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/JniHelpers.cpp b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/JniHelpers.cpp
new file mode 100644 (file)
index 0000000..ba6d815
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include "JniHelpers.h"
+#include "rootpaErrors.h"
+
+JniHelpers::JniHelpers(JNIEnv* envP):broken_(false),
+                                     envP_(envP),
+                                     keysP_(NULL),
+                                     valuesP_(NULL),
+                                     productIdP_(NULL),
+                                     listCls_(NULL),
+                                     intCls_(NULL),
+                                     stringCls_(NULL),
+                                     stringConstructur_(NULL),
+                                     intConstructor_(NULL),
+                                     listAdd_(NULL)
+{}
+
+JniHelpers::~JniHelpers()
+{
+    if(listCls_!=NULL)
+    {
+        envP_->DeleteLocalRef(listCls_);
+    }
+
+    if(intCls_!=NULL)
+    {
+        envP_->DeleteLocalRef(intCls_);
+    }
+
+    if(stringCls_!=NULL)
+    {
+        envP_->DeleteLocalRef(stringCls_);
+    }
+}
+
+
+JniHelpers::JniHelpers(JNIEnv* envP,jobject* keysP, jobject* valuesP, jbyteArray* productIdP):broken_(false),
+                                                                                              envP_(envP),
+                                                                                              keysP_(keysP),
+                                                                                              valuesP_(valuesP),
+                                                                                              productIdP_(productIdP),
+                                                                                              listCls_(NULL),
+                                                                                              intCls_(NULL),
+                                                                                              stringCls_(NULL),
+                                                                                              stringConstructur_(NULL),
+                                                                                              intConstructor_(NULL),
+                                                                                              listAdd_(NULL)
+{
+    listCls_=envP_->FindClass("java/util/List");
+    if(NULL == listCls_)
+    {
+        LOGE("JniHelpers::JniHelpers no listCls_");
+        broken_=true;
+        return;
+    }
+
+    listAdd_=envP_->GetMethodID(listCls_, "add", "(Ljava/lang/Object;)Z");
+    if(NULL == listAdd_)
+    {
+        LOGE("JniHelpers::JniHelpers no listAdd_");
+        broken_=true;
+        return;
+    }
+
+    intCls_=envP_->FindClass("java/lang/Integer");
+    if(NULL == intCls_)
+    {
+        LOGE("JniHelpers::JniHelpers no intCls_");
+        broken_=true;
+        return;
+    }
+
+    intConstructor_=envP_->GetMethodID(intCls_, "<init>", "(I)V");
+    if(NULL == intConstructor_)
+    {
+        LOGE("JniHelpers::JniHelpers no intConstructor_");
+        broken_=true;
+        return;
+    }
+
+    stringCls_=envP_->FindClass("java/lang/String");
+    if(NULL == stringCls_)
+    {
+        LOGE("JniHelpers::JniHelpers no stringCls_");
+        broken_=true;
+        return;
+    }
+
+    stringConstructur_=envP_->GetMethodID(stringCls_, "<init>", "([B)V");
+    if(NULL == stringConstructur_)
+    {
+        LOGE("JniHelpers::JniHelpers no stringConstructur_");
+        broken_=true;
+        return;
+    }
+}
+
+int JniHelpers::setVersion(char* fieldName, int version)
+{
+    if(broken_) return ROOTPA_ERROR_INTERNAL;
+
+    jbyteArray fName=byteArrayToJByteArray((uint8_t*)fieldName, strlen(fieldName));
+    if(NULL == fName)
+    {
+        LOGE("JniHelpers::setVersion no fName");
+        broken_=true;
+        return ROOTPA_ERROR_INTERNAL;
+    }
+
+    jobject newStringObject = envP_->NewObject(stringCls_, stringConstructur_, fName);
+    if(NULL == newStringObject)
+    {
+        LOGE("JniHelpers::setVersion no newStringObject");
+        broken_=true;
+        envP_->DeleteLocalRef(fName);
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    envP_->DeleteLocalRef(fName);
+
+    if(envP_->CallBooleanMethod(*keysP_, listAdd_, newStringObject)==JNI_FALSE)
+    {
+        LOGE("JniHelpers::setVersion can not add key");
+        broken_=true;
+        envP_->DeleteLocalRef(newStringObject);
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    envP_->DeleteLocalRef(newStringObject);
+
+    jobject newIntObject = envP_->NewObject(intCls_, intConstructor_, version);
+    if(NULL == newIntObject)
+    {
+        LOGE("JniHelpers::setVersion no newIntObject");
+        broken_=true;
+        return ROOTPA_ERROR_INTERNAL;
+    }
+
+    if(envP_->CallBooleanMethod(*valuesP_, listAdd_, newIntObject)==JNI_FALSE)
+    {
+        LOGE("JniHelpers::setVersion can not add value");
+        broken_=true;
+        envP_->DeleteLocalRef(newIntObject);
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    envP_->DeleteLocalRef(newIntObject);
+
+    return ROOTPA_OK;
+}
+
+int JniHelpers::setProductId(char* productId)
+{
+    return setByteArray(productIdP_,(uint8_t*)productId, strlen(productId));
+}
+
+int JniHelpers::setByteArray(jbyteArray* targetArrayP, uint8_t* sourceArrayP , uint32_t length)
+{
+    if(broken_) return ROOTPA_ERROR_INTERNAL;
+    if(NULL==targetArrayP || NULL == sourceArrayP || 0 == length)  return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    envP_->SetByteArrayRegion(*targetArrayP, 0, length, (jbyte*) sourceArrayP);
+
+    return ROOTPA_OK;
+}
+
+int JniHelpers::setBooleanToArray(jbooleanArray* targetArrayP, bool source)
+{
+    if(broken_) return ROOTPA_ERROR_INTERNAL;
+    if(NULL==targetArrayP )  return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    envP_->SetBooleanArrayRegion(*targetArrayP, 0, 1 , (jboolean*) &source);
+
+    return ROOTPA_OK;
+}
+
+int  JniHelpers::setIntToArray(jintArray* targetArrayP, int index, int source)
+{
+    if(broken_) return ROOTPA_ERROR_INTERNAL;
+    if(NULL==targetArrayP )  return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    envP_->SetIntArrayRegion(*targetArrayP, index, 1 , (jint*) &source);
+
+    return ROOTPA_OK;
+}
+
+jbyteArray JniHelpers::byteArrayToJByteArray(uint8_t* dataP, uint32_t length)
+{
+    jbyteArray jbArray = NULL;
+    if (envP_->EnsureLocalCapacity(1) == JNI_OK)
+    {
+
+        if ((length > 0) && (dataP != NULL))
+        {
+            jbArray = envP_->NewByteArray(length);
+            if (jbArray != NULL)
+            {
+                envP_->SetByteArrayRegion(jbArray, 0, length, (jbyte*) dataP);
+            }
+        }
+    }
+
+    return jbArray;
+}
+
+/**
+* Retrieves a uint8_t* jbyteArray (java) object. Result needs to be freed with delete[] afterwards.
+* @param jBytes jbyteArray (java) of primitive byte data
+* @param outLength* (OUT PARAMETER) length of the returned uint8_t* byte array
+* @return uint8_t* byte array. Needs to be freed with delete[] afterwards.
+*/
+uint8_t* JniHelpers::jByteArrayToCByteArray(jbyteArray jBytes, uint32_t* outLength)
+{
+    *outLength=0;
+    uint8_t* cBytes = NULL;
+    if ((jBytes != NULL) && !broken_)
+    {
+        *outLength = envP_->GetArrayLength(jBytes);
+        cBytes = new uint8_t[*outLength];
+        jbyte* p_jcResult = envP_->GetByteArrayElements(jBytes, JNI_FALSE);
+        for (unsigned int i = 0; i < *outLength; i++)
+        {
+            cBytes[i] = (uint8_t) p_jcResult[i] & (0x00ff);
+        }
+
+        envP_->ReleaseByteArrayElements(jBytes, p_jcResult, JNI_FALSE);
+    }
+    else
+    {
+        LOGE("jByteArrayToCByteArray: Input is NULL or something else is broken. Cannot return byte array");
+    }
+    return cBytes;
+}
+
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/JniHelpers.h b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/JniHelpers.h
new file mode 100644 (file)
index 0000000..df3b02e
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JNIHELPERS_H
+#define JNIHELPERS_H
+
+#include <stdlib.h>
+#include <jni.h>
+#include "logging.h"
+
+
+class JniHelpers
+{
+    public:
+        JniHelpers(JNIEnv* envP);
+        JniHelpers(JNIEnv* envP, jobject* keysP, jobject* valuesP, jbyteArray* productIdP);
+        virtual ~JniHelpers();
+        int setVersion(char* fieldName, int version);
+        int setProductId(char* productId);
+        int setByteArray(jbyteArray* targetArrayP, uint8_t* sourceArrayP , uint32_t length);
+        int setBooleanToArray(jbooleanArray* targetArrayP, bool source);
+        int setIntToArray(jintArray* targetArrayP, int index, int source);
+        jbyteArray byteArrayToJByteArray(uint8_t* dataP, uint32_t length);
+        uint8_t* jByteArrayToCByteArray(jbyteArray jBytes, uint32_t* outLength);
+    private:
+
+        bool broken_;
+
+        JNIEnv* envP_;
+        jobject* keysP_;
+        jobject* valuesP_;
+        jbyteArray* productIdP_;
+
+// classes and methods
+
+        jclass listCls_;
+        jclass intCls_;
+        jclass stringCls_;
+        jmethodID stringConstructur_;
+        jmethodID intConstructor_;
+        jmethodID listAdd_;
+};
+
+
+#endif // JNIHELPERS_H
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/NOTICE b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h
new file mode 100644 (file)
index 0000000..d74074c
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_gd_mobicore_pa_jni_CommonPAWrapper */
+
+#ifndef _Included_com_gd_mobicore_pa_jni_CommonPAWrapper
+#define _Included_com_gd_mobicore_pa_jni_CommonPAWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_IMEI_ESN_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_IMEI_ESN_INDEX 0L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_MNO_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_MNO_INDEX 1L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_BRAND_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_BRAND_INDEX 2L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_MANUFACTURER_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_MANUFACTURER_INDEX 3L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_HARDWARE_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_HARDWARE_INDEX 4L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_MODEL_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_MODEL_INDEX 5L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_VERSION_INDEX
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_VERSION_INDEX 6L
+#undef com_gd_mobicore_pa_jni_CommonPAWrapper_RESPONSE_ARRAY_SIZE
+#define com_gd_mobicore_pa_jni_CommonPAWrapper_RESPONSE_ARRAY_SIZE 7L
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    openSession
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_openSession
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    closeSession
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_closeSession
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    executeCmpCommands
+ * Signature: (ILjava/util/List;Ljava/util/List;)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_executeCmpCommands
+  (JNIEnv *, jobject, jint, jobject, jobject);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    getVersion
+ * Signature: ([BLjava/util/List;Ljava/util/List;)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getVersion
+  (JNIEnv *, jobject, jbyteArray, jobject, jobject);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    getSuid
+ * Signature: ([B)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSuid
+  (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    isRootContainerRegistered
+ * Signature: ([Z)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_isRootContainerRegistered
+  (JNIEnv *, jobject, jbooleanArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    isSpContainerRegistered
+ * Signature: (I[Z)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_isSpContainerRegistered
+  (JNIEnv *, jobject, jint, jbooleanArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    getSPContainerState
+ * Signature: (I[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSPContainerState
+  (JNIEnv *, jobject, jint, jintArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    getSPContainerStructure
+ * Signature: (I[I[[B[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSPContainerStructure
+  (JNIEnv *, jobject, jint, jintArray, jobjectArray, jintArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    doProvisioning
+ * Signature: (II[B)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_doProvisioning
+  (JNIEnv *, jobject, jint, jint, jbyteArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    installTrustlet
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet
+  (JNIEnv *, jobject, jint, jbyteArray, jint, jbyteArray, jint, jbyteArray, jint, jint, jint, jbyteArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    unregisterRootContainer
+ * Signature: ([B)I
+ */
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_unregisterRootContainer
+  (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
+ * Method:    setEnvironmentVariable
+ * Signature: ([B[B)I
+ */
+JNIEXPORT void JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable
+  (JNIEnv *, jobject, jbyteArray, jbyteArray);
+
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_storeTA
+  (JNIEnv *, jobject, jint, jbyteArray, jbyteArray);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp b/mobicore/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp
new file mode 100644 (file)
index 0000000..f265c1e
--- /dev/null
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+
+#include "com_gd_mobicore_pa_jni_CommonPAWrapper.h"
+#include "CmpCommands.h"
+#include "CmpResponses.h"
+#include "JniHelpers.h"
+
+#include "rootpaErrors.h"
+#include "logging.h"
+#include "provisioningagent.h"
+
+#define CERT_PATH "/system/etc/security/cacerts"
+#define HARDCODED_STORAGEPATH "/data/data/com.gd.mobicore.pa"
+
+JavaVM* jvmP_ = NULL;
+const jint VERSION=JNI_VERSION_1_2;
+
+/* Original params list : (JavaVM* jvm, void* reserved)*/
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* jvm, void*)
+{
+// remember JVM pointer:
+       jvmP_ = jvm;
+    LOGD("JNI_OnLoad jvmP_ set %ld\n", (long int) jvmP_);
+       return VERSION;
+}
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_openSession(JNIEnv *, jobject)
+{
+    return (jint) openSessionToCmtl();
+}
+
+JNIEXPORT void JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_closeSession(JNIEnv *, jobject)
+{
+    closeSessionToCmtl();
+}
+
+/* Original params list : (JNIEnv* env, jobject, jint uid, jobject inCommands, jobject outResults)*/
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_executeCmpCommands
+  (JNIEnv* env, jobject, jint, jobject inCommands, jobject outResults)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_executeCmpCommands\n");
+    int ret=ROOTPA_OK;
+    uint32_t internalError=0;
+
+    CmpCommands inCmd(env, inCommands);
+    int numberOfCommands=inCmd.numberOfElements();
+
+    if(0==numberOfCommands){
+        LOGD("No commands received, returning ROOTPA_COMMAND_NOT_SUPPORTED\n");
+        return ROOTPA_COMMAND_NOT_SUPPORTED;
+    }
+
+    CmpMessage* commands = new CmpMessage[numberOfCommands];
+    if(NULL==commands) return ROOTPA_ERROR_OUT_OF_MEMORY;
+    memset(commands, 0, numberOfCommands*sizeof(CmpMessage));
+
+    CmpMessage* responses = new CmpMessage[numberOfCommands];
+    if(NULL==responses)
+    {
+        delete [] commands;
+        return ROOTPA_ERROR_OUT_OF_MEMORY;
+    }
+    memset(responses, 0, numberOfCommands*sizeof(CmpMessage));
+
+    if(inCmd.getCommands(commands)==false)
+    {
+        LOGE("getting commands on C side of the wrapper failed\n");
+        ret=ROOTPA_ERROR_INTERNAL;
+    }
+    else
+    {
+        ret=executeCmpCommands(numberOfCommands, commands, responses, &internalError);
+        CmpResponses outRsp(env, outResults);
+        if(ret!=ROOTPA_OK)
+        {
+            LOGE("call to executeCmpCommands failed %d %d\n", ret, internalError);
+            (void) outRsp.update(responses, numberOfCommands); // don't overwrite the return code but still try to copy the results
+        }
+        else
+        {
+            ret=outRsp.update(responses, numberOfCommands);
+        }
+    }
+
+// cleanup
+
+    for(int i=0; i<numberOfCommands; i++)
+    {
+        delete [] commands[i].contentP;
+        free(responses[i].contentP); // this is reserved with malloc
+    }
+    delete [] commands;
+    delete [] responses;
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_executeCmpCommands %d\n", ret);
+
+    return ret;
+}
+
+#define VERSION_FIELD_TAG "TAG"
+#define VERSION_FIELD_TAG1ALL "TAG1ALL"
+#define VERSION_FIELD_MCI "MCI"
+#define VERSION_FIELD_SO "SO"
+#define VERSION_FIELD_MCLF "MCLF"
+#define VERSION_FIELD_CONT "CONT"
+#define VERSION_FIELD_MCCONF "MCCONF"
+#define VERSION_FIELD_TLAPI "TLAPI"
+#define VERSION_FIELD_DRAPI "DRAPI"
+#define VERSION_FIELD_CMP "CMP"
+
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getVersion
+  (JNIEnv* env, jobject, jbyteArray productId, jobject keys, jobject values)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getVersion %x %x %x\n", productId, keys, values);
+    int ret=ROOTPA_OK;
+    int tag=0;
+    mcVersionInfo_t version;
+
+    ret=getVersion(&tag, &version);
+    if(ROOTPA_OK == ret)
+    {
+        JniHelpers jniHelp(env, &keys, &values, &productId);
+
+        ret=jniHelp.setVersion((char*) VERSION_FIELD_TAG, tag);
+        if(ROOTPA_OK == ret)
+        {
+            ret=jniHelp.setProductId((char*) version.productId);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_MCI, version.versionMci);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_SO, version.versionSo);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_MCLF, version.versionMclf);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_CONT, version.versionContainer);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_MCCONF, version.versionMcConfig);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_TLAPI, version.versionTlApi);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_DRAPI, version.versionDrApi);
+            if(ret != ROOTPA_OK) return ret;
+            ret=jniHelp.setVersion((char*) VERSION_FIELD_CMP, version.versionCmp);
+            if(tag!=2)
+            {
+                LOGE("Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getVersion unknown tag %d, version information may be wrong\n", tag);
+                ret=ROOTPA_ERROR_INTERNAL;
+            }
+        }
+    }
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getVersion %x %x %x\n", productId, keys, values);
+    return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSuid
+  (JNIEnv* env, jobject, jbyteArray suid)
+{
+    int ret=ROOTPA_OK;
+    mcSuid_t mySuid;
+
+    ret=getSuid(&mySuid);
+    if(ROOTPA_OK == ret)
+    {
+        JniHelpers jniHelp(env);
+        ret=jniHelp.setByteArray(&suid, (uint8_t*)&mySuid, sizeof(mySuid));
+    }
+    return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_isRootContainerRegistered
+  (JNIEnv* envP, jobject, jbooleanArray result)
+{
+    int ret=ROOTPA_OK;
+    bool isRegistered;
+
+    ret=isRootContainerRegistered(&isRegistered);
+    if(ROOTPA_OK == ret)
+    {
+        JniHelpers jniHelp(envP);
+        ret=jniHelp.setBooleanToArray(&result, isRegistered);
+    }
+    return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_isSpContainerRegistered
+  (JNIEnv* envP, jobject, jint spid, jbooleanArray result)
+{
+    int ret=ROOTPA_OK;
+    bool isRegistered;
+
+    ret=isSpContainerRegistered((mcSpid_t) spid, &isRegistered);
+    if(ROOTPA_OK == ret)
+    {
+        JniHelpers jniHelp(envP);
+        ret=jniHelp.setBooleanToArray(&result, isRegistered);
+    }
+    return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSPContainerState
+  (JNIEnv* envP, jobject, jint spid, jintArray stateArray)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSpContainerState\n");
+    int ret=ROOTPA_OK;
+    int state;
+
+    ret=getSpContainerState((mcSpid_t) spid, (mcContainerState_t*) &state);
+    if(ROOTPA_OK == ret)
+    {
+        JniHelpers jniHelp(envP);
+        ret=jniHelp.setIntToArray(&stateArray, 0, state);
+    }
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSpContainerState\n");
+    return ret;
+}
+
+const int CONTAINER_STATE_IDX=0;
+const int NUMBER_OF_TLTS_IDX=1;
+const int NUMBER_OF_ELEMENTS=2;
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSPContainerStructure
+  (JNIEnv* envP, jobject, jint spid, jintArray ints, jobjectArray uuidArray, jintArray trustletStates)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSPContainerStructure\n");
+    int ret=ROOTPA_OK;
+    int state;
+
+    SpContainerStructure spContainerStructure;
+
+    ret=getSpContainerStructure((mcSpid_t) spid, &spContainerStructure);
+    if(ROOTPA_OK == ret)
+    {
+        JniHelpers jniHelp(envP);
+
+        ret=jniHelp.setIntToArray(&ints, CONTAINER_STATE_IDX, spContainerStructure.state);
+        if(ROOTPA_OK==ret)
+        {
+            ret=jniHelp.setIntToArray(&ints, NUMBER_OF_TLTS_IDX, spContainerStructure.nbrOfTlts);
+            if(ROOTPA_OK==ret)
+            {
+                for(int i=0; i<spContainerStructure.nbrOfTlts;i++)
+                {
+                    LOGD("TLT %d/%d %.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x",i, spContainerStructure.nbrOfTlts, spContainerStructure.tltContainers[i].uuid.value[0],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[1],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[2],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[3],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[4],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[5],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[6],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[7],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[8],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[9],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[10],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[11],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[12],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[13],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[14],
+                                                                                                             spContainerStructure.tltContainers[i].uuid.value[15]);
+
+                    ret=jniHelp.setIntToArray(&trustletStates, i, spContainerStructure.tltContainers[i].state);
+                    jbyteArray uuid = jniHelp.byteArrayToJByteArray(spContainerStructure.tltContainers[i].uuid.value, UUID_LENGTH);
+                    envP->SetObjectArrayElement(uuidArray, i, (jobject) uuid);
+                    envP->DeleteLocalRef(uuid);
+                }
+            }
+            else
+            {
+                LOGE("..._jni_CommonPAWrapper_getSPContainerStructure copy number of trustlets failed\n");
+            }
+        }
+        else
+        {
+            LOGE("..._jni_CommonPAWrapper_getSPContainerStructure copy container state failed\n");
+        }
+    }
+    else
+    {
+        LOGE("..._jni_CommonPAWrapper_getSPContainerStructure getSpContainerStructure failed\n");
+    }
+
+
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_getSPContainerStructure %d\n", ret);
+    return ret;
+}
+
+jmethodID provisioningStateCallback_=NULL;
+jmethodID getSystemInfoCallback_=NULL;
+jmethodID trustletInstallCallback_=NULL;
+jobject obj_=NULL;
+
+void stateUpdateCallback(ProvisioningState state, rootpaerror_t error, tltInfo_t* tltInfoP)
+{
+    LOGD(">>stateUpdateCallback %d %d\n", state, error);
+
+    JNIEnv* envP=NULL;
+
+    // it is enough to call this only once for each thread but since this is
+    // the best place to call it we call it every time
+
+    jint res = jvmP_->AttachCurrentThread(&envP, NULL);
+
+    if(NULL==obj_ ||NULL==provisioningStateCallback_ || NULL== envP || res != JNI_OK)
+    {
+        LOGE("obj=%ld, provisioningStateCallback==%ld, envP==%ld res==%d", (long int) obj_, (long int) provisioningStateCallback_, (long int) envP, res);
+    }
+    else if(PROVISIONING_STATE_INSTALL_TRUSTLET == state)
+    {
+        if(tltInfoP)
+        {
+            LOGD("installing trustled");
+            JniHelpers jniHelp(envP);
+            jbyteArray trustlet=jniHelp.byteArrayToJByteArray(tltInfoP->trustletP, tltInfoP->trustletSize);
+            envP->CallVoidMethod(obj_, trustletInstallCallback_, trustlet);
+        }
+        else
+        {
+               envP->CallVoidMethod(obj_, provisioningStateCallback_, ERROR_STATE, ROOTPA_ERROR_INTERNAL);
+        }
+    }
+    else
+    {
+        envP->CallVoidMethod(obj_, provisioningStateCallback_, state, error);
+    }
+
+    if( obj_!=NULL && (PROVISIONING_STATE_THREAD_EXITING == state) )
+    {
+        LOGD("deleting global reference to obj_ (envP %ld)", envP);
+        if(envP!=NULL) envP->DeleteGlobalRef(obj_);
+        obj_=NULL;
+    }
+
+    // doing this in every round in order to make sure what is attached will be detached and that
+    // envP is correctly updated at every round (it seems to work also inside the above if statement,
+    // but calling AttachCurrentThread to already attached thread is is supposed to be no-op. It seems
+    // to update the envP though.)
+    // If the thread is not detached there will be a crash when the thread exists
+    jvmP_->DetachCurrentThread();
+
+    LOGD("<<stateUpdateCallback\n");
+}
+
+void storeCallbackMethodIds(JNIEnv* envP)
+{
+    LOGD(">>storeCallbackMethodIds\n");
+
+    jclass cls = envP->GetObjectClass(obj_);
+    if(NULL==cls)
+    {
+        LOGE("storeCallbackMethodIds cls(obj_)==NULL");
+        return;
+    }
+    provisioningStateCallback_ = envP->GetMethodID(cls, "provisioningStateCallback","(II)V");
+    if(NULL==provisioningStateCallback_)
+    {
+        LOGE("storeCallbackMethodIds provisioningStateCallback_==NULL");
+    }
+
+
+    getSystemInfoCallback_ = envP->GetMethodID(cls, "getSystemInfo","()[Ljava/lang/String;");
+    if(NULL==getSystemInfoCallback_)
+    {
+        LOGE("storeCallbackMethodIds getSystemInfoCallback_==NULL");
+    }
+
+    trustletInstallCallback_ = envP->GetMethodID(cls, "trustletInstallCallback","([B)V");
+    if(NULL==trustletInstallCallback_)
+    {
+        LOGE("storeCallbackMethodIds trustletInstallCallback_==NULL");
+    }
+
+    if(cls!=NULL)
+    {
+        envP->DeleteLocalRef(cls);
+    }
+
+    LOGD("<<storeCallbackMethodIds\n");
+}
+
+/*
+This function has to be called before any communication with SE is done (or actually,
+before any xml parsing is done.
+*/
+void setFilesPath(JNIEnv* envP, jobject obj)
+{
+    LOGD(">>setFilesPath\n");
+
+    jclass cls = envP->GetObjectClass(obj);
+    if(NULL==cls)
+    {
+        LOGE("setFilesPath cls(obj)==NULL");
+        return;
+    }
+    jmethodID getFilesDirPath = envP->GetMethodID(cls, "getFilesDirPath","()Ljava/lang/String;");
+    if(NULL==getFilesDirPath)
+    {
+        setPaths(HARDCODED_STORAGEPATH, CERT_PATH);
+        LOGE("<<setFilesPath getFilesDirPath==NULL, used hardcoded paths");
+        return;
+    }
+
+    jobject jpath = envP->CallObjectMethod(obj, getFilesDirPath);
+    if(jpath!=NULL)
+    {
+        const char* pathP = envP->GetStringUTFChars((jstring)jpath, NULL);
+        setPaths(pathP, CERT_PATH);
+        if(NULL == pathP)
+        {
+            LOGE("setFilesPath pathP==NULL");
+        }
+
+//        LOGD("path: %s\n", pathP);
+        envP->ReleaseStringUTFChars((jstring)jpath, pathP);
+    }
+    else
+    {
+        LOGE("setFilesPath jpath==NULL, using hardcoded paths");
+        setPaths(HARDCODED_STORAGEPATH, CERT_PATH);
+    }
+
+    if(cls!=NULL)
+    {
+        envP->DeleteLocalRef(cls);
+    }
+
+    LOGD("<<setFilesPath\n");
+}
+
+const int IMEI_ESN_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_IMEI_ESN_INDEX;
+const int MNO_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_MNO_INDEX;
+const int BRAND_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_BRAND_INDEX;
+const int MANUFACTURER_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_MANUFACTURER_INDEX;
+const int HARDWARE_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_HARDWARE_INDEX;
+const int MODEL_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_MODEL_INDEX;
+const int VERSION_INDEX=com_gd_mobicore_pa_jni_CommonPAWrapper_VERSION_INDEX;
+
+void copyElement(JNIEnv* envP, char** target, jstring source)
+{
+    if(source != NULL)
+    {
+        const char* tmp=envP->GetStringUTFChars(source, NULL);
+        *target=(char*)malloc(strlen(tmp)+1);
+        if(*target!=NULL)
+        {
+            strcpy(*target, tmp);
+        }
+        envP->ReleaseStringUTFChars(source, tmp);
+    }
+    else
+    {
+        *target=NULL;
+    }
+}
+
+rootpaerror_t getSystemInfoCallback(osInfo_t* osSpecificInfoP)
+{
+    LOGD(">>getSystemInfoCallback\n");
+    rootpaerror_t ret=ROOTPA_OK;
+
+    if(NULL==osSpecificInfoP) return ROOTPA_ERROR_INTERNAL;
+
+    memset(osSpecificInfoP, 0, sizeof(osInfo_t));
+
+    JNIEnv* envP=NULL;
+    jint res = jvmP_->AttachCurrentThread(&envP, NULL);
+
+
+    if(NULL==obj_ ||NULL==getSystemInfoCallback_ || NULL== envP || res != JNI_OK)
+    {
+        ret=ROOTPA_ERROR_INTERNAL;
+        LOGE("obj=%ld, getSystemInfoCallback_==%ld, envP==%ld res==%d", (long int) obj_, (long int) getSystemInfoCallback_, (long int) envP, res);
+    }
+    else
+    {
+        jobjectArray systemInfo = (jobjectArray) envP->CallObjectMethod(obj_, getSystemInfoCallback_);
+        if(systemInfo!=NULL)
+        {
+            jstring imeiEsn=(jstring) envP->GetObjectArrayElement(systemInfo, IMEI_ESN_INDEX);
+            jstring mno=(jstring) envP->GetObjectArrayElement(systemInfo, MNO_INDEX);
+            jstring brand=(jstring) envP->GetObjectArrayElement(systemInfo, BRAND_INDEX);
+            jstring manufacturer=(jstring) envP->GetObjectArrayElement(systemInfo, MANUFACTURER_INDEX);
+            jstring hw=(jstring) envP->GetObjectArrayElement(systemInfo, HARDWARE_INDEX);
+            jstring model=(jstring) envP->GetObjectArrayElement(systemInfo, MODEL_INDEX);
+            jstring version=(jstring) envP->GetObjectArrayElement(systemInfo, VERSION_INDEX);
+
+            copyElement(envP, &osSpecificInfoP->imeiEsnP, imeiEsn);
+            copyElement(envP, &osSpecificInfoP->mnoP, mno);
+            copyElement(envP, &osSpecificInfoP->brandP, brand);
+            copyElement(envP, &osSpecificInfoP->manufacturerP, manufacturer);
+            copyElement(envP, &osSpecificInfoP->hardwareP, hw);
+            copyElement(envP, &osSpecificInfoP->modelP, model);
+            copyElement(envP, &osSpecificInfoP->versionP, version);
+
+            envP->DeleteLocalRef(systemInfo);
+            if(imeiEsn!=NULL) envP->DeleteLocalRef(imeiEsn);
+            if(mno!=NULL) envP->DeleteLocalRef(mno);
+            if(brand!=NULL) envP->DeleteLocalRef(brand);
+            if(manufacturer!=NULL) envP->DeleteLocalRef(manufacturer);
+            if(hw!=NULL) envP->DeleteLocalRef(hw);
+            if(model!=NULL) envP->DeleteLocalRef(model);
+            if(version!=NULL) envP->DeleteLocalRef(version);
+        }
+    }
+
+    // doing this in every round in order to make sure what is attached will be detached and that
+    // envP is correctly updated at every round (it seems to work also inside the above if, but
+    // calling AttachCurrentThread to already attched thread is is supposed to be no-op. It seems to
+    // update the envP though.)
+    // If the thread is not detached there will be a crash when the thread exists
+    jvmP_->DetachCurrentThread();
+
+    LOGD("<<getSystemInfoCallback %d\n", ret);
+    return ret;
+}
+
+/* Original params list : (JNIEnv* envP, jobject obj, jint uid, jint spid, jbyteArray seAddress)*/
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_doProvisioning
+  (JNIEnv* envP, jobject obj, jint, jint spid, jbyteArray seAddress)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_doProvisioning %ld %ld\n", (long int) stateUpdateCallback, (long int) getSystemInfoCallback);
+    setFilesPath(envP, obj);
+    int ret=ROOTPA_OK;
+
+    if(seAddress)
+    {
+        uint32_t length=0;
+        JniHelpers jniHelp(envP);
+        char*  addrP=(char*)jniHelp.jByteArrayToCByteArray(seAddress, &length);
+        ret=setSeAddress(addrP, length);
+        delete[] addrP;
+    }
+
+    if(ROOTPA_OK==ret)
+    {
+        obj_= envP->NewGlobalRef(obj);
+        storeCallbackMethodIds(envP);
+        ret=doProvisioning(spid, stateUpdateCallback, getSystemInfoCallback);
+    }
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_doProvisioning %d\n", ret);
+    return ret;
+}
+
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet
+(JNIEnv* envP, jobject obj,
+jint spid,
+jbyteArray uuid,
+jint requestDataType,
+jbyteArray tltOrKeyData,
+jint minTltVersion,
+jbyteArray tltPukHash,
+jint memoryType,
+jint numberOfInstances,
+jint flags,
+jbyteArray seAddress)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet %ld %ld\n", (long int) stateUpdateCallback, (long int) getSystemInfoCallback);
+    setFilesPath(envP, obj);
+    int ret=ROOTPA_OK;
+    JniHelpers jniHelp(envP);
+
+    if(seAddress)
+    {
+        uint32_t length=0;
+        char*  addrP=(char*)jniHelp.jByteArrayToCByteArray(seAddress, &length);
+        ret=setSeAddress(addrP, length);
+        delete[] addrP;
+    }
+
+    if(ROOTPA_OK==ret)
+    {
+        obj_= envP->NewGlobalRef(obj);
+        storeCallbackMethodIds(envP);
+        trustletInstallationData_t tltData;
+        tltData.dataP=(uint8_t*) jniHelp.jByteArrayToCByteArray(tltOrKeyData, &tltData.dataLength);
+        tltData.dataType=(TltInstallationRequestDataType) requestDataType;
+        tltData.minTltVersion=minTltVersion;
+        tltData.tltPukHashP=(uint8_t*) jniHelp.jByteArrayToCByteArray(tltPukHash, &tltData.tltPukHashLength);
+        tltData.memoryType=memoryType;
+        tltData.numberOfInstances=numberOfInstances;
+        tltData.flags=flags;
+
+        uint32_t uuidLength=0;
+        uint8_t* uuidP=(uint8_t*) jniHelp.jByteArrayToCByteArray(uuid, &uuidLength);
+        if(UUID_LENGTH != uuidLength){
+            LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet, wrong uuidLength %d, not installing\n", uuidLength);
+            free(uuidP);
+            return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+        }
+        memcpy(tltData.uuid.value, uuidP, UUID_LENGTH);
+        free(uuidP);
+        ret=installTrustlet(spid, stateUpdateCallback, getSystemInfoCallback, &tltData);
+    }
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet %d\n", ret);
+    return ret;
+}
+
+
+
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_unregisterRootContainer(JNIEnv* envP, jobject obj,  jbyteArray seAddress)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_unregisterRootContainer\n");
+    setFilesPath(envP, obj);
+    int ret=ROOTPA_OK;
+    JniHelpers jniHelp(envP);
+
+    if(seAddress)
+    {
+        uint32_t length=0;
+        char*  addrP=(char*)jniHelp.jByteArrayToCByteArray(seAddress, &length);
+        ret=setSeAddress(addrP, length);
+        delete[] addrP;
+    }
+
+    if(ROOTPA_OK==ret)
+    {
+        obj_= envP->NewGlobalRef(obj);
+        storeCallbackMethodIds(envP);
+        ret=unregisterRootContainer(stateUpdateCallback, getSystemInfoCallback);
+    }
+
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_unregisterRootContainer\n");
+
+    return ret;
+}
+
+char* addTrailingZero(uint8_t* vP, uint32_t length)
+{
+    char* newVP = new char[length+1];
+    if(NULL!=newVP)
+    {
+        memcpy(newVP, vP, length);
+        newVP[length]=0;
+    }
+    delete [] vP;
+    return newVP;
+}
+
+/* Original params list : (JNIEnv* envP, jobject obj, jbyteArray variable_name, jbyteArray value)*/
+JNIEXPORT void JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable(JNIEnv* envP, jobject, jbyteArray variable_name, jbyteArray value)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable");
+    JniHelpers jniHelp(envP);
+    uint32_t length=0;
+    char* envVarP=NULL;
+    char* envValP=NULL;
+    uint8_t*  vP=jniHelp.jByteArrayToCByteArray(variable_name, &length);
+
+    if(NULL==vP)
+    {
+        LOGE("Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable, FAILURE: can not get variable\n");
+        return;
+    }
+
+    envVarP = addTrailingZero(vP, length);
+    if(value!=NULL)
+    {
+        vP=jniHelp.jByteArrayToCByteArray(value, &length);
+        if(NULL!=vP)
+        {
+            envValP = addTrailingZero(vP, length);
+            if(envVarP && envValP)
+            {
+                LOGD("setting environment variable, %s %s", envVarP, envValP);
+                if(setenv(envVarP, envValP, 1)!=0)
+                {
+                    LOGE("Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable, setenv %s FAILURE\n", envVarP);
+                }
+            }
+        }
+        else
+        {
+            LOGE("Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable, FAILURE: can not get value\n");
+        }
+    }
+    else
+    {
+        LOGD("unsetting environment variable, %s", envVarP);
+        if(unsetenv(envVarP)!=0)
+        {
+            LOGE("Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable, unsetenv %s FAILURE\n", envVarP);
+        }
+    }
+
+    delete[] envVarP;
+    delete[] envValP;
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_setEnvironmentVariable");
+}
+
+/* Original params list : (JNIEnv* envP, jobject obj, jint spid, jbyteArray uuid, jbyteArray taBin)*/
+JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_storeTA(JNIEnv* envP, jobject, jint spid, jbyteArray uuid, jbyteArray taBin)
+{
+    LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_storeTA");
+    int ret=ROOTPA_OK;
+    JniHelpers jniHelp(envP);
+
+    uint32_t uuidLength=0;
+    uint8_t* uuidP=(uint8_t*) jniHelp.jByteArrayToCByteArray(uuid, &uuidLength);
+
+    if(UUID_LENGTH != uuidLength){
+        LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_storeTA, wrong uuidLength %d, not installing\n", uuidLength);
+        free(uuidP);
+        return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+    mcUuid_t mcUuid;
+    memcpy(mcUuid.value, uuidP, UUID_LENGTH);
+    free(uuidP);
+
+    uint32_t taBinLength=0;
+    uint8_t* taBinP=(uint8_t*) jniHelp.jByteArrayToCByteArray(taBin, &taBinLength);
+    if(0==taBinLength){
+        LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_storeTA, no taBin\n", taBinLength);
+        free(taBinP);
+        return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+
+    ret=storeTA((mcSpid_t)spid, &mcUuid, taBinP, taBinLength);
+    free(taBinP);
+
+    LOGD("<<Java_com_gd_mobicore_pa_jni_CommonPAWrapper_storeTA %d", ret);
+    return ret;
+}
+
diff --git a/mobicore/rootpa/Code/Android/app/jni/McStub/Android.mk b/mobicore/rootpa/Code/Android/app/jni/McStub/Android.mk
new file mode 100644 (file)
index 0000000..4cfc9df
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# Copyright Â© Trustonic Limited 2013
+#
+# All rights reserved.
+#
+#  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. Neither the name of the Trustonic Limited nor the names of its contributors 
+#     may be used to endorse or promote products derived from this software 
+#     without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+#
+# makefile for building the MobiCore stub library
+#
+
+ifeq ($(ROOTPA_MODULE_TEST), 1)
+
+    LOCAL_PATH := $(call my-dir)
+    include $(CLEAR_VARS)
+
+    LOCAL_CFLAGS += -DANDROID_ARM=1
+    LOCAL_CFLAGS += -DANDROID
+
+    LOCAL_MODULE    := McStub
+    LOCAL_SRC_FILES += ../../../../../Test/Common/mcStub/mcStub.c
+
+    LOCAL_C_INCLUDES += $(MOBICORE_DIR_INC)
+    LOCAL_C_INCLUDES += $(MOBICORE_DIR_INC)/TlCm
+    LOCAL_C_INCLUDES += $(MOBICOREDRIVER_DIR_INC)
+    LOCAL_C_INCLUDES +=  $(LOCAL_PATH)/../../../../Common/include
+       APP_PIE := true
+       LOCAL_32_BIT_ONLY := true
+       
+    include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/mobicore/rootpa/Code/Android/app/jni/McStub/NOTICE b/mobicore/rootpa/Code/Android/app/jni/McStub/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/rootpa/Code/Android/app/proguard-project.txt b/mobicore/rootpa/Code/Android/app/proguard-project.txt
new file mode 100644 (file)
index 0000000..39b3569
--- /dev/null
@@ -0,0 +1,73 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+############## proguard-android.txt
+
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+
+-dontoptimize
+-dontpreverify
+
+-keepattributes *Annotation*
+-keep public class com.google.vending.licensing.ILicensingService
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keepclassmembers public class * extends android.view.View {
+   void set*(***);
+   *** get*();
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}
+
+-keepclassmembers class **.R$* {
+    public static <fields>;
+}
+
+-dontwarn android.support.**
+
+##############
+
+
+# plus rootpa specifics
+
+-dontobfuscate
+
+-keep class com.gd.mobicore.pa.ifc.* { public *; }
+-keep class com.gd.mobicore.pa.jni.CommonPAWrapper { public *; }
+
+
diff --git a/mobicore/rootpa/Code/Android/app/project.properties b/mobicore/rootpa/Code/Android/app/project.properties
new file mode 100644 (file)
index 0000000..f91ff48
--- /dev/null
@@ -0,0 +1,19 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+proguard.config=proguard-project.txt
+
+android.library.reference.1=../lib/
+
+# Project target.
+
+target=android-16
diff --git a/mobicore/rootpa/Code/Android/app/res/values/strings.xml b/mobicore/rootpa/Code/Android/app/res/values/strings.xml
new file mode 100644 (file)
index 0000000..bc5debf
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="description_oempermission">
+        This permission allows the application to remove the root container that is used by the secure OS (Mobicore). 
+        Removing the root container disables all the installed secure applications that are running on the secure OS 
+        so that they can not be executed before the rootcontainer and the applications are re-installed. Secure application 
+        is an application that is not running on the secure OS (Mobicore) rather than on the main os (Android).  
+        Android application the communites with it in order to perform some security critical tasks.
+    </string>
+    <string name="description_developerpermission">
+        This permission allows the application to install a secure application that is not controlled by any TSM (trusted service manager) 
+        and thus can only be removed by uninstalling (this) application that installed it. Secure application is an application that is not 
+        running on the secure OS (Mobicore) rather than on the main os (Android).  Android application the communites with it in order 
+        to perform some security critical tasks.
+    </string>
+</resources>
diff --git a/mobicore/rootpa/Code/Android/app/res/values/version.xml b/mobicore/rootpa/Code/Android/app/res/values/version.xml
new file mode 100644 (file)
index 0000000..e549bde
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+<string name="name">3.96</string>
+<integer name="code">0x30060</integer>
+</resources>
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.class b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.class
new file mode 100644 (file)
index 0000000..f2b1889
Binary files /dev/null and b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.class differ
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java
new file mode 100644 (file)
index 0000000..36abbe9
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// Wrapper class for common C part of the Root Provisioning Agent, the C
+// files under Android/jni
+//
+
+package com.gd.mobicore.pa.jni;
+
+import com.gd.mobicore.pa.service.Log;
+import android.os.Build;
+import android.os.Build.VERSION;
+import android.telephony.TelephonyManager;
+import android.content.Context;
+
+import java.util.List;
+import com.gd.mobicore.pa.service.BaseService;
+import com.gd.mobicore.pa.ifc.CmpCommand;
+import com.gd.mobicore.pa.ifc.CmpResponse;
+
+public class CommonPAWrapper {
+    private static final String TAG = "RootPA-J";
+    private BaseService service_;
+
+    public CommonPAWrapper(BaseService service){
+        service_=service;
+        Log.d(TAG,"CommonPAWrapper.java: constructor");
+    }
+
+    public native int openSession();
+    public native void closeSession();
+    public native int executeCmpCommands(int uid, List<CmpCommand> commands, List<CmpResponse> responses);
+    public native int getVersion(byte[] productId, List<String> keys, List<Integer> values);
+    public native int getSuid(byte[] suid);
+    public native int isRootContainerRegistered(boolean[] result);
+    public native int isSpContainerRegistered(int spid, boolean[] result);
+    public native int getSPContainerState(int spid, int[] state);
+    public native int getSPContainerStructure(int spid, int[] ints, byte[][] uuidArray, int[] trustletStates);
+    public native int doProvisioning(int uid, int spid, byte[] seAddress);
+       public native int installTrustlet(int spid,
+                                      byte[] uuid,
+                                      int dataType,
+                                      byte[] tltOrKeyData,
+                                      int minTltVersion,
+                                      byte[] tltPukHash,
+                                      int memoryType,
+                                      int numberOfInstances,
+                                      int flags,
+                                      byte[] seAddress);
+    public native int unregisterRootContainer(byte[] seAddress);
+    public native int storeTA(int spid, byte[] uuid, byte[] taBinary);
+    public native void setEnvironmentVariable(byte[] variable, byte[] value);
+
+    static{
+        Log.d(TAG,"CommonPAWrapper.java: static");
+       try {
+            System.loadLibrary("commonpawrapper");
+       } catch (Throwable e) {
+            Log.d(TAG,"loading common wrapper failed, trying to load test");
+             System.loadLibrary("commonpawrapper_test");
+        }
+    }
+
+    // callbacks from C code
+
+     public String getFilesDirPath(){
+        Log.d(TAG,"CommonPAWrapper.getFilesDirPath");
+        return service_.getFilesDirPath();
+     }
+
+     public void provisioningStateCallback(int state, int ret){
+        Log.d(TAG,"CommonPAWrapper.provisioningStateCallback");
+        service_.provisioningStateCallback(state, ret);
+     }
+
+    private static final int IMEI_ESN_INDEX=0;
+    private static final int MNO_INDEX=1;
+    private static final int BRAND_INDEX=2;
+    private static final int MANUFACTURER_INDEX=3;
+    private static final int HARDWARE_INDEX=4;
+    private static final int MODEL_INDEX=5;
+    private static final int VERSION_INDEX=6;
+    private static final int RESPONSE_ARRAY_SIZE=7;
+
+    public String[] getSystemInfo(){
+        Log.d(TAG,">>CommonPAWrapper.getSystemInfo");
+        String[] response= new String[RESPONSE_ARRAY_SIZE];
+        response[IMEI_ESN_INDEX]="";
+        response[MNO_INDEX]="";
+        response[BRAND_INDEX]=Build.BRAND;
+        response[MANUFACTURER_INDEX]=Build.MANUFACTURER;
+        response[HARDWARE_INDEX]=Build.HARDWARE;
+        response[MODEL_INDEX]=Build.MODEL;
+        response[VERSION_INDEX]=Build.VERSION.CODENAME+" "+Build.VERSION.INCREMENTAL+" "+Build.VERSION.RELEASE+" "+Integer.toString(Build.VERSION.SDK_INT);
+
+        Log.d(TAG,"<<CommonPAWrapper.getSystemInfo "+response[IMEI_ESN_INDEX]+" "+response[MANUFACTURER_INDEX]+" "+response[VERSION_INDEX]);
+        return response;
+     }
+
+
+    public void trustletInstallCallback(byte[] trustlet){
+        Log.d(TAG,">>CommonPAWrapper.trustletInstallCallback "+trustlet.length);
+        service_.trustletInstallCallback(trustlet);
+        Log.d(TAG,"<<CommonPAWrapper.trustletInstallCallback");
+    }
+}
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/BaseService.java b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/BaseService.java
new file mode 100644 (file)
index 0000000..8c8bb2a
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.net.NetworkInfo;
+import android.net.ConnectivityManager;
+
+import java.io.File;
+import java.net.URI;
+import java.net.Proxy;
+import java.net.Proxy.Type;
+import java.net.ProxySelector;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.gd.mobicore.pa.jni.CommonPAWrapper;
+import com.gd.mobicore.pa.ifc.RootPAProvisioningIntents;
+import com.gd.mobicore.pa.ifc.CommandResult;
+
+public abstract class BaseService extends Service {
+    protected static final String TAG = "RootPA-J";
+
+    /*
+        being statically linked library, the Common C implementation does not handle locks,
+        they must be handled in the using implementation, in this case here.
+    */
+    private static final int LOCK_FREE=0;
+    private static final AtomicInteger lock_= new AtomicInteger(LOCK_FREE);
+    private static final int LOCK_TIMEOUT_MS=300000; //5 mins in ms
+    private TimerTask timerTask_=null;
+    private Timer timer_=null;
+
+    protected int doProvisioningLockSuid_=0;
+    protected byte[] se_ = null;
+
+    private static final int C_CONNECTING_SERVICE_ENABLER=1;
+    private static final int C_AUTHENTICATING_SOC=2;
+    private static final int C_CREATING_ROOT_CONTAINER=3;
+    private static final int C_AUTHENTICATING_ROOT=4;
+    private static final int C_CREATING_SP_CONTAINER=5;
+    private static final int C_FINISHED_PROVISIONING=6;
+    private static final int C_ERROR=7;
+    private static final int C_UNREGISTERING_ROOT_CONTAINER=8;
+    private static final int C_PROVISIONING_STATE_THREAD_EXITING=0xDEAD;
+
+    protected final CommonPAWrapper commonPaWrapper_=new CommonPAWrapper(this);
+    private boolean sessionOpened_=false;
+
+    protected CommonPAWrapper commonPAWrapper(){
+        return commonPaWrapper_;
+    }
+
+    protected synchronized CommandResult acquireLock(int uid, boolean openSession){
+        Log.d(TAG,">>BaseService.acquireLock "+uid+" "+lock_.get()+" "+timer_);
+        if(uid==LOCK_FREE){
+            return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+        }
+        boolean result=lock_.compareAndSet(LOCK_FREE, uid);
+        if(result==true || lock_.get() == uid){
+
+            if(result==true && openSession==true && sessionOpened_==false){
+                Log.d(TAG,"BaseService.acquireLock, openingSession");
+                commonPAWrapper().openSession();
+                sessionOpened_=true;
+            }
+
+            if(timer_!=null){
+                timerTask_.cancel();
+                timer_.cancel();
+            }
+
+            timer_=new Timer();
+            timerTask_=new TimerTask(){
+                public void run(){
+                    Log.i(TAG,"Timer expired, releasing lock");
+                    lock_.set(LOCK_FREE);
+                    if(sessionOpened_==true){
+                        Log.d(TAG,"BaseService.Timer.run, closingSession");
+                        commonPAWrapper().closeSession();
+                        sessionOpened_=false;
+                    }
+                }
+            };
+            timer_.schedule(timerTask_,LOCK_TIMEOUT_MS);
+            Log.d(TAG,"<<BaseService.acquireLock, successfull return "+timer_);
+            return new CommandResult(CommandResult.ROOTPA_OK);
+        }
+        return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+    }
+
+    // this is public for the ProvisioningService to call it
+    protected synchronized CommandResult releaseLock(int uid, boolean closeSession){
+        Log.d(TAG,"BaseService.releaseLock "+uid+" "+lock_.get()+" "+timer_);
+
+        if(uid==LOCK_FREE){
+            return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+        }
+
+        if((lock_.get()==LOCK_FREE) || (lock_.compareAndSet(uid, LOCK_FREE)==true)){
+
+            if(closeSession==true && sessionOpened_==true){
+                Log.d(TAG,"BaseService.releaseLock, closingSession");
+                commonPAWrapper().closeSession();
+                sessionOpened_=false;
+            }
+
+            if(timer_!=null){
+                timerTask_.cancel();
+                timerTask_=null;
+                timer_.cancel();
+                timer_=null;
+            }
+            return new CommandResult(CommandResult.ROOTPA_OK);
+        }
+        return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+    }
+
+    /**
+        Since libcurl is able to read and use proxy settings from http_proxy environment variable, we set the proxy here.
+        This should be changed every time the connection changes so that there are always correct proxy settings available
+    */
+
+    BroadcastReceiver networkChangeReceiver_=null;
+    protected void setupProxy()
+    {
+        byte[] proxyAddress=null;
+        ProxySelector defaultProxySelector = ProxySelector.getDefault();
+
+        if(defaultProxySelector != null){
+            URI uri=null;
+            List<Proxy> proxyList=null;
+            try{
+                if(se_==null){
+                    uri=new URI("https://se.cgbe.trustonic.com"); // the URI here does not matter a lot, as long as one exists. We try to use as real one as is easily possible
+                }else{
+                    uri=new URI(new String(se_));
+                }
+                proxyList = defaultProxySelector.select(uri);
+                if (proxyList.size() > 0)
+                {
+                    Proxy proxy = proxyList.get(0);
+                    Log.d(TAG,"BaseService.setupProxy proxy "+proxy); // there should be only one element in the list in the current Android versions, it is for the current connection
+                    if(proxy != Proxy.NO_PROXY){
+                        Log.d(TAG,"BaseService.setupProxy proxy.type "+proxy.type());
+                        if(proxy.type()==Proxy.Type.HTTP){
+                            // TODO-future there is currently no way for the user to store proxy user name and password in Android,
+                            // so they need to be asked at connection time. There is not any kind of user/password support for proxies in RootPA.
+                            // If we were able to get username/password we would add them to http(s)_proxy here.
+                            // if(username && password) proxyAddress=username+":"+password; (and add the next line just remove +1 from indexOf)
+                            proxyAddress=proxy.toString().substring(proxy.toString().indexOf("@")+1).getBytes();
+                        }
+                    }
+                }
+
+            }catch(Exception e){
+                Log.e(TAG,"BaseService.setupProxy FAILURE in getting the proxy: "+e.toString());
+            }
+        }
+
+        commonPAWrapper().setEnvironmentVariable("http_proxy".getBytes(), proxyAddress);
+        commonPAWrapper().setEnvironmentVariable("https_proxy".getBytes(), proxyAddress);
+        Log.d(TAG,"BaseService.setupProxy just set the proxy to: "+(proxyAddress==null?proxyAddress:new String(proxyAddress)));
+
+        // start listening to intents on network changes if not doing it already
+        // this is important since the proxy settings are network specific
+        if(networkChangeReceiver_==null){
+            networkChangeReceiver_=new BroadcastReceiver(){
+                public void onReceive(Context ctx, Intent intent){
+                    Log.d(TAG, "BaseService: Network connection changed");
+                    try{
+                        NetworkInfo ni=((ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
+                        if(ni!=null && ni.isConnectedOrConnecting()) {
+                            Log.d(TAG,"BaseService: Network "+ni.getTypeName()+" connected");
+                            setupProxy();
+                        }else{
+                            if(ni!=null){
+                                Log.d(TAG, "BaseService: network state "+ni.getState());
+                            }else{
+                                Log.d(TAG, "BaseService: no network info");
+                            }
+                        }
+                    }catch(Exception e){
+                        Log.e(TAG, "BaseService: Network connection change handling FAILURE "+e);
+                    }
+                }
+            };
+            IntentFilter filter=new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
+            registerReceiver(networkChangeReceiver_, filter);
+        }
+    }
+
+    protected synchronized boolean locked(int uid){
+        return(lock_.get() != uid && uid != LOCK_FREE);
+    }
+
+    /**
+    This method is called from the C code to send the trustlet binary to the client
+    (trustlet connector/"sp.pa" for develope trustlet) that then can store it where desired.
+    */
+    public void trustletInstallCallback(byte[] trustlet){
+        Log.d(TAG,">>BaseService.trustletInstallCallback");
+        Intent intent=new Intent(RootPAProvisioningIntents.INSTALL_TRUSTLET);
+        intent.putExtra(RootPAProvisioningIntents.TRUSTLET, trustlet);
+        sendBroadcast(intent);
+        Log.d(TAG,"<<BaseService.trustletInstallCallback");
+    }
+
+    /**
+    This method is called from the C code to get the path for files directory
+    */
+    public String getFilesDirPath(){
+        File file = this.getFilesDir();
+        if (null != file){
+            return file.getAbsolutePath();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     This method is called from the C code to send the intents while executing doProvisioning
+    */
+    public void provisioningStateCallback(int state, int ret){
+        Log.d(TAG,">>provisioningStateCallback "+state+" "+ret);
+
+        // since sommunication with SE may take consirderable amount of time, we refresh the Lock timer
+        // by calling acquireLock every time a state notification callback is called. This way the lock
+        // will not timeout before the communication with SE is complete.
+        try{
+            CommandResult res=acquireLock(doProvisioningLockSuid_, false);
+            if(!res.isOk()){
+                Log.e(TAG,"provisioningStateCallback re-acquiring lock failed, res: "+res.result());
+            }
+        }catch(Exception e){
+            Log.e(TAG,"provisioningStateCallback re-acquiring lock failed: "+e);
+        }
+
+        Intent intent=new Intent(RootPAProvisioningIntents.PROVISIONING_PROGRESS_UPDATE);
+        switch(state){
+            case C_CONNECTING_SERVICE_ENABLER:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.CONNECTING_SERVICE_ENABLER);
+                break;
+            case C_AUTHENTICATING_SOC:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.AUTHENTICATING_SOC);
+                break;
+            case C_CREATING_ROOT_CONTAINER:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.CREATING_ROOT_CONTAINER);
+                break;
+            case C_AUTHENTICATING_ROOT:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.AUTHENTICATING_ROOT);
+                break;
+            case C_CREATING_SP_CONTAINER:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.CREATING_SP_CONTAINER);
+                break;
+            case C_FINISHED_PROVISIONING:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.FINISHED_PROVISIONING);
+                break;
+            case C_UNREGISTERING_ROOT_CONTAINER:
+                intent.putExtra(RootPAProvisioningIntents.STATE, RootPAProvisioningIntents.UNREGISTERING_ROOT_CONTAINER);
+                break;
+            case C_ERROR:
+                intent=new Intent(RootPAProvisioningIntents.PROVISIONING_ERROR);
+
+                intent.putExtra(RootPAProvisioningIntents.ERROR, ret);
+                break;
+
+            case C_PROVISIONING_STATE_THREAD_EXITING:
+                try{
+                    CommandResult res=releaseLock(doProvisioningLockSuid_, false);
+                    if(!res.isOk()){
+                        Log.e(TAG,"provisioningStateCallback releasing lock failed, res: "+res.result());
+                    }
+                    doProvisioningLockSuid_=0;
+                    intent=null; // no intent sent in this case
+                }catch(Exception e){
+                    Log.e(TAG,"provisioningStateCallback releasing lock failed: "+e);
+                }
+                if(networkChangeReceiver_!=null){
+                    unregisterReceiver(networkChangeReceiver_);
+                    networkChangeReceiver_=null;
+                }
+                sendBroadcast(new Intent(RootPAProvisioningIntents.FINISHED_ROOT_PROVISIONING));
+                break;
+            default:
+                Log.e(TAG,"unknown state: "+state);
+                intent=null;
+                break;
+        }
+        if(intent!=null){
+            sendBroadcast(intent);
+        }
+
+        Log.d(TAG,"<<provisioningStateCallback ");
+    }
+
+    public void onConfigurationChanged(android.content.res.Configuration newConfig){
+        super.onConfigurationChanged(newConfig);
+        Log.d(TAG,"BaseService.onConfigurationChanged");
+    }
+
+    public void onCreate(){
+        super.onCreate();
+        Log.d(TAG,"BaseService.onCreate");
+    }
+
+    public void onDestroy(){
+        if(networkChangeReceiver_!=null){
+            unregisterReceiver(networkChangeReceiver_);
+            networkChangeReceiver_=null;
+        }
+        Log.d(TAG,"BaseService.onDestroy");
+    }
+
+    public void onLowMemory(){
+        super.onLowMemory();
+        Log.d(TAG,"BaseService.onLowMemory");
+    }
+
+    public void onRebind(Intent intent){
+        super.onRebind(intent);
+        Log.d(TAG,"BaseService.onRebind");
+    }
+
+    public void onStart(Intent intent, int startId){
+        super.onStart(intent, startId);
+        Log.d(TAG,"BaseService.onStart");
+    }
+
+    public int onStartCommand(Intent intent, int flags, int startId){
+        int res=super.onStartCommand(intent, flags, startId);
+        Log.d(TAG,"BaseService.onStartCommand");
+        return res;
+    }
+
+    public void onTaskRemoved(Intent intent){
+        super.onTaskRemoved(intent);
+        Log.d(TAG,"BaseService.onTaskRemoved");
+    }
+
+
+    public void onTrimMemory(int level){
+        super.onTrimMemory(level);
+        Log.d(TAG,"BaseService.onTrimMemory");
+    }
+
+    public boolean onUnbind(Intent intent){
+        boolean res=super.onUnbind(intent);
+        Log.d(TAG,"BaseService.onUnbind");
+        return res;
+    }
+
+}
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java
new file mode 100644 (file)
index 0000000..b595469
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Bundle;
+
+import java.util.Random;
+
+import com.gd.mobicore.pa.jni.CommonPAWrapper;
+import com.gd.mobicore.pa.ifc.RootPAProvisioningIntents;
+import com.gd.mobicore.pa.ifc.RootPADeveloperIfc;
+import com.gd.mobicore.pa.ifc.CommandResult;
+import com.gd.mobicore.pa.ifc.BooleanResult;
+import com.gd.mobicore.pa.ifc.TrustletContainer;
+import com.gd.mobicore.pa.ifc.IfcVersion;
+
+public class DeveloperService extends BaseService {
+
+    private final RootPADeveloperIfc.Stub mBinder = new ServiceIfc();
+    private static final int DEVELOPER_UID_FOR_LOCK=0x22220000;
+    private static final int UUID_LENGTH=16;
+    private static final int EXTERNAL_MEMORY=2;
+    private static final int DEFAULT_MEMORY_TYPE=EXTERNAL_MEMORY;
+    private static final int DEFAULT_NUMBER_OF_INSTANCES=1;
+    private static final int DEFAULT_FLAGS=0;
+    private static final byte[] DEFAULT_PUKHASH={0,0,0,0,0,0,0,0,0,0,
+                                                 0,0,0,0,0,0,0,0,0,0,
+                                                 0,0,0,0,0,0,0,0,0,0,0,0};
+    private class ServiceIfc extends RootPADeveloperIfc.Stub {
+        public ServiceIfc(){
+            super();
+        }
+
+        // note that these values have to be in line with TltInstallationRequestDataType in rootpa.h
+        public static final int REQUEST_DATA_TLT=1;
+        public static final int REQUEST_DATA_KEY=2;
+
+
+        private CommonPAWrapper commonPAWrapper(){
+            return DeveloperService.this.commonPAWrapper();
+        }
+
+        private boolean uuidOk(byte[] uuid){
+            if(uuid==null || uuid.length != UUID_LENGTH){
+                Log.e(TAG,"DeveloperService.Stub.uuidOk NOK");
+                return false;
+            }
+            Log.d(TAG,"DeveloperService.Stub.uuidOk OK");
+            return true;
+        }
+
+        public CommandResult installTrustletOrKey(int spid, byte[] uuid, byte[] trustletBinary, byte[] key, int minTltVersion, byte[] tltPukHash){
+            Log.d(TAG,">>DeveloperService.Stub.installTrustletOrKey");
+            if(tltPukHash==null){
+                tltPukHash=DEFAULT_PUKHASH;
+            }
+
+            if((trustletBinary == null && key == null) || (trustletBinary != null && key != null) || 0==spid || !uuidOk(uuid) ){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int tmpSuid=DEVELOPER_UID_FOR_LOCK+new Random().nextInt();
+
+            if(!DeveloperService.this.acquireLock(tmpSuid, false).isOk()){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+            doProvisioningLockSuid_=tmpSuid;
+            int err=0;
+            byte[] data=null;
+            int dataType;
+            try{
+                if(trustletBinary != null){
+                    data=trustletBinary;
+                    dataType=REQUEST_DATA_TLT;
+                }else{
+                    data=key;
+                    dataType=REQUEST_DATA_KEY;
+                }
+                setupProxy();
+                err=commonPAWrapper().installTrustlet(spid,
+                                                      uuid,
+                                                      dataType,
+                                                      data,
+                                                      minTltVersion,
+                                                      tltPukHash,
+                                                      DEFAULT_MEMORY_TYPE,
+                                                      DEFAULT_NUMBER_OF_INSTANCES,
+                                                      DEFAULT_FLAGS,
+                                                      se_);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().installTrustletOrKey exception: ", e);
+                err=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"<<DeveloperService.Stub.installTrustletOrKey");
+            return new CommandResult(err);
+        }
+
+        public CommandResult installTrustlet(int spid,
+                                             byte[] uuid,
+                                             byte[] trustletBinary,
+                                             int minTltVersion,
+                                             byte[] tltPukHash,
+                                             int memoryType,
+                                             int numberOfInstances,
+                                             int flags){
+            Log.d(TAG,">>DeveloperService.Stub.installTrustlet");
+            if(tltPukHash==null){
+                tltPukHash=DEFAULT_PUKHASH;
+            }
+
+
+            if(trustletBinary == null || 0==spid || !uuidOk(uuid) || memoryType > EXTERNAL_MEMORY){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int tmpSuid=DEVELOPER_UID_FOR_LOCK+new Random().nextInt();
+
+            if(!DeveloperService.this.acquireLock(tmpSuid, false).isOk()){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+            doProvisioningLockSuid_=tmpSuid;
+            int err=0;
+            try{
+                setupProxy();
+                err=commonPAWrapper().installTrustlet(spid,
+                                                      uuid,
+                                                      REQUEST_DATA_TLT,
+                                                      trustletBinary,
+                                                      minTltVersion,
+                                                      tltPukHash,
+                                                      memoryType,
+                                                      numberOfInstances,
+                                                      flags,
+                                                      se_);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().installTrustlet exception: ", e);
+                err=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"<<DeveloperService.Stub.installTrustlet");
+            return new CommandResult(err);
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        Log.d(TAG,"Hello, DeveloperService onCreate");
+        super.onCreate();
+    }
+
+    @Override
+    public void onLowMemory() {
+        Log.d(TAG,"DeveloperService onLowMemory");
+        super.onLowMemory();
+    }
+
+    public void onDestroy(){
+        super.onDestroy();
+        Log.d(TAG,"DeveloperService being destroyed");
+    }
+
+    @Override
+    public IBinder onBind(Intent intent){
+        try{
+            se_ = intent.getByteArrayExtra("SE");
+        }catch(Exception e){
+            Log.i(TAG,"DeveloperService something wrong in the given ip "+e );
+        }
+
+        try{
+            Log.setLoggingLevel(intent.getIntExtra("LOG",0));
+        }catch(Exception e){
+            Log.i(TAG,"DeveloperService something wrong in the given logging level "+e );
+        }
+        Log.i(TAG,"DeveloperService binding, IfcVersion: " +IfcVersion.ROOTPA_ANDROID_API_VERSION_MAJOR+"."+IfcVersion.ROOTPA_ANDROID_API_VERSION_MINOR);
+        if(se_!=null) Log.d(TAG,new String(se_));
+        return mBinder;
+
+    }
+
+    @Override
+    public int  onStartCommand(Intent i, int flags, int startid){
+        Log.d(TAG,"DeveloperService starting");
+        return START_STICKY;
+    }
+}
+
+
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/Log.java b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/Log.java
new file mode 100644 (file)
index 0000000..2697d32
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.service;
+
+import java.lang.String;
+import java.lang.Throwable;
+
+public class Log {
+
+    private static int level_=android.util.Log.INFO;
+
+    /**
+    Set level of logging
+    */
+    public static void setLoggingLevel(int level){
+        if( level == android.util.Log.VERBOSE ||
+            level == android.util.Log.DEBUG ||
+            level == android.util.Log.INFO ||
+            level == android.util.Log.WARN ||
+            level == android.util.Log.ERROR ||
+            level == android.util.Log.ASSERT ){
+            level_=level;
+        }
+    }
+
+    /**
+    Send a DEBUG log message.
+    */
+    public static int d(String tag, String msg){
+        if(level_<=android.util.Log.DEBUG) return android.util.Log.d(tag, msg);
+        return 0;
+    }
+
+    /**
+    Send a DEBUG log message and log the exception.
+    */
+    public static int d(String tag, String msg, Throwable tr){
+        if(level_<=android.util.Log.DEBUG) return android.util.Log.d(tag, msg, tr);
+        return 0;
+    }
+
+    /**
+    Send an ERROR log message.
+    */
+    public static int e(String tag, String msg){
+        if(level_<=android.util.Log.ERROR) return android.util.Log.e(tag, msg);
+        return 0;
+    }
+
+    /**
+    Send a ERROR log message and log the exception.
+    */
+    public static int e(String tag, String msg, Throwable tr){
+        if(level_<=android.util.Log.ERROR) return android.util.Log.e(tag, msg, tr);
+        return 0;
+    }
+
+    /**
+    Send an INFO log message.
+    */
+    public static int i(String tag, String msg){
+        if(level_<=android.util.Log.INFO) return android.util.Log.i(tag, msg);
+        return 0;
+    }
+
+    /**
+    Send a INFO log message and log the exception.
+    */
+    public static int i(String tag, String msg, Throwable tr){
+        if(level_<=android.util.Log.INFO) return android.util.Log.i(tag, msg, tr);
+        return 0;
+    }
+
+    /**
+    Handy function to get a loggable stack trace from a Throwable
+    */
+    public static String getStackTraceString(Throwable tr){
+        return android.util.Log.getStackTraceString(tr);
+    }
+
+    /**
+    Checks to see whether or not a log for the specified tag is loggable at the specified level.
+    */
+    public static boolean isLoggable(String tag, int level){
+        return android.util.Log.isLoggable(tag, level);
+    }
+
+    /**
+    Low-level logging call.
+    */
+    public static int println(int priority, String tag, String msg){
+        return android.util.Log.println(priority, tag, msg);
+    }
+
+    /**
+    Send a VERBOSE log message.
+    */
+    public static int v(String tag, String msg){
+        if(level_<=android.util.Log.VERBOSE) return android.util.Log.v(tag, msg);
+        return 0;
+    }
+
+    /**
+    Send a VERBOSE log message and log the exception.
+    */
+    public static int v(String tag, String msg, Throwable tr){
+        if(level_<=android.util.Log.VERBOSE) return android.util.Log.v(tag, msg, tr);
+        return 0;
+    }
+
+    /**
+    Log the exception at WARN level
+    */
+
+    public static int w(String tag, Throwable tr){
+        if(level_>=android.util.Log.WARN) return android.util.Log.w(tag, tr);
+        return 0;
+    }
+
+    /**
+    Send a WARN log message and log the exception.
+    */
+    public static int w(String tag, String msg, Throwable tr){
+        if(level_<=android.util.Log.WARN) return android.util.Log.w(tag, msg, tr);
+        return 0;
+    }
+
+    /**
+    Send a WARN log message.
+    */
+    public static int w(String tag, String msg){
+        if(level_<=android.util.Log.WARN) return android.util.Log.w(tag, msg);
+        return 0;
+    }
+
+    /**
+    What a Terrible Failure: Report an exception that should never happen.
+    */
+    public static int wtf(String tag, Throwable tr){
+        return android.util.Log.wtf(tag, tr);
+    }
+
+    /**
+    What a Terrible Failure: Report a condition that should never happen.
+    */
+    public static int wtf(String tag, String msg){
+        return android.util.Log.wtf(tag, msg);
+    }
+
+    /**
+    What a Terrible Failure: Report an exception that should never happen.
+    */
+    public static int wtf(String tag, String msg, Throwable tr){
+        return android.util.Log.wtf(tag, msg, tr);
+    }
+}
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/OemService.java b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/OemService.java
new file mode 100644 (file)
index 0000000..730e85b
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Bundle;
+
+import java.util.Random;
+
+import com.gd.mobicore.pa.jni.CommonPAWrapper;
+import com.gd.mobicore.pa.ifc.RootPAProvisioningIntents;
+import com.gd.mobicore.pa.ifc.RootPADeveloperIfc;
+import com.gd.mobicore.pa.ifc.RootPAOemIfc;
+import com.gd.mobicore.pa.ifc.CommandResult;
+import com.gd.mobicore.pa.ifc.BooleanResult;
+import com.gd.mobicore.pa.ifc.TrustletContainer;
+import com.gd.mobicore.pa.ifc.IfcVersion;
+
+public class OemService extends BaseService {
+    private static final String TAG = "RootPA-J";
+
+    private final RootPAOemIfc.Stub mBinder = new ServiceIfc();
+    private static final int OEM_UID_FOR_LOCK=0x33330000;
+
+    private class ServiceIfc extends RootPAOemIfc.Stub {
+        public ServiceIfc(){
+            super();
+        }
+
+        private CommonPAWrapper commonPAWrapper(){
+            return OemService.this.commonPAWrapper();
+        }
+
+        public CommandResult unregisterRootContainer(){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.unregisterRootContainer");
+
+            int tmpSuid=OEM_UID_FOR_LOCK+new Random().nextInt(); // this may override the uid used in lock, which means it will not be
+
+            if(!OemService.this.acquireLock(tmpSuid, false).isOk()){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            doProvisioningLockSuid_=tmpSuid;
+            Log.d(TAG,"RootPAServiceIfc.Stub.unregisterRootContainer calling JNI");
+
+            int ret=CommandResult.ROOTPA_OK;
+
+            try{
+                setupProxy();
+               ret=commonPAWrapper().unregisterRootContainer(se_);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().unregisterRootContainer exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            CommandResult res=OemService.this.releaseLock(doProvisioningLockSuid_, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.unregisterRootContainer");
+            return new CommandResult(ret);
+        }
+
+    }
+
+    @Override
+    public void onCreate() {
+        Log.d(TAG,"Hello, OemService onCreate");
+        super.onCreate();
+    }
+
+    @Override
+    public void onLowMemory() {
+        Log.d(TAG,"OemService onLowMemory");
+        super.onLowMemory();
+    }
+
+    public void onDestroy(){
+        super.onDestroy();
+        Log.d(TAG,"OemService being destroyed");
+    }
+
+    @Override
+    public IBinder onBind(Intent intent){
+        try{
+            se_ = intent.getByteArrayExtra("SE");
+        }catch(Exception e){
+            Log.i(TAG,"OemService something wrong in the given ip "+e );
+        }
+
+        try{
+            Log.setLoggingLevel(intent.getIntExtra("LOG",0));
+        }catch(Exception e){
+            Log.i(TAG,"OemService something wrong in the given logging level "+e );
+        }
+        Log.i(TAG,"OemService binding, IfcVersion: " +IfcVersion.ROOTPA_ANDROID_API_VERSION_MAJOR+"."+IfcVersion.ROOTPA_ANDROID_API_VERSION_MINOR);
+        if(se_!=null) Log.d(TAG,new String(se_));
+        return mBinder;
+    }
+
+    @Override
+    public int  onStartCommand(Intent i, int flags, int startid){
+        Log.d(TAG,"OemService starting");
+        return START_STICKY;
+    }
+}
+
+
diff --git a/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/ProvisioningService.java b/mobicore/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/ProvisioningService.java
new file mode 100644 (file)
index 0000000..6a9dd28
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Bundle;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.UUID;
+import java.util.Random;
+import java.math.BigInteger;
+
+import com.gd.mobicore.pa.jni.CommonPAWrapper;
+
+import com.gd.mobicore.pa.ifc.RootPAServiceIfc;
+import com.gd.mobicore.pa.ifc.CmpMsg;
+import com.gd.mobicore.pa.ifc.CmpCommand;
+import com.gd.mobicore.pa.ifc.CmpResponse;
+import com.gd.mobicore.pa.ifc.CommandResult;
+import com.gd.mobicore.pa.ifc.BooleanResult;
+import com.gd.mobicore.pa.ifc.SPID;
+import com.gd.mobicore.pa.ifc.Version;
+import com.gd.mobicore.pa.ifc.SUID;
+import com.gd.mobicore.pa.ifc.SPContainerStructure;
+import com.gd.mobicore.pa.ifc.SPContainerStateParcel;
+import com.gd.mobicore.pa.ifc.SPContainerState;
+import com.gd.mobicore.pa.ifc.TrustletContainer;
+import com.gd.mobicore.pa.ifc.TrustletContainerState;
+import com.gd.mobicore.pa.ifc.IfcVersion;
+
+public class ProvisioningService extends BaseService {
+//    protected static final String TAG = "RootPA-J";
+
+    private static final int PROVISIONING_UID_FOR_LOCK=0x11110000;
+    private static final int LONG_SIZE=8;
+    private final RootPAServiceIfc.Stub mBinder = new ServiceIfc();
+
+    // using this instead of anonymous inner class in order to allow call to some of the private methods we define here
+    private class ServiceIfc extends RootPAServiceIfc.Stub {
+
+        public ServiceIfc(){
+            super();
+        }
+
+        private CommonPAWrapper commonPAWrapper(){
+            return ProvisioningService.this.commonPAWrapper();
+        }
+
+        public CommandResult executeCmpCommands(int uid, List<CmpCommand> commands, List<CmpResponse> responses){
+
+            Log.d(TAG,">>RootPAServiceIfc.Stub.executeCmpCommands "+commands+" "+responses);
+
+            if(commands==null||responses==null){ // having null out variable leads to null pointer exception in the client, however we still want to do checking so that there is not unncessary execution of the following code
+                Log.d(TAG,"RootPAServiceIfc.Stub.executeCmpCommands, illegal argument");
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            if(locked(uid)){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            int ret=CommandResult.ROOTPA_OK;
+            try{
+                ret=commonPAWrapper().executeCmpCommands(uid, commands, responses);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().executeCmpCommands exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.executeCmpCommands");
+            return new CommandResult(ret);
+        }
+
+        public CommandResult isRootContainerRegistered(BooleanResult result){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.isRootContainerRegistered");
+
+            if(result==null){  // having null out variable leads to null pointer exception in the client, however we stll want to do checking so that there is not unncessary execution of the following code
+                Log.d(TAG,"RootPAServiceIfc.Stub.isRootContainerRegistered result null");
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int internalUidForLock=new Random().nextInt();
+
+            if(!ProvisioningService.this.acquireLock(internalUidForLock, false).isOk())
+            {
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            boolean[] isRegistered = new boolean[1];
+            int ret=CommandResult.ROOTPA_OK;
+            try{
+                ret=commonPAWrapper().isRootContainerRegistered(isRegistered);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().isRootContainerRegistered exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+            result.setResult(isRegistered[0]);
+
+            CommandResult res=ProvisioningService.this.releaseLock(internalUidForLock, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.isRootContainerRegistered");
+            return new CommandResult(ret);
+        }
+
+        public CommandResult isSPContainerRegistered(SPID spid, BooleanResult result){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.isSPContainerRegistered");
+
+            if(spid==null || result==null){  // having null out variable leads to null pointer exception in the client, however we still want to do checking so that there is not unncessary execution of the following code
+                Log.d(TAG,"RootPAServiceIfc.Stub.isSPContainerRegistered spid "+spid+" result "+result);
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            boolean[] isRegistered = new boolean[1];
+            int ret=CommandResult.ROOTPA_OK;
+
+            int internalUidForLock=new Random().nextInt();
+            if(!ProvisioningService.this.acquireLock(internalUidForLock, false).isOk())
+            {
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            try{
+                ret=commonPAWrapper().isSpContainerRegistered(spid.spid(), isRegistered);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().isSpContainerRegistered exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+            result.setResult(isRegistered[0]);
+
+            CommandResult res=ProvisioningService.this.releaseLock(internalUidForLock, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.isSPContainerRegistered ");
+            return new CommandResult(ret);
+        }
+
+        public CommandResult getVersion(Version version){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.getVersion");
+
+            int internalUidForLock=new Random().nextInt();
+            if(!ProvisioningService.this.acquireLock(internalUidForLock, false).isOk())
+            {
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            int ret=CommandResult.ROOTPA_OK;
+            byte[] productId=new byte[64]; // max length of product id from mcVersionInfo.h
+            Bundle versionBundle= new Bundle();
+            List<String> keys = new ArrayList<String>();
+            List<Integer> values = new ArrayList<Integer>();
+
+            try{
+                ret=commonPAWrapper().getVersion(productId, keys, values);
+                if(ret == CommandResult.ROOTPA_OK && (keys.size() != values.size())){
+                    ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+                }
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().getVersion exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            if(ret==CommandResult.ROOTPA_OK){
+                version.setProductId(new String(productId).trim());
+
+                for(int i=0; i<values.size(); i++){
+                    versionBundle.putInt(keys.get(i), values.get(i));
+                }
+
+                version.setVersion(versionBundle);
+            }
+
+            CommandResult res=ProvisioningService.this.releaseLock(internalUidForLock, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.getVersion "+ret);
+            return new CommandResult(ret);
+        }
+
+
+        public CommandResult getDeviceId(SUID suid){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.getDeviceId");
+
+            int internalUidForLock=new Random().nextInt();
+            if(!ProvisioningService.this.acquireLock(internalUidForLock, false).isOk())
+            {
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            int ret=CommandResult.ROOTPA_OK;
+            byte[] suidArray=new byte[16]; // suid length
+            try{
+                ret=commonPAWrapper().getSuid(suidArray);
+                suid.setSuid(suidArray);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().getSuid exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            CommandResult res=ProvisioningService.this.releaseLock(internalUidForLock, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.getDeviceId");
+            return new CommandResult(ret);
+        }
+
+        public CommandResult acquireLock(int uid){
+            return ProvisioningService.this.acquireLock(uid, true);
+        }
+
+        public CommandResult releaseLock(int uid){
+            return ProvisioningService.this.releaseLock(uid, true);
+        }
+
+        public CommandResult doProvisioning(int uid, SPID spid){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.doProvisioning");
+            int ret=CommandResult.ROOTPA_OK;
+
+            if(spid==null){  // having null out variable leads to null pointer exception in the client, however we still want to do checking so that there is not unncessary execution of the following code
+                Log.d(TAG,"RootPAServiceIfc.Stub.doProvisioning spid==null");
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            // we do not use uid here since we do not want to let the client to released the lock, it is done
+            // internally at CommonPAWrapper.java when sending Intents.
+
+            int tmpSuid=uid+PROVISIONING_UID_FOR_LOCK+new Random().nextInt();
+
+            if(!ProvisioningService.this.acquireLock(tmpSuid, false).isOk()){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+            doProvisioningLockSuid_=tmpSuid;
+
+            try{
+                setupProxy();
+                ret=commonPAWrapper().doProvisioning(uid, spid.spid(), se_);
+            }catch(Exception e){
+                Log.d(TAG,"CommonPAWrapper()).doProvisioning failed "+e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"CommonPAWrapper()).doProvisioning returned "+ret);
+            if(ret!=CommandResult.ROOTPA_OK){
+                if(!ProvisioningService.this.releaseLock(doProvisioningLockSuid_, false).isOk()){
+                    Log.e(TAG,"releasing lock failed after doProvisioning returned an error");
+                }
+                doProvisioningLockSuid_=0;
+            }
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.doProvisioning");
+            return new CommandResult(ret);
+        }
+
+        public CommandResult getSPContainerStructure(SPID spid, SPContainerStructure cs){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.getSPContainerStructure");
+
+            if(spid==null||cs==null){ // having null out variable leads to null pointer exception in the client, however we still want to do checking so that there is not unncessary execution of the following code
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int internalUidForLock=new Random().nextInt();
+            if(!ProvisioningService.this.acquireLock(internalUidForLock, false).isOk())
+            {
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            int ret=CommandResult.ROOTPA_OK;
+
+            final int CONTAINER_STATE_IDX=0;
+            final int NUMBER_OF_TLTS_IDX=1;
+            final int NUMBER_OF_ELEMENTS=2;
+            final int MAX_NUMBER_OF_TRUSTLETS=16;
+            final int UUID_LENGTH=16;
+
+            int[] ints = new int[NUMBER_OF_ELEMENTS];
+            int[] trustletStates = new int[MAX_NUMBER_OF_TRUSTLETS];
+            byte[][] uuidArray = new byte[MAX_NUMBER_OF_TRUSTLETS][];
+
+            try{
+                ret=commonPAWrapper().getSPContainerStructure(spid.spid(), ints, uuidArray, trustletStates);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().getSPContainerStructure exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            if(ret==CommandResult.ROOTPA_OK){
+
+                SPContainerState s=mapSpContainerState(ints[CONTAINER_STATE_IDX]);
+                   cs.setState(s);
+                if (s == SPContainerState.UNDEFINED){
+                    ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+                }
+
+                for(int i=0; i<ints[NUMBER_OF_TLTS_IDX]; i++){
+                    byte[] msBytes=new byte[LONG_SIZE];
+                    System.arraycopy(uuidArray[i], 0, msBytes, 0, LONG_SIZE);
+                    BigInteger mostSignificant=new BigInteger(msBytes);
+
+                    byte[] lsBytes=new byte[LONG_SIZE];
+                    System.arraycopy(uuidArray[i], LONG_SIZE, lsBytes, 0, LONG_SIZE);
+                    BigInteger leastSignificant=new BigInteger(lsBytes);
+
+                    Log.d(TAG,"UUID: ls ms"+leastSignificant+" "+mostSignificant);
+
+                    TrustletContainerState ts=mapTltContainerState(trustletStates[i]);
+                    if (ts == TrustletContainerState.UNDEFINED){
+                        ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+                    }
+                    cs.add(new TrustletContainer(new UUID(mostSignificant.longValue(), leastSignificant.longValue()), ts));
+                }
+
+            }else if (ret==CommandResult.ROOTPA_ERROR_INTERNAL_NO_CONTAINER){
+                   cs.setState(SPContainerState.DOES_NOT_EXIST);
+                ret=CommandResult.ROOTPA_OK;
+            }
+
+            CommandResult res=ProvisioningService.this.releaseLock(internalUidForLock, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.getSPContainerStructure");
+            return new CommandResult(ret);
+        }
+
+
+        public CommandResult getSPContainerState(SPID spid, SPContainerStateParcel state){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.getSPContainerState");
+
+            if(spid==null||state==null){ // having null out variable leads to null pointer exception in the client, however we still want to do checking so that there is not unncessary execution of the following code
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int internalUidForLock=new Random().nextInt();
+            if(!ProvisioningService.this.acquireLock(internalUidForLock, false).isOk())
+            {
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+
+            int ret=CommandResult.ROOTPA_OK;
+            int[] containerState = new int[1];
+
+            try{
+                ret=commonPAWrapper().getSPContainerState(spid.spid(), containerState);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().getSPContainerState exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"RootPAServiceIfc.Stub.getSPContainerState received " + containerState[0] + " "+ ret);
+
+            if(ret==CommandResult.ROOTPA_OK){
+
+                SPContainerState s=mapSpContainerState(containerState[0]);
+                   state.setEnumeratedValue(s);
+                if (s == SPContainerState.UNDEFINED){
+                    ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+                }
+            }else if (ret==CommandResult.ROOTPA_ERROR_INTERNAL_NO_CONTAINER){
+                   state.setEnumeratedValue(SPContainerState.DOES_NOT_EXIST);
+                ret=CommandResult.ROOTPA_OK;
+            }
+
+            CommandResult res=ProvisioningService.this.releaseLock(internalUidForLock, false);
+            if(!res.isOk()){
+                Log.e(TAG,"releasing lock failed, res: "+res.result());
+                // this return code is not returned to the client since
+                // the command may have succeeded and there is just something wrong with the lock
+                // we leave it the the next command if the problem remains
+            }
+
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.getSPContainerState");
+            return new CommandResult(ret);
+        }
+
+        public CommandResult storeTA(SPID spid, byte[] uuid, byte[] taBinary){
+            Log.d(TAG,">>RootPAServiceIfc.Stub.storeTA");
+            if(spid==null||uuid==null||taBinary==null|| taBinary.length == 0 || spid.spid()==0){ // having null out variable leads to null pointer exception in the client, however we still want to do checking so that there is not unncessary execution of the following code
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int ret=CommandResult.ROOTPA_OK;
+            try{
+                ret=commonPAWrapper().storeTA(spid.spid(), uuid, taBinary);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().storeTA exception: ", e);
+                ret=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"<<RootPAServiceIfc.Stub.storeTA");
+            return new CommandResult(ret);
+        }
+
+        private final static int  MC_CONT_STATE_UNREGISTERED=0;
+        private final static int  MC_CONT_STATE_REGISTERED=1;
+        private final static int  MC_CONT_STATE_ACTIVATED=2;
+        private final static int  MC_CONT_STATE_ROOT_LOCKED=3;
+        private final static int  MC_CONT_STATE_SP_LOCKED=4;
+        private final static int  MC_CONT_STATE_ROOT_SP_LOCKED=5;
+
+        private TrustletContainerState mapTltContainerState(int containerState){
+            TrustletContainerState state=TrustletContainerState.UNDEFINED;
+            switch (containerState){
+                case MC_CONT_STATE_REGISTERED:
+                    state=TrustletContainerState.REGISTERED;
+                    break;
+                case MC_CONT_STATE_ACTIVATED:
+                    state=TrustletContainerState.ACTIVATED;
+                    break;
+                case MC_CONT_STATE_SP_LOCKED:
+                           state=TrustletContainerState.SP_LOCKED;
+                    break;
+                default:
+                    Log.e(TAG,"mapTltContainerState returning undefined: "+ containerState);
+                           state=TrustletContainerState.UNDEFINED;
+                    break;
+            }
+            return state;
+        }
+
+        private SPContainerState mapSpContainerState(int containerState){
+            SPContainerState state=SPContainerState.UNDEFINED;
+            switch (containerState){
+                case MC_CONT_STATE_UNREGISTERED:
+                    state=SPContainerState.DOES_NOT_EXIST;
+                    break;
+                case MC_CONT_STATE_REGISTERED:
+                    state=SPContainerState.REGISTERED;
+                    break;
+                case MC_CONT_STATE_ACTIVATED:
+                    state=SPContainerState.ACTIVATED;
+                    break;
+                case MC_CONT_STATE_ROOT_LOCKED:
+                           state=SPContainerState.ROOT_LOCKED;
+                    break;
+                case MC_CONT_STATE_SP_LOCKED:
+                           state=SPContainerState.SP_LOCKED;
+                    break;
+                case MC_CONT_STATE_ROOT_SP_LOCKED:
+                           state=SPContainerState.ROOT_SP_LOCKED;
+                    break;
+                default:
+                    Log.e(TAG,"mapSpContainerState returning undefined: "+ containerState);
+                           state=SPContainerState.UNDEFINED;
+                    break;
+            }
+            return state;
+        }
+    };
+
+    @Override
+    public void onCreate() {
+        Log.d(TAG,"Hello, ProvisioningService onCreate");
+        super.onCreate();
+    }
+
+    @Override
+    public void onLowMemory() {
+        Log.d(TAG,"ProvisioningService onLowMemory");
+        super.onLowMemory();
+    }
+
+    public void onDestroy(){
+        super.onDestroy();
+        Log.d(TAG,"ProvisioningService being destroyed");
+    }
+
+    @Override
+    public IBinder onBind(Intent intent){
+        try{
+            se_ = intent.getByteArrayExtra("SE");
+        }catch(Exception e){
+            Log.i(TAG,"ProvisioningService something wrong in the given ip "+e );
+        }
+
+        try{
+            Log.setLoggingLevel(intent.getIntExtra("LOG",0));
+        }catch(Exception e){
+            Log.i(TAG,"ProvisioningService something wrong in the given logging level "+e );
+        }
+        Log.i(TAG,"ProvisioningService binding, IfcVersion: " +IfcVersion.ROOTPA_ANDROID_API_VERSION_MAJOR+"."+IfcVersion.ROOTPA_ANDROID_API_VERSION_MINOR);
+        if(se_!=null) Log.d(TAG,new String(se_));
+        return mBinder;
+    }
+
+    @Override
+    public int  onStartCommand(Intent i, int flags, int startid){
+        Log.d(TAG,"ProvisioningService starting");
+        return START_STICKY;
+    }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/Android.mk b/mobicore/rootpa/Code/Android/lib/Android.mk
new file mode 100644 (file)
index 0000000..ffdc0f0
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# build the interface library
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES +=  src/com/gd/mobicore/pa/ifc/RootPAServiceIfc.aidl \
+                    src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl \
+                    src/com/gd/mobicore/pa/ifc/RootPAOemIfc.aidl 
+
+
+LOCAL_MODULE := rootpa_interface
+LOCAL_MODULE_TAGS := debug eng optional
+
+APP_PIE := true
+LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/AndroidManifest.xml b/mobicore/rootpa/Code/Android/lib/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..5648a6d
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" ?> 
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gd.mobicore.pa.ifc" android:versionCode="1" android:versionName="1.0"> 
+  <uses-sdk android:minSdkVersion="8"
+           android:targetSdkVersion="16" />
+</manifest>            
diff --git a/mobicore/rootpa/Code/Android/lib/NOTICE b/mobicore/rootpa/Code/Android/lib/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/rootpa/Code/Android/lib/ant.properties b/mobicore/rootpa/Code/Android/lib/ant.properties
new file mode 100644 (file)
index 0000000..269886d
--- /dev/null
@@ -0,0 +1 @@
+java.compilerargs="-Xlint:unchecked"
diff --git a/mobicore/rootpa/Code/Android/lib/build.xml b/mobicore/rootpa/Code/Android/lib/build.xml
new file mode 100644 (file)
index 0000000..189b6f6
--- /dev/null
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="rootpa-interface" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to inject it through the ANDROID_HOME environment variable in doBuild.sh."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+
+    <!-- the version tag is set to custom in order to avoid regenerating this file. The file has been modifies to make the project name different from the folder name -->
+    <!-- version-tag: custom -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/mobicore/rootpa/Code/Android/lib/proguard-project.txt b/mobicore/rootpa/Code/Android/lib/proguard-project.txt
new file mode 100644 (file)
index 0000000..f2fe155
--- /dev/null
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/mobicore/rootpa/Code/Android/lib/project.properties b/mobicore/rootpa/Code/Android/lib/project.properties
new file mode 100644 (file)
index 0000000..59c81c4
--- /dev/null
@@ -0,0 +1,17 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+android.library=true
+
+# Project target.
+
+target=android-16
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/AbstractEnumParcel.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/AbstractEnumParcel.java
new file mode 100644 (file)
index 0000000..6434730
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Abstracts some of the logic common to all parcelable facades that wrap a single enumerated value.
+ */
+public abstract class AbstractEnumParcel<E extends Enum<E>> implements Parcelable {
+       private E enumeratedValue;
+
+       public AbstractEnumParcel() {
+       }
+
+       public AbstractEnumParcel(E enumeratedValue) {
+               this.enumeratedValue = enumeratedValue;
+       }
+
+       public E getEnumeratedValue() {
+               return enumeratedValue;
+       }
+
+       public void setEnumeratedValue(E enumeratedValue) {
+               this.enumeratedValue = enumeratedValue;
+       }
+
+       @Override
+       public int describeContents() {
+               return 0;
+       }
+
+       @Override
+       public void writeToParcel(Parcel dest, int flags) {
+               if (enumeratedValue != null){
+                       dest.writeString(enumeratedValue.toString());
+        }
+       }
+
+       @Override
+       public String toString() {
+               return this.getClass().getSimpleName() + '{' + enumeratedValue + '}';
+       }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/BooleanResult.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/BooleanResult.aidl
new file mode 100644 (file)
index 0000000..4aecad5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable BooleanResult;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/BooleanResult.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/BooleanResult.java
new file mode 100644 (file)
index 0000000..0d1b259
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * An 'out' value for an AIDL method that represents a boolean value.
+ */
+public class BooleanResult implements Parcelable {
+    private Boolean result_;
+
+    public BooleanResult() {
+    }
+
+    public BooleanResult(Boolean result) {
+        setResult(result);
+    }
+
+    public Boolean result() {
+        return result_;
+    }
+
+    public void setResult(final Boolean result) {
+        if(result == null) {
+            throw new IllegalStateException("Result is null!");
+        }
+
+        this.result_ = result;
+    }
+
+    //parcelable interface
+
+    public static final Creator<BooleanResult> CREATOR = new Creator<BooleanResult>() {
+        public BooleanResult createFromParcel(Parcel in) {
+            return new BooleanResult(in);
+        }
+
+        public BooleanResult[] newArray(int size) {
+            return new BooleanResult[size];
+        }
+    };
+
+    private BooleanResult(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public void readFromParcel(Parcel in) {
+        result_ = (in.readByte() == 1);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        if(result_ != null){
+            out.writeByte((byte) (result_ ? 1 : 0));
+        }
+    }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpCommand.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpCommand.aidl
new file mode 100644 (file)
index 0000000..72cd33f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable CmpCommand;
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpCommand.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpCommand.java
new file mode 100644 (file)
index 0000000..13de3cd
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+    Class that contains content management protocol command. The class inherits is parcelable.
+    @see CmpMsg
+    @see CmpResponse
+*/
+public class CmpCommand extends CmpMsg{
+    public static final int COMMAND_LENGTH_IDX=4;
+    private static final int COMMAND_RESERVED_IDX=8;
+
+    /**
+    This is not directly tied to the content of the command but to execution of
+    multiple commands. If ignoreError is set, the execution continues even if
+    this command returns an error. By default ignoreError is false.
+    @return boolean value telling whether the error should be ignored
+    */
+    public boolean ignoreError(){
+        return ignoreError_;
+    }
+
+    /**
+    This is not directly tied to the content of the command but to execution of
+    multiple commands. If ignoreError is set, the execution continues even if
+    this command returns an error. By default ignoreError is false.
+    @param ignore boolean value telling whether the error should be ignored
+    */
+    public void setIgnoreError(boolean ignore){
+
+        ignoreError_=ignore;
+    }
+
+    /**
+        @return id of the command
+    */
+    public int commandId(){
+        return msgId();
+    }
+
+    /**
+        @param id command id, see possible values from CmpMsg
+    */
+    public void setCommandId(int id){
+        setMsgId(id);
+    }
+
+    public void setLength(int length)
+    {
+        // MC_CMP_CMD_GET_VERSION, MC_CMP_CMD_GENERATE_AUTH_TOKEN and MC_CMP_CMD_GET_SUID do not have length field for legacy reasons
+        if(msgId()!=MC_CMP_CMD_GET_VERSION
+        && msgId()!=MC_CMP_CMD_GENERATE_AUTH_TOKEN
+        && msgId()!=MC_CMP_CMD_GET_SUID
+           && length > 4) // not setting length for messages that only have id
+        {
+            setInt(COMMAND_LENGTH_IDX, length);
+        }
+    }
+
+    /**
+        Constructor
+        @param commandId see possible values from CmpMsg
+    */
+    public CmpCommand(int commandId){
+        super();
+        setCommandId(commandId);
+    }
+
+    public CmpCommand(byte[] content){
+        super(content);
+    }
+
+    /**
+        Costructor required by Parcelable
+    */
+    public CmpCommand(Parcel in){
+        super(in);
+    }
+
+
+    public static final Parcelable.Creator<CmpCommand> CREATOR = new Parcelable.Creator<CmpCommand>(){
+        public CmpCommand createFromParcel(Parcel in){
+            return new CmpCommand(in);
+        }
+
+        public CmpCommand[] newArray(int size){
+            return null;
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel out, int flags){
+        out.writeByte((byte)((ignoreError_==true)?1:0));
+        super.writeToParcel(out, flags);
+    }
+
+    public void readFromParcel(Parcel in){
+        ignoreError_=(in.readByte()==1);
+        super.readFromParcel(in);
+    }
+
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpMsg.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpMsg.java
new file mode 100644 (file)
index 0000000..d3467e5
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+    Base class for content management protocol commands and responses
+    @see CmpCommand
+    @see CmpResponse
+*/
+public abstract class CmpMsg implements Parcelable{
+
+// CMP message ID's
+    public static final int MC_CMP_CMD_AUTHENTICATE=0;
+    public static final int MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION=1;
+    public static final int MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION=2;
+    public static final int MC_CMP_CMD_BEGIN_SP_AUTHENTICATION=3;
+    public static final int MC_CMP_CMD_GENERATE_AUTH_TOKEN=4;
+    public static final int MC_CMP_CMD_GET_VERSION=5;
+
+    public static final int MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT=7;
+
+    public static final int MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE=9;
+    public static final int MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT=10;
+    public static final int MC_CMP_CMD_ROOT_CONT_UNREGISTER=11;
+    public static final int MC_CMP_CMD_SP_CONT_ACTIVATE=12;
+    public static final int MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT=13;
+    public static final int MC_CMP_CMD_SP_CONT_LOCK_BY_SP=14;
+    public static final int MC_CMP_CMD_SP_CONT_REGISTER=15;
+    public static final int MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE=16;
+    public static final int MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT=17;
+    public static final int MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP=18;
+    public static final int MC_CMP_CMD_SP_CONT_UNREGISTER=19;
+    public static final int MC_CMP_CMD_TLT_CONT_ACTIVATE=20;
+    public static final int MC_CMP_CMD_TLT_CONT_LOCK_BY_SP=21;
+    public static final int MC_CMP_CMD_TLT_CONT_PERSONALIZE=22;
+    public static final int MC_CMP_CMD_TLT_CONT_REGISTER=23;
+    public static final int MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE=24;
+    public static final int MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP=25;
+    public static final int MC_CMP_CMD_TLT_CONT_UNREGISTER=26;
+    public static final int MC_CMP_CMD_GET_SUID=27;
+    public static final int MC_CMP_CMD_AUTHENTICATE_TERMINATE=28;
+
+// indices and masks
+    public static final int MSG_ID_IDX=0;
+    public static final int INT_LENGTH=4;
+    public static final int RSP_ID_MASK=(1 << 31);
+
+    /**
+        helper method to convert given command id to response id
+        @param commandId id to be converted
+        @return response id corresponding to given command id
+    */
+    public static final int commandIdToResponseId(int commandId){
+        return (RSP_ID_MASK|commandId);
+    }
+
+    /**
+        helper method to convert given command id to response id
+        @param responseId id to be converted
+        @return command id corresponding to given response id
+    */
+    public static final int responseIdToCommandId(int responseId){
+        return (RSP_ID_MASK^responseId);
+    }
+
+
+    /**
+        Constructor that takes in the whole message as by array
+        @param content the whole message
+    */
+    public CmpMsg(byte[] content){
+        super();
+        setContent(content);
+    }
+
+    /**
+        default constructor
+    */
+    public CmpMsg(){
+        super();
+    }
+
+    /**
+        @return size of the message
+    */
+    public int size(){
+        if(content_==null) return 0;
+        return content_.length;
+    }
+
+    /**
+        Sets the whole message, if anything has been set before this method is called, it will be overwritten
+        @param content the whole message
+    */
+    public void setContent(byte[] content)
+    {
+        content_=content;
+        setLength(content.length);
+    }
+
+    /**
+        @return the whole message as byte array
+    */
+    public byte[] toByteArray()
+    {
+        return content_;
+    }
+
+
+    protected int msgId()
+    {
+        return getInt(MSG_ID_IDX);
+    }
+
+    protected void setMsgId(int id)
+    {
+        setInt(MSG_ID_IDX, id);
+    }
+
+
+    public abstract void setLength(int length);
+
+    private void createEmptyContentIfNeeded(int index, int size){
+        if(content_==null){
+            content_=new byte[size];
+            setLength(content_.length); // we keep the length field automatically up to date
+        }else if(content_.length<(index+size)){
+            byte[] newarray=new byte[index+size];
+            System.arraycopy(content_, 0, newarray, 0, content_.length);
+            content_=newarray;
+            setLength(content_.length); // we keep the length field automatically up to date
+        }
+    }
+// generic setters ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    /**
+        Set an integer in given index in byte array. If the array is not long enough, lenghtens the array as needed
+        @param index index of the start of the integer in byte array
+        @param value to be set
+    */
+    public void setInt(int index, int value)
+    {
+        createEmptyContentIfNeeded(index, INT_LENGTH);
+        content_[index+0]=(byte) (value & 0xFF);
+        content_[index+1]=(byte)((value >> 8) & 0xFF);
+        content_[index+2]=(byte) ((value >> 16) & 0xFF);
+        content_[index+3]=(byte) ((value >> 24) & 0xFF);
+    }
+
+
+    /**
+        Set an integer in given index in byte array. If the array is not long enough, lenghtens the array as needed
+        @param index index of the start of the integer in byte array
+        @param addBytes bytes to be added
+    */
+    public void setByteArray(int index, byte[] addBytes)
+    {
+        createEmptyContentIfNeeded(index,addBytes.length);
+        System.arraycopy(addBytes, 0, content_, index, addBytes.length);
+    }
+
+
+// generic getters ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+    /**
+        Gets integer value from the message
+        @param index index of the start of the integer in byte array
+        @return integer stored in the given index
+        @throws ArrayIndexOutOfBoundsException if given index is out of bounds of the stored message
+    */
+    public int getInt(int index) throws ArrayIndexOutOfBoundsException
+    {
+        return (content_[index] & 0xFF) +
+               ((content_[index+1] & 0xFF) << 8) +
+               ((content_[index+2] & 0xFF) << 16) +
+               ((content_[index+3] & 0xFF) << 24);
+    }
+
+    /**
+        Gets byte array from the message
+        @param index index of the start of the requested byte array
+        @param length length of the byte array to be returned
+        @return byte array stored in the given index
+        @throws ArrayIndexOutOfBoundsException if given index is out of bounds of the stored message
+    */
+    public byte[] getByteArray(int index, int length) throws ArrayIndexOutOfBoundsException
+    {
+        byte[] newarray=new byte[length];
+        System.arraycopy(content_, index, newarray, 0, length);
+        return newarray;
+    }
+
+
+    /**
+        Gets string value from the message
+        @param index index of the start of the string in byte array
+        @param length length of the byte array to be returned as string
+        @return string stored in the given index
+        @throws ArrayIndexOutOfBoundsException if given index is out of bounds of the stored message
+    */
+    public String getString(int index, int length) throws ArrayIndexOutOfBoundsException
+    {
+        return new String(content_,index,length);
+    }
+
+// data ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+    private byte[] content_;
+    boolean ignoreError_=false;  // this is moved from CmpCommand since
+                                 // for some reason it is always false
+                                 // if CmpCommand.ignoreError() called
+                                 // with JNI CallBooleanMethod but if
+                                 // this is here it works
+
+// stuff related to parcelable ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+    /**
+        constructor required by Parcelable
+    */
+    public CmpMsg(Parcel in){
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags){
+        out.writeByteArray(content_);
+    }
+
+    public void readFromParcel(Parcel in){
+        content_=in.createByteArray();
+    }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpResponse.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpResponse.aidl
new file mode 100644 (file)
index 0000000..eda484c
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.gd.mobicore.pa.ifc;
+
+parcelable CmpResponse;
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpResponse.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CmpResponse.java
new file mode 100644 (file)
index 0000000..aa5d9f5
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+    Class that contains content management protocol response. The class inherits parcelable.
+    @see CmpMsg
+    @see CmpCommand
+*/
+public class CmpResponse extends CmpMsg{
+    private static final int RETURN_CODE_IDX=4;
+    private static final int RESPONSE_LENGTH_IDX=8;
+    private static final int RESPONSE_RESERVED_IDX=12;
+
+    /**
+        @return response id
+    */
+    public int responseId(){
+        return msgId();
+    }
+
+    /**
+        @param id respose id of the message
+    */
+    public void setResponseId(int id){
+        setMsgId(id);
+    }
+
+    /**
+        @return returnCode
+    */
+    public int returnCode(){
+        return getInt(RETURN_CODE_IDX);
+    }
+
+    /**
+        @param ret return code for the message
+    */
+    public void setReturnCode(int ret){
+        setInt(RETURN_CODE_IDX, ret);
+    }
+
+    public void setLength(int length)
+    {
+        // MC_CMP_CMD_GET_VERSION and MC_CMP_CMD_GET_SUID do not have length field for legacy reasons
+        if(responseId()!=responseIdToCommandId(MC_CMP_CMD_GET_VERSION)
+        && responseId()!=responseIdToCommandId(MC_CMP_CMD_GENERATE_AUTH_TOKEN)
+        && responseId()!=responseIdToCommandId(MC_CMP_CMD_GET_SUID)
+        & length > 0)  // not setting length for messages that only have id
+        {
+            setInt(RESPONSE_LENGTH_IDX, length);
+        }
+    }
+
+
+    /**
+        Default constructor
+    */
+    public CmpResponse(){
+        super();
+    }
+
+    /**
+        Constructor
+        @param content the whole response as byte array
+    */
+    public CmpResponse(byte[] content){
+        super(content);
+    }
+
+    /**
+        Constructor required by parcelable
+    */
+    public CmpResponse(Parcel in){
+        super(in);
+    }
+
+    public static final Parcelable.Creator<CmpResponse> CREATOR = new Parcelable.Creator<CmpResponse>(){
+        public CmpResponse createFromParcel(Parcel in){
+            return new CmpResponse(in);
+        }
+
+        public CmpResponse[] newArray(int size){
+            return null;
+        }
+    };
+
+
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CommandResult.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CommandResult.aidl
new file mode 100644 (file)
index 0000000..fb46cdd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.gd.mobicore.pa.ifc;
+
+parcelable CommandResult;
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CommandResult.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/CommandResult.java
new file mode 100644 (file)
index 0000000..156fa11
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+    Result of commands requested from interfaces in com.gd.mobicore.pa.ifc package
+*/
+public class CommandResult implements Parcelable{
+
+    /*
+    NOTE to the maintainer. These values and documentation needs to be in line with the ones in rootpaErrors.h
+    */
+
+    /**
+    No errors detected, successful execution
+    */
+    public static final int ROOTPA_OK=0x00000000;
+
+    /**
+    Client has requested unsupported CMP command or command that it can not execute via the used interface.
+    Possible steps to recover: send only supported CMP commands or update to RootPA that supports handling the particular command in the used interface.
+    */
+    public static final int ROOTPA_COMMAND_NOT_SUPPORTED=0x00000001;
+
+    /**
+    Either rootpa is locked by another client, or the client requests lock or unlock when it is not allowed to do that.
+    Possible steps to recover: wait until the lock is released
+    */
+    public static final int ROOTPA_ERROR_LOCK=0x00000002;
+
+    /**
+    Error in one of the CMP commands, see command specific response for more details.
+    */
+    public static final int ROOTPA_ERROR_COMMAND_EXECUTION=0x00000003;
+
+    /**
+    Registry returned an error when trying to write a container.  mcDaemon could be dead or something seriously wrong in the file system.
+    Possible steps to recover: rebooting the device may help
+    */
+    public static final int ROOTPA_ERROR_REGISTRY=0x00000004;
+
+    /**
+    Error in communicating with t-base secure side. This is returned when any of the mcDeamon API calls related to communication with secure side fails.
+    Possible steps to recover: rebooting the device may help
+    */
+    public static final int ROOTPA_ERROR_MOBICORE_CONNECTION=0x00000005;
+
+    /**
+    Either Nwd or Swd software is out of memory.
+    Possible steps to recover: release memory
+    */
+    public static final int ROOTPA_ERROR_OUT_OF_MEMORY=0x00000006;
+
+    /**
+    Rootpa internal error. This error is returned in various situations when something unexpected went wrong e.g. message from CMTL can‘t be interpreted, SE returned an error indicating invalid data, bad request or similar or base64 decoding failed
+    Possible steps to recover: rebooting or updating the device may help
+    */
+    public static final int ROOTPA_ERROR_INTERNAL=0x00000007;
+
+    /**
+    Given argument is not allowed (in many cases it is NULL) or e.g. the format of xml is unsupported.
+    Possible steps to recover: give correct argument
+    */
+    public static final int ROOTPA_ERROR_ILLEGAL_ARGUMENT=0x00000008;
+
+    /**
+    Error in network connection or use of networking library.
+    Possible steps to recover: create working network connection (avoid firewalls and proxies that require password)
+    */
+    public static final int ROOTPA_ERROR_NETWORK=0x00000009;
+
+    /**
+    Error returned by XML library. Problems in parsing received XML command or creating new XML response.
+    */
+    public static final int ROOTPA_ERROR_XML=0x0000000A;
+
+    /**
+    Registry returned an error when trying to read a container. Most likely the container does not exist.
+    */
+    public static final int ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE=0x0000000B;
+
+    /**
+    CMP version of the device is not supported by SE.
+    Possible steps to recover: use CMP version supported by SE (>=3.0)
+    */
+    public static final int ROOTPA_ERROR_SE_CMP_VERSION=0x0000000C;
+
+    /**
+    Precoditions for SP container installation are not met in SE.
+    Possible steps to recover: register used SPID to SE
+    */
+    public static final int ROOTPA_ERROR_SE_PRECONDITION_NOT_MET=0x0000000D;
+
+    /**
+    Requested SP container does not exist. This is not always considered an error but is used as an informative return code. As this is internal return code, user of RootPA services should never see this.
+    Possible steps to recover: add SP container or request container with different SPID
+    */
+    public static final int ROOTPA_ERROR_INTERNAL_NO_CONTAINER=0x00000030;
+
+
+    private int result_;
+
+    public static final Parcelable.Creator<CommandResult> CREATOR = new Parcelable.Creator<CommandResult>(){
+        public CommandResult createFromParcel(Parcel in){
+            return new CommandResult(in);
+        }
+
+        public CommandResult[] newArray(int size){
+            return null;
+        }
+    };
+
+    /**
+        Constructor
+        @param result of the command
+    */
+    public CommandResult(int result){
+        result_=result;
+    }
+
+    public CommandResult(){
+        result_=ROOTPA_OK;
+    }
+
+    /**
+        Constructor required by parcelable
+    */
+    public CommandResult(Parcel in){
+        readFromParcel(in);
+    }
+
+    public int result(){
+        return result_;
+    }
+
+    public void setValue(int value){
+        result_=value;
+    }
+
+    public boolean isOk(){
+        return (result_==ROOTPA_OK);
+    }
+
+    @Override
+    public String toString() {
+        String ret=new Integer(result_).toString();
+        switch(result_){
+            case ROOTPA_OK:
+                ret+=": ROOTPA_OK";
+                break;
+            case ROOTPA_COMMAND_NOT_SUPPORTED:
+                ret+=": ROOTPA_COMMAND_NOT_SUPPORTED";
+                break;
+            case ROOTPA_ERROR_INTERNAL:
+                ret+=": ROOTPA_ERROR_INTERNAL";
+                break;
+            case ROOTPA_ERROR_LOCK:
+                ret+=": ROOTPA_ERROR_LOCK";
+                break;
+            case ROOTPA_ERROR_ILLEGAL_ARGUMENT:
+                ret+=": ROOTPA_ERROR_ILLEGAL_ARGUMENT";
+                break;
+            case ROOTPA_ERROR_INTERNAL_NO_CONTAINER:
+                ret+=": ROOTPA_ERROR_INTERNAL_NO_CONTAINER";
+                break;
+            case ROOTPA_ERROR_COMMAND_EXECUTION:
+                ret+=": ROOTPA_ERROR_COMMAND_EXECUTION";
+                break;
+            case ROOTPA_ERROR_REGISTRY:
+                ret+=": ROOTPA_ERROR_REGISTRY";
+                break;
+            case ROOTPA_ERROR_MOBICORE_CONNECTION:
+                ret+=": ROOTPA_ERROR_MOBICORE_CONNECTION";
+                break;
+            case ROOTPA_ERROR_OUT_OF_MEMORY:
+                ret+=": ROOTPA_ERROR_OUT_OF_MEMORY";
+                break;
+            case ROOTPA_ERROR_NETWORK:
+                ret+=": ROOTPA_ERROR_NETWORK";
+                break;
+            case ROOTPA_ERROR_XML:
+                ret+=": ROOTPA_ERROR_XML";
+                break;
+            case ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE:
+                ret+=": ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE";
+                break;
+            case ROOTPA_ERROR_SE_CMP_VERSION:
+                ret+=": ROOTPA_ERROR_SE_CMP_VERSION";
+                break;
+            case ROOTPA_ERROR_SE_PRECONDITION_NOT_MET:
+                ret+=": ROOTPA_ERROR_SE_PRECONDITION_NOT_MET";
+                break;
+            default:
+                break;
+        }
+
+        return ret;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags){
+        out.writeInt(result_);
+    }
+
+    private void readFromParcel(Parcel in){
+        result_=in.readInt();
+    }
+
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/IfcVersion.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/IfcVersion.java
new file mode 100644 (file)
index 0000000..c66c9f9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ROOTPA
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+public class IfcVersion{
+
+    public final static int ROOTPA_ANDROID_API_VERSION_MAJOR=1;
+    public final static int ROOTPA_ANDROID_API_VERSION_MINOR=1;
+};
+
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl
new file mode 100644 (file)
index 0000000..0889f57
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \addtogroup ROOTPA  AIDL Interfaces
+ * @{
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import com.gd.mobicore.pa.ifc.CommandResult;
+
+
+/**
+ * This API contains method(s) that are intended to be used for developer
+ * TA installation. Note that this API may be removed in the future when the
+ * developer TA installation is handled by a service manager and installation of
+ * all trutlets follow the same architecture for RootPA point of view.
+ *
+ * The service is started by sending intent com.gd.mobicore.pa.service.DEVELOPER_SERVICE in binding.
+ * The service is protected by permission com.gd.mobicore.pa.permission.DEVELOPER_PERMISSION with
+ * protectionLevel "normal"
+ */
+interface RootPADeveloperIfc{
+
+    /**
+     * This method can be used for installing "developer TA" that is not tied to any
+     * service provider and/or service manager. It contacts Service Enabler and asks it to
+     * perform the tasks, so the device has to be connected to network in order for this to
+     * succeed.
+     *
+     * The service progress is informed with the same Intents as is progress of the
+     * @ref RootPAServiceIfc#doProvisioning, however there is an additional
+     * Intent com.gd.mobicore.pa.service.INSTALL_TRUSTLET for returning the encrypted
+     * TA binary (in case of dynamic installation where taBinary is given
+     * as a parameter).
+     *
+     * There are constants related to the intents in @ref RootPAProvisioningIntents
+     *
+     * @param spid service provider id
+     * @param uuid uuid of the TA in hex, without dashes. Needs to be correct length.
+     * @param taBinary TA binary to be encrypted with and returned back.
+     *        If the binary is already encrypted, this array must be empty. The binary
+     *        has to be encrypted for transfer. Note that only either taBinary
+     *        or key can be given. There are sperate instructions on how the binary is to
+     *        be encrypted and packaged. Key and taBinary are exclusive, only one of
+     *        them can be given. This methods uses default values for memoryType (2),
+     *        numberOfInstances (1) and flags (0) when TA binary is installed.
+     * @param key a key that has been used to encrypt the TA binary in case when
+     *        the TA binary is not given as a parameter. This key has to be
+     *        encrypted for transfer. There are sperate instructions on how the key is to
+     *        be encrypted and packaged. Key and taBinary are exclusive, only one of
+     *        them can be given.
+     * @param minTltVersion minimum version of the TA
+     * @param tltPukHash this field is not used at the moment, null is fine here.
+     *
+     * @return indication of successful start of provisioning thread (ROOTPA_OK) or an error code
+     */
+    CommandResult installTrustletOrKey(in int spid,
+                                       in byte[] uuid,
+                                       in byte[] taBinary,
+                                       in byte[] key,
+                                       in int minTltVersion,
+                                       in byte[] tltPukHash);
+
+    /**
+     * This method can be used for installing "developer TA" that is not tied to any
+     * service provider and/or service manager. It contacts Service Enabler and asks it to
+     * perform the tasks, so the device has to be connected to network in order for this to
+     * succeed.
+     *
+     * The service progress is informed with the same Intents as is progress of the
+     * @ref RootPAServiceIfc#doProvisioning, however there is an additional
+     * Intent com.gd.mobicore.pa.service.INSTALL_TRUSTLET for returning the encrypted
+     * TA binary.
+     *
+     * There are constants related to the intents in @ref RootPAProvisioningIntents
+     *
+     * @param spid service provider id
+     * @param uuid uuid of the TA in hex, without dashes. Needs to be correct length.
+     * @param taBinary TA binary to be encrypted with and returned back.
+     *        If the binary is already encrypted, this array must be empty. The binary
+     *        has to be encrypted for transfer. Note that only either taBinary
+     *        or key can be given. There are sperate instructions on how the binary is to
+     *        be encrypted and packaged.
+     * @param minTltVersion minimum version of the TA
+     * @param tltPukHash this field is not used at the moment, null is fine here.
+     * @param memoryType memory where the TA is to be loaded and executed: 0 - if enough space is available,
+              load the TA into the internal memory, otherwise into the external memory, 1 - internal memory,
+              2 - external memory
+     * @param numberOfInstances indicates how many instances of a TA can be installed (run) in parallel
+     * @param flags current flags are: 1 - permanent, 2 - service has no WSW control interface,  4 - debuggable
+     *
+     * @return indication of successful start of provisioning thread (ROOTPA_OK) or an error code
+     */
+    CommandResult installTrustlet(in int spid,
+                                  in byte[] uuid,
+                                  in byte[] taBinary,
+                                  in int minTltVersion,
+                                  in byte[] tltPukHash,
+                                  in int memoryType,
+                                  in int numberOfInstances,
+                                  in int flags);
+
+}
+
+/**@}*/
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAOemIfc.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAOemIfc.aidl
new file mode 100644 (file)
index 0000000..973801c
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \addtogroup ROOTPA AIDL Interfaces
+ * @{
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import com.gd.mobicore.pa.ifc.CommandResult;
+
+/**
+* RootPAOemIfc is intended to be used by OEM only. It provides means to initiate unregistering root container.
+*
+* The service is started by sending intent com.gd.mobicore.pa.service.OEM_SERVICE in binding. The service is
+* protected by permission com.gd.mobicore.pa.permission.OEM_PERMISSION with protectionLevel "signatureOrSystem"
+*/
+interface RootPAOemIfc{
+
+    /**
+     * For OEM testing purposes only. Contacts Service Enabler and requests it to unregister the root container,
+     * so the device has to be connected to network for the call to succeed. The command returns almost immediately
+     * and executes in a separate thread, the same status Intents and values as are returned with
+     * @ref RootPAServiceIfc#doProvisioning can be returned when calling this methods. With the addition of value:
+     * <ul>
+     *     <li>UNREGISTERING_ROOT_CONTAINER (id 3000)</li>
+     * </ul>
+     *
+     * There are constants related to the intents in @ref RootPAProvisioningIntents
+     *
+     * @return indication of successful start of provisioning thread (ROOTPA_OK) or an error code
+     */
+    CommandResult unregisterRootContainer();
+}
+/**@}*/
+
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAProvisioningIntents.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAProvisioningIntents.java
new file mode 100644 (file)
index 0000000..9a1c7a0
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+/**
+ * A list of intent actions that the root PA can broadcast.
+ */
+public class RootPAProvisioningIntents {
+
+//
+/** Intents for starting up and connecting to services  */
+//
+
+    public static final String PROVISIONING_SERVICE="com.gd.mobicore.pa.service.PROVISIONING_SERVICE";
+    public static final String DEVELOPER_SERVICE="com.gd.mobicore.pa.service.DEVELOPER_SERVICE";
+    public static final String OEM_SERVICE="com.gd.mobicore.pa.service.OEM_SERVICE";
+
+//
+/** Execution status reporting Intents   */
+//
+
+/** Provisioning is ongoing. The intent contained additional data in the integer field pointed by STATUS */
+    public static final String PROVISIONING_PROGRESS_UPDATE = "com.gd.mobicore.pa.service.PROVISIONING_PROGRESS_UPDATE";
+/** root provisioning was attempted but failed - the intent will contain an error code */
+    public static final String PROVISIONING_ERROR = "com.gd.mobicore.pa.service.PROVISIONING_ERROR";
+/** root provisioning has completed, root and SP containers are available for use */
+    public static final String FINISHED_ROOT_PROVISIONING = "com.gd.mobicore.pa.service.PROVISIONING_FINISHED";
+
+
+/** this intent contains developer trustlet in it's extra data. The trustlet has been signed by SE */
+    public static final String INSTALL_TRUSTLET = "com.gd.mobicore.pa.service.INSTALL_TRUSTLET";
+
+//
+/** Names of extra data field's for intents */
+//
+
+/** Additional state information in PROVISIONING_PROGRESS_UPDATE intent */
+    public static final String STATE ="com.gd.mobicore.pa.ifc.State";
+/** Error code field in PROVISIONING_ERROR intent */
+    public static final String ERROR ="com.gd.mobicore.pa.ifc.Error";
+/** Error code field in INSTALL_TRUSTLET intent */
+    public static final String TRUSTLET ="com.gd.mobicore.pa.ifc.Trustlet";
+
+//
+/** possible values for STATE field */
+//
+
+/** root provisioning has started and a connection to SE is being established */
+    public static final int CONNECTING_SERVICE_ENABLER=100;
+    public static final int AUTHENTICATING_SOC=200;
+/** connection to SE has been established during provisioning and the root container is being created */
+    public static final int CREATING_ROOT_CONTAINER=300;
+    public static final int AUTHENTICATING_ROOT=400;
+/** connection to SE has been established during provisioning and the SP container is being created */
+    public static final int CREATING_SP_CONTAINER=500;
+    public static final int FINISHED_PROVISIONING=1000;
+/** unregistering root container will be sent by SE after OemService.unregisterRootContainer is used */
+    public static final int UNREGISTERING_ROOT_CONTAINER=3000;
+
+       private RootPAProvisioningIntents() { }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAServiceIfc.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPAServiceIfc.aidl
new file mode 100644 (file)
index 0000000..1efc03d
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \addtogroup ROOTPA AIDL Interfaces
+ * @{
+ */
+package com.gd.mobicore.pa.ifc;
+
+import java.util.List;
+import com.gd.mobicore.pa.ifc.CmpCommand;
+import com.gd.mobicore.pa.ifc.CmpResponse;
+import com.gd.mobicore.pa.ifc.CommandResult;
+import com.gd.mobicore.pa.ifc.BooleanResult;
+import com.gd.mobicore.pa.ifc.SPID;
+import com.gd.mobicore.pa.ifc.Version;
+import com.gd.mobicore.pa.ifc.SUID;
+import com.gd.mobicore.pa.ifc.SPContainerStructure;
+import com.gd.mobicore.pa.ifc.SPContainerStateParcel;
+
+/**
+* RootPAServiceIfc is intended for SP.PA use at the time of installing new TA. It provides means
+* to communicate with content management TA (using CMP version 3), request SE to perform provisioning
+* of root container and TA container and means to obtain some information on the MobiCore and its registry.
+*
+* The service is started by sending intent com.gd.mobicore.pa.service.PROVISIONING_SERVICE in binding.
+*/
+interface RootPAServiceIfc {
+
+    /**
+     * Checks if a root container is registered.
+     * Lock must not be acquired before executing this method and it can not be
+     * acquired while this method runs.
+     *
+     * @param result true if root container exists.
+     * @return indication of successful completion
+     */
+    CommandResult isRootContainerRegistered(out BooleanResult result);
+
+    /**
+     * Checks if a specific SP container is registered.
+     * Lock must not be acquired before executing this method and it can not be
+     * acquired while this method runs.
+     *
+     * @param spid SPID of the Service Provider
+     * @param result is true if the SP container exists.
+     * @return indication of successful completion
+     */
+    CommandResult isSPContainerRegistered(in SPID spid, out BooleanResult result);
+
+    /**
+     * Returns the version of various components of the MobiCore OS and surrounding components.
+     * Lock must not be acquired before executing this method and it can not be
+     * acquired while this method runs.
+     *
+     * @param version the result code of the call is saved in this parameter.
+     * @return indication of successful completion
+     */
+    CommandResult getVersion(out Version version);
+
+    /**
+     * Returns the SUID of the device.
+     * Lock must not be acquired before executing this method and it can not be
+     * acquired while this method runs.
+     *
+     * @param suid the result of the SUID is saved in this parameter.
+     * @return indication of successful completion
+     */
+    CommandResult getDeviceId(out SUID suid);
+
+    /**
+     * Acquires an exclusive communication lock with the MobiCore CMTL and registers the UID as the owner of the lock.
+     * Subsequent calls to acquire a lock by the same application with the same UID will succeed, but requests for a lock
+     * by other applications with different UIDs will fail until the lock is released. A lock is released when
+     * {@link #releaseLock(int)} is called or the lock times out 60 seconds after being acquired. Each subsequent
+     * call to acquire a lock with the same UID will reset the lock timeout counter, so that it expires 60 seconds after
+     * the most recent call.
+     * @param uid a unique value for the application that wishes to acquire a lock (the user id of the process satisfies this)
+     * @return indication of successful completion
+     */
+    CommandResult acquireLock(int uid);
+
+    /**
+     * Explicitly frees a lock.
+     *
+     * @param uid the user id of the process which is accessing.
+     * @return indication of successful completion
+     */
+    CommandResult releaseLock(int uid);
+
+    /**
+     * Executes a list of CMP commands and returns the corresponding CMP responses.
+     * If one of the commands result in an error then the following commands are
+     * not executed anymore, unless the command object has "ignoreError" set true.
+     * A lock is required to execute this method.
+     *
+     * Note that this causes only excution of the CMP command(s) and reads/stores the
+     * secure objects when needed. It does not initiate any discussion with Servce Enabler
+     * or any other network component with any of CMP commands.
+     *
+     * @param uid the user id of the process which is accessing.
+     * @param commands the CMP commands to be executed
+     * @param responses the CMP command responses
+     * @return result code of the call
+     */
+     CommandResult executeCmpCommands(int uid, in List<CmpCommand> commands, out List<CmpResponse> responses);
+
+    /**
+     * Starts provisioning. What actually happens after calling this depends on the state of the system and the commands SE sends.
+     * In normal situation, SE sends commands to create root container and SP container (indicated by spid) if they do not already
+     * exist. If given spid is 0, only root container is created (if it does not already exist).
+     * Tasks are performed asynchronously. Method returns immediately.
+     * Intents are broadcast to indicate the progress of the provisioning. The result is also
+     * sent via broadcast.
+     *
+     * Cannot be executed if the acquireLock is called. Release any lock before calling this
+     * method. Also, this command acquires lock internally before executing and releases lock
+     * when error occurs or provisioning is finished (just before sending FINISHED_ROOT_PROVISIONING intent) or after 1 minute timeout.
+     *
+     * The following intents are broadcast after calling doProvisioning:
+     * <ul>
+     *     <li>com.gd.mobicore.pa.service.PROVISIONING_PROGRESS_UPDATE: Sent when the progress is changing, status can be one of the following.
+     *         <ul>
+     *             <li>CONNECTING_SERVICE_ENABLER (id 100)</li>
+     *             <li>AUTHENTICATING_SOC (id 200)</li>
+     *             <li>CREATING_ROOT_CONTAINER (id 300)</li>
+     *             <li>AUTHENTICATING_ROOT (id 400)</li>
+     *             <li>CREATING_SP_CONTAINER (id 500)</li>
+     *             <li>FINISHED_PROVISIONING (id 1000)</li>
+     *         </ul>
+     *     </li>
+     *     <li>com.gd.mobicore.pa.service.FINISHED_ROOT_PROVISIONING: Sent when the provisioning is finished.</li>
+     *     <li>com.gd.mobicore.pa.service.PROVISIONING_ERROR: Sent when an error has occured, also contains an error code.</li>
+     * </ul>
+     * Note that depending on the nature of th errors it is possible that more than one PROVISIONING_ERROR intents are sent
+     * before the excution of provisioning is fully stopped. This depends a lot on whether SE can still continue execution.
+     *
+     * There are constants related to the intents in @ref RootPAProvisioningIntents
+     *
+     * Service Enabler is contacted and asked to perform the tasks, so the device has to be connected to network
+     * in order for this to succeed.
+     *
+     * @param uid the user id of the process which is accessing.
+     * @param spid the service provider id for which a SP container should be created
+     * @return indication of successful start of provisioning thread (ROOTPA_OK) or an error code
+     */
+
+    CommandResult doProvisioning(int uid, in SPID spid);
+
+    /**
+     * Interrogates the SP container structure.
+     * Lock must not be acquired before executing this method and it can not be
+     * acquired while this method runs.
+     *
+     * @param spid provides [in] the id of the SP (SPCont)
+     * @param cs [out] state of the sp container and a list of installed TA containers for the given SP
+     * @return indication of successful completion
+     */
+    CommandResult getSPContainerStructure(in SPID spid, out SPContainerStructure cs);
+
+    /**
+     * Interrogates the state of an SP container.
+     * Lock must not be acquired before executing this method and it can not be
+     * acquired while this method runs.
+     *
+     * @param spid [in] service provider id to query
+     * @param state [out] the state of the SP container
+     * @return indication of successful completion
+     */
+    CommandResult getSPContainerState(in SPID spid, out SPContainerStateParcel state);
+
+
+    /**
+     * Stores the actual TA binary to registry.
+     *
+     * @param spid [in] service provider id
+     * @param uuid [in] unique UUID of the TA
+     * @param taBinary [in] the actual TA to be stored
+     * @return indication of successful completion
+     */
+    CommandResult storeTA(in SPID spid, in byte[] uuid, in byte[] taBinary);
+}
+
+/**@}*/
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerState.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerState.java
new file mode 100644 (file)
index 0000000..fa8ba70
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+/**
+ * Lifecycle states of SP containers.
+ */
+public enum SPContainerState {
+       /** the container does not exist */
+       DOES_NOT_EXIST,
+       /** the container is locked because the SP container is locked */
+       SP_LOCKED,
+       /** the container is locked because the root container is locked */
+       ROOT_LOCKED,
+       /** initial state, not yet initialized */
+       UNDEFINED,
+       /** the container is registered, but not activated */
+       REGISTERED,
+       /** the container is registered and activated */
+       ACTIVATED,
+       /** the container is locked by both root and sp*/
+       ROOT_SP_LOCKED
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStateParcel.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStateParcel.aidl
new file mode 100644 (file)
index 0000000..c96ae46
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable SPContainerStateParcel;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStateParcel.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStateParcel.java
new file mode 100644 (file)
index 0000000..fa1de10
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+
+/**
+ * Lifecycle states of SP containers.
+ */
+public class SPContainerStateParcel extends AbstractEnumParcel<SPContainerState> {
+       /**
+        * Reads the enumerated value from the given parcel.
+        * @param source parcel containing a single string value representing the enumeration
+        * @throws IllegalArgumentException if the parcel contains a string that does not resolve to an enumeration
+        */
+       public void readFromParcel(final Parcel source) {
+               final String value = source.readString();
+               if (value != null)
+                       setEnumeratedValue(SPContainerState.valueOf(value));
+       }
+
+       public static final Creator<SPContainerStateParcel> CREATOR = new Creator<SPContainerStateParcel>() {
+               @Override
+               public SPContainerStateParcel createFromParcel(Parcel source) {
+                       final SPContainerStateParcel cs = new SPContainerStateParcel();
+                       cs.readFromParcel(source);
+                       return cs;
+               }
+
+               @Override
+               public SPContainerStateParcel[] newArray(int size) {
+                       return new SPContainerStateParcel[size];
+               }
+       };
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStructure.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStructure.aidl
new file mode 100644 (file)
index 0000000..cfaab65
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable SPContainerStructure;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStructure.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPContainerStructure.java
new file mode 100644 (file)
index 0000000..ea58c3a
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Serializes the state of the sp container and a list of installed trustlet containers into a parcel.
+ */
+public class SPContainerStructure implements Parcelable {
+       /** State of the sp container */
+       private SPContainerState state_;
+       /** The trustlet containers registered for this SPCont */
+       private final List<TrustletContainer> tcList_;
+
+       public SPContainerStructure(SPContainerState state, List<TrustletContainer> tcList) {
+               this.state_ = state;
+               this.tcList_ = tcList;
+       }
+
+       public SPContainerStructure() {
+               this(null, new ArrayList<TrustletContainer>());
+       }
+
+       public void add(TrustletContainer tc) {
+               tcList_.add(tc);
+       }
+
+       public SPContainerState state() {
+               return state_;
+       }
+
+       public List<TrustletContainer> tcList() {
+               return tcList_;
+       }
+
+       public void setState(SPContainerState state) {
+               this.state_ = state;
+       }
+
+       @Override
+       public int describeContents() {
+               return 0;
+       }
+
+       @Override
+       public void writeToParcel(Parcel dest, int flags) {
+               if (state_ == null)
+                       dest.writeString(null);
+               else
+                       dest.writeString(state_.toString());
+               dest.writeTypedList(tcList_);
+       }
+
+       public static final Creator<SPContainerStructure> CREATOR = new Creator<SPContainerStructure>() {
+               @Override
+               public SPContainerStructure createFromParcel(Parcel source) {
+                       SPContainerStructure cs = new SPContainerStructure();
+                       cs.readFromParcel(source);
+                       return cs;
+               }
+
+               @Override
+               public SPContainerStructure[] newArray(int size) {
+                       return new SPContainerStructure[size];
+               }
+       };
+
+       /**
+        * Reads a parcel and deserializes it into an instance of this class.
+        * @param source parcel data
+        * @return never null
+        * @throws IllegalArgumentException if the parcel contains a state string that does not resolve to an enumeration
+        */
+       public void readFromParcel(Parcel source) {
+               final String state = source.readString();
+               if (state != null && state.length() > 0)
+                       this.state_ = SPContainerState.valueOf(state);
+               source.readTypedList(this.tcList_, TrustletContainer.CREATOR);
+       }
+
+       @Override
+       public String toString() {
+               return "SPContainerStructure{" + "state=" + state_ + ", tcList=" + tcList_ + '}';
+       }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPID.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPID.aidl
new file mode 100644 (file)
index 0000000..7048774
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable SPID;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPID.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SPID.java
new file mode 100644 (file)
index 0000000..2e5bf2b
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Service Provider ID.
+ */
+public class SPID implements Parcelable {
+    private int spid_;
+
+    public SPID(int spid) {
+        this.spid_ = spid;
+    }
+
+    public SPID() {
+    }
+
+    public int spid() {
+        return spid_;
+    }
+
+    // parcelable interface
+
+    public static final Parcelable.Creator<SPID> CREATOR = new Parcelable.Creator<SPID>() {
+        public SPID createFromParcel(Parcel in) {
+            return new SPID(in);
+        }
+
+        public SPID[] newArray(int size) {
+            return new SPID[size];
+        }
+    };
+
+    private SPID(Parcel in) {
+        spid_ = in.readInt();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(spid_);
+    }
+
+       @Override
+       public boolean equals(Object o) {
+               if (this == o) return true;
+               if (o == null || getClass() != o.getClass()) return false;
+               final SPID spid = (SPID) o;
+               return spid_ == spid.spid_;
+       }
+
+       @Override
+       public int hashCode() {
+               return spid_;
+       }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SUID.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SUID.aidl
new file mode 100644 (file)
index 0000000..06ff3f5
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable SUID;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SUID.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/SUID.java
new file mode 100644 (file)
index 0000000..1f75c0c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A unique device ID.
+ */
+public class SUID implements Parcelable {
+    private final static int SUID_LENGTH=16;
+    private byte[] suid_;
+
+    public SUID() {
+    }
+
+    public SUID(byte[] suid) {
+        setSuid(suid);
+    }
+
+    public void setSuid(final byte[] suid) {
+               if (suid == null)
+                       throw new IllegalArgumentException("Cannot set null SUID.");
+        if (suid.length != SUID_LENGTH)
+            throw new IllegalArgumentException("Bad length given, SUID has to be "+SUID_LENGTH+" bytes in length");
+
+        this.suid_ = suid.clone();
+    }
+
+    public byte[] suid() {
+        return suid_;
+    }
+
+    // parcelable interface
+    public static final Parcelable.Creator<SUID> CREATOR = new Parcelable.Creator<SUID>() {
+        public SUID createFromParcel(Parcel in) {
+            return new SUID(in);
+        }
+
+        public SUID[] newArray(int size) {
+            return new SUID[size];
+        }
+    };
+
+    private SUID(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public void readFromParcel(Parcel in) {
+        if(in.dataAvail()>=SUID_LENGTH){
+            this.suid_ = new byte[SUID_LENGTH];
+            in.readByteArray(suid_);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        if(suid_!=null){
+            out.writeByteArray(suid_);
+        }
+    }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainer.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainer.aidl
new file mode 100644 (file)
index 0000000..a0dc152
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable TrustletContainer;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainer.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainer.java
new file mode 100644 (file)
index 0000000..4af3fc8
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.UUID;
+
+/**
+ * Trustlet Container class
+ */
+public class TrustletContainer implements Parcelable {
+       /** The UUID addressing the trustlet container */
+       private UUID trustletId_;
+       private TrustletContainerStateParcel state_;
+
+       public TrustletContainer() {
+       }
+
+       public TrustletContainer(UUID trustletId, TrustletContainerState state) {
+               this.trustletId_ = trustletId;
+               this.state_ = new TrustletContainerStateParcel(state);
+       }
+
+       @Override
+       public int describeContents() {
+               return 0;
+       }
+
+       @Override
+       public void writeToParcel(Parcel dest, int flags) {
+               dest.writeString(trustletId_.toString());
+               if (state_ == null)
+                       dest.writeString(null);
+               else
+                       state_.writeToParcel(dest, 0);
+       }
+
+       public static TrustletContainer readFromParcel(Parcel source) {
+               final TrustletContainer tc = new TrustletContainer();
+               tc.setTrustletId(source.readString());
+               tc.setState(TrustletContainerStateParcel.CREATOR.createFromParcel(source));
+               return tc;
+       }
+
+       public static final Creator<TrustletContainer> CREATOR = new Creator<TrustletContainer>() {
+               @Override
+               public TrustletContainer createFromParcel(Parcel source) {
+                       return readFromParcel(source);
+               }
+
+               @Override
+               public TrustletContainer[] newArray(int size) {
+                       return new TrustletContainer[size];
+               }
+       };
+
+       public UUID trustletId() {
+               return trustletId_;
+       }
+
+       public void setTrustletId(UUID trustletId) {
+               this.trustletId_ = trustletId;
+       }
+
+       public void setTrustletId(String trustletId) {
+               if (trustletId != null)
+                       this.trustletId_ = UUID.fromString(trustletId);
+               else
+                       this.trustletId_ = null;
+       }
+
+       public TrustletContainerStateParcel state() {
+               return state_;
+       }
+
+       public void setState(TrustletContainerStateParcel state) {
+               this.state_ = state;
+       }
+
+       @Override
+       public String toString() {
+               return "TrustletContainer{" + "trustletId=" + trustletId_ + ", state=" + state_ + '}';
+       }
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerState.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerState.java
new file mode 100644 (file)
index 0000000..08eb060
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+/**
+ * Lifecycle states of trustlets.
+ */
+public enum TrustletContainerState {
+       /** initial state, not yet initialized */
+       UNDEFINED,
+       /** the container is registered, but not activated */
+       REGISTERED,
+       /** the container is registered and activated */
+       ACTIVATED,
+       /** the container is locked */
+       SP_LOCKED
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerStateParcel.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerStateParcel.aidl
new file mode 100644 (file)
index 0000000..49eeb7c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable TrustletContainerStateParcel;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerStateParcel.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/TrustletContainerStateParcel.java
new file mode 100644 (file)
index 0000000..97ee603
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Parcel;
+
+/**
+ * Wraps the enumeration of trustlet container states.
+ */
+public class TrustletContainerStateParcel extends AbstractEnumParcel<TrustletContainerState> {
+       public TrustletContainerStateParcel() {
+       }
+
+       public TrustletContainerStateParcel(TrustletContainerState enumeratedValue) {
+               super(enumeratedValue);
+       }
+
+       /**
+        * Reads the enumerated value from the given parcel.
+        * @param source parcel containing a single string value representing the enumeration
+        * @throws IllegalArgumentException if the parcel contains a string that does not resolve to an enumeration
+        */
+       public void readFromParcel(final Parcel source) {
+               final String value = source.readString();
+               if (value != null)
+                       setEnumeratedValue(TrustletContainerState.valueOf(value));
+       }
+
+       public static final Creator<TrustletContainerStateParcel> CREATOR = new Creator<TrustletContainerStateParcel>() {
+               @Override
+               public TrustletContainerStateParcel createFromParcel(Parcel source) {
+                       final TrustletContainerStateParcel cs = new TrustletContainerStateParcel();
+                       cs.readFromParcel(source);
+                       return cs;
+               }
+
+               @Override
+               public TrustletContainerStateParcel[] newArray(int size) {
+                       return new TrustletContainerStateParcel[size];
+               }
+       };
+}
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/Version.aidl b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/Version.aidl
new file mode 100644 (file)
index 0000000..be24fce
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+parcelable Version;
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/Version.java b/mobicore/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/Version.java
new file mode 100644 (file)
index 0000000..00074e3
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.gd.mobicore.pa.ifc;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Map;
+
+/**
+ * Contains the device's product ID and a collection of version numbers for various software components installed on
+ * the device.
+ */
+public class Version implements Parcelable {
+    public final static String VERSION_FIELD_TAG="TAG";
+    public final static String VERSION_FIELD_TAG1ALL="TAG1ALL";
+    public final static String VERSION_FIELD_MCI="MCI";
+    public final static String VERSION_FIELD_SO="SO";
+    public final static String VERSION_FIELD_MCLF="MCLF";
+    public final static String VERSION_FIELD_CONT="CONT";
+    public final static String VERSION_FIELD_MCCONF="MCCONF";
+    public final static String VERSION_FIELD_TLAPI="TLAPI";
+    public final static String VERSION_FIELD_DRAPI="DRAPI";
+    public final static String VERSION_FIELD_CMP="CMP";
+
+       private String productId_;
+       private Bundle version_;
+
+    public Version() {
+    }
+
+    public Version(String productId, Bundle version) {
+        setVersion(version);
+               setProductId(productId);
+    }
+
+       public String productId() {
+               return productId_;
+       }
+
+       public void setProductId(String productId) {
+               this.productId_ = productId;
+       }
+
+       public Bundle version() {
+               return version_;
+       }
+
+       public void setVersion(Bundle version) {
+               this.version_ = version;
+       }
+
+//parcelable interface
+
+    public static final Creator<Version> CREATOR = new Creator<Version>() {
+        public Version createFromParcel(Parcel in) {
+            return new Version(in);
+        }
+
+        public Version[] newArray(int size) {
+            return new Version[size];
+        }
+    };
+
+    private Version(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public void readFromParcel(Parcel in) {
+               productId_ = in.readString();
+        version_ = in.readBundle();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        if(productId_!=null){
+               out.writeString(productId_);
+        }
+        if(version_!=null){
+            out.writeBundle(version_);
+        }
+    }
+
+}
diff --git a/mobicore/rootpa/Code/CMakeLists.txt b/mobicore/rootpa/Code/CMakeLists.txt
new file mode 100644 (file)
index 0000000..57329d4
--- /dev/null
@@ -0,0 +1,43 @@
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(LIBDIR "${PREFIX}/lib")
+SET(RESOURCEDIR "${CMAKE_CURRENT_SOURCE_DIR}/resource")
+
+set(CMAKE_VERBOSE_MAKEFILE ON)
+
+pkg_check_modules(rpkgs REQUIRED libxml2)
+pkg_check_modules(rpkgs REQUIRED libxml2-devel)
+pkg_check_modules(rpkgs REQUIRED libwbxml2)
+pkg_check_modules(rpkgs REQUIRED libcurl-devel)
+pkg_check_modules(rpkgs REQUIRED openssl-devel)
+add_definitions(${rpkgs_CFLAGS})
+
+SET(SRCS
+        Common/base64.c
+        Common/commandhandler.c
+        Common/contentmanager.c
+        Common/pacmp3.c
+        Common/pacmtl.c
+        Common/provisioningengine.c
+        Common/registry.c
+        Common/seclient.c
+        Common/trustletchannel.c
+        Common/xmlmessagehandler.c
+)
+
+INCLUDE_DIRECTORIES(Common/include)
+INCLUDE_DIRECTORIES(Common)
+INCLUDE_DIRECTORIES(/usr/include/libxml2)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag} -Wconversion-null -Werror=strict-aliasing")
+ENDFOREACH(flag)
+
+ADD_DEFINITIONS("-DLINUX -DARM -D_32BIT -DANDROID_ARM=1 -DTIZEN")
+
+# Rules for LIBPROVISIONINGAGENT
+SET(LIBPROVISIONINGAGENT_SO "provisioningagent")
+ADD_LIBRARY(${LIBPROVISIONINGAGENT_SO} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${LIBPROVISIONINGAGENT_SO} ${rpkgs_LDFLAGS} ${LIBCLIENT_SO} ${LIBREGISTRY_SO} -lssl -lcrypto -lz -lxml2 -lcurl)
+
+INSTALL(TARGETS ${LIBPROVISIONINGAGENT_SO} DESTINATION ${LIBDIR})
+INSTALL(DIRECTORY Common/include/ DESTINATION /usr/include FILES_MATCHING PATTERN "*.h")
diff --git a/mobicore/rootpa/Code/Common/Android.mk b/mobicore/rootpa/Code/Common/Android.mk
new file mode 100644 (file)
index 0000000..031e1dd
--- /dev/null
@@ -0,0 +1,87 @@
+#
+# Copyright Â© Trustonic Limited 2013
+#
+# All rights reserved.
+#
+#  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. Neither the name of the Trustonic Limited nor the names of its contributors 
+#     may be used to endorse or promote products derived from this software 
+#     without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+#
+# makefile for building the provisioning agent Common part for android. build the code by executing 
+# $NDK_ROOT/ndk-build in the folder where this file resides
+#
+# naturally the right way to build is to use build script under Build folder. It then uses this file.
+#
+
+
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS += -DANDROID_ARM=1
+LOCAL_CFLAGS += -DANDROID 
+LOCAL_CFLAGS +=-fstack-protector
+ifeq ($(DEBUG), 1)
+    LOCAL_CFLAGS += -D__DEBUG=1
+endif    
+
+
+LOCAL_SRC_FILES += pacmp3.c
+LOCAL_SRC_FILES += pacmtl.c
+LOCAL_SRC_FILES += trustletchannel.c
+LOCAL_SRC_FILES += registry.c
+LOCAL_SRC_FILES += seclient.c
+LOCAL_SRC_FILES += base64.c
+LOCAL_SRC_FILES += xmlmessagehandler.c
+LOCAL_SRC_FILES += provisioningengine.c
+LOCAL_SRC_FILES += contentmanager.c
+LOCAL_SRC_FILES += commandhandler.c
+
+
+LOCAL_C_INCLUDES +=  $(MOBICORE_DIR_INC)
+LOCAL_C_INCLUDES +=  external/curl/include
+LOCAL_C_INCLUDES +=  external/icu/icu4c/source/common
+LOCAL_C_INCLUDES +=  external/icu4c/common
+LOCAL_C_INCLUDES +=  external/libxml2/include
+LOCAL_C_INCLUDES +=  .
+LOCAL_C_INCLUDES +=  $(LOCAL_PATH)/include
+
+ifeq ($(ROOTPA_MODULE_TEST), 1)
+    LOCAL_STATIC_LIBRARIES +=  McStub
+    LOCAL_MODULE    := provisioningagent_test
+else
+    LOCAL_MODULE    := provisioningagent
+endif
+
+LOCAL_MODULE_TAGS := debug eng optional
+
+LOCAL_STATIC_LIBRARIES = MobiCoreTlcm
+LOCAL_SHARED_LIBRARIES = libMcClient libMcRegistry
+
+APP_PIE := true
+LOCAL_32_BIT_ONLY := true
+include $(BUILD_STATIC_LIBRARY)
diff --git a/mobicore/rootpa/Code/Common/NOTICE b/mobicore/rootpa/Code/Common/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/rootpa/Code/Common/README-Android.txt b/mobicore/rootpa/Code/Common/README-Android.txt
new file mode 100644 (file)
index 0000000..48fe7f5
--- /dev/null
@@ -0,0 +1 @@
+Build the component for Android by running ndk-build in ProvisioningAgent/Android/jni
diff --git a/mobicore/rootpa/Code/Common/base64.c b/mobicore/rootpa/Code/Common/base64.c
new file mode 100644 (file)
index 0000000..23685c8
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+The content of this file is copied from b64.c (http://base64.sourceforge.net)
+and modified to work with memory buffers instead of files.
+
+The linebreak addition has been removed from the encoding part
+
+COPYRIGHT AND LICENCE from the original code, applies only to this file:
+                Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
+
+                Permission is hereby granted, free of charge, to any person
+                obtaining a copy of this software and associated
+                documentation files (the "Software"), to deal in the
+                Software without restriction, including without limitation
+                the rights to use, copy, modify, merge, publish, distribute,
+                sublicense, and/or sell copies of the Software, and to
+                permit persons to whom the Software is furnished to do so,
+                subject to the following conditions:
+
+                The above copyright notice and this permission notice shall
+                be included in all copies or substantial portions of the
+                Software.
+
+                THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+                KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+                WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+                PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+                OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+                OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+                OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+                SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <string.h>
+#include "logging.h"
+#include "base64.h"
+
+static const char* cb64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char* cd64="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
+
+
+static void decodeblock( unsigned char *in, unsigned char *out )
+{
+    out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
+    out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
+    out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
+}
+
+#define ENCODEDSIZE 4
+#define PLAINSIZE 3
+
+#define ASCIIPLUS 43
+#define ASCIIz 122
+
+#define FIRSTB64ASCII ASCIIPLUS
+#define LASTB64ASCII ASCIIz
+
+#define LINESIZE 74
+
+/**
+Decode base64 encoded NULL terminated string. If the string is not NULL terminated the behaviour is undetermined.
+
+@param toBeDecoded the string to be decoded
+@param resultP pointer to the pointer to the buffer where the decoded data is. The caller has to free the buffer when not needed.
+@return size of the decoded string
+*/
+size_t base64DecodeStringRemoveEndZero(const char* toBeDecoded, char** resultP)
+{
+    size_t inSize;
+    size_t outSize;
+
+    unsigned char in[ENCODEDSIZE];
+    unsigned char out[PLAINSIZE];
+    int v;
+    int i, len;
+    size_t inIndex=0;
+    int outIndex=0;
+
+    LOGD(">> base64DecodeStringRemoveEndZero");
+    if(NULL==toBeDecoded) return 0;
+
+    inSize=strlen(toBeDecoded);
+    outSize=((inSize*PLAINSIZE)/ENCODEDSIZE)+((inSize*PLAINSIZE)%ENCODEDSIZE);
+    *resultP=(char *)malloc(outSize);
+
+    if((*resultP)==NULL) return 0;
+
+    LOGD("in %d out %d", (int) inSize, (int) outSize);
+
+       *in = (unsigned char) 0;
+       *out = (unsigned char) 0;
+
+
+    while( inIndex < inSize )
+    {
+        for( len = 0, i = 0; i < ENCODEDSIZE && inIndex < inSize; i++ )
+        {
+            v = 0;
+            // skip characters that do not belong to decoded base64 and set v
+            while( inIndex < inSize && 0 == v )
+            {
+                v = toBeDecoded[ inIndex++ ];
+
+                v = ((v < FIRSTB64ASCII || v > LASTB64ASCII) ? 0 : (int) cd64[ v - FIRSTB64ASCII ]);
+                       if( v != 0 )
+                {
+                    v = ((v == (int)'$') ? 0 : v - 61);
+                }
+            }
+
+            // set the character to in buffer, but only if it is not 0 (last character in toBeDecoded illegal)
+            if( inIndex <= inSize )
+            {
+                if( v != 0 )
+                {
+                    len++;
+                    in[ i ] = (unsigned char) (v - 1);
+                }
+            }
+            else
+            {
+                in[i] = (unsigned char) 0;
+            }
+        }
+
+        if( len > 0 )
+        {
+            decodeblock( in, out );
+            for( i = 0; i < (len - 1); i++ )
+            {
+                (*resultP)[outIndex++]=out[i];
+            }
+        }
+    }
+
+    LOGD("<< base64DecodeStringRemoveEndZero inIndex %d outIndex %d allocatedBuffer %d", (int) inIndex, (int) outIndex, (int) outSize);
+    return( outIndex );
+}
+
+static void encodeblock( unsigned char *in, unsigned char *out, int len )
+{
+    out[0] = (unsigned char) cb64[ (int)(in[0] >> 2) ];
+    out[1] = (unsigned char) cb64[ (int)(((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)) ];
+    out[2] = (unsigned char) (len > 1 ? cb64[ (int)(((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)) ] : '=');
+    out[3] = (unsigned char) (len > 2 ? cb64[ (int)(in[2] & 0x3f) ] : '=');
+}
+
+/**
+base64encode data to a NULL terminated string.
+
+@param toBeEncoded the buffer to be encoded
+@param length length of the buffer to be encoded
+@return pointer to NULL terminated base64encoded string. The caller has to free the buffer pointer by the pointer.
+*/
+char* base64EncodeAddEndZero(const char* toBeEncoded, size_t length)
+{
+    size_t outSize;
+    char* resultP;
+
+    unsigned char in[PLAINSIZE];
+       unsigned char out[ENCODEDSIZE];
+    int i, len;
+    size_t inIndex=0;
+    int outIndex=0;
+
+    LOGD(">> base64EncodeAddEndZero %d %s", (int) length, ((toBeEncoded!=NULL)?"ptr ok":"NULL"));
+    if(NULL==toBeEncoded) return NULL;
+
+    outSize=(length/PLAINSIZE + ((length%PLAINSIZE>0)?1:0))*ENCODEDSIZE+1;
+
+//    outSize+=(outsize/LINESIZE)*2; // crlf after each full line
+
+    resultP=(char *) malloc(outSize);
+
+    if(resultP==NULL) return NULL;
+    resultP[outSize-1]=0;
+
+    LOGD("in %d out %d", (int) length, (int) outSize);
+
+       *in = (unsigned char) 0;
+       *out = (unsigned char) 0;
+
+    while( inIndex < length )
+    {
+        len = 0;
+        for( i = 0; i < PLAINSIZE; i++ )
+        {
+            if( inIndex < length )
+            {
+                in[i] = toBeEncoded[inIndex];
+                len++;
+            }
+            else
+            {
+                in[i] = (unsigned char) 0;
+            }
+            inIndex++;
+        }
+
+        if( len > 0 )
+        {
+            encodeblock( in, out, len );
+            for( i = 0; i < ENCODEDSIZE; i++ )
+            {
+                resultP[outIndex++]=out[i];
+            }
+        // could be adding line breaks here but then we need to calculate also some space for them
+
+        }
+    }
+    resultP[outIndex]=0;
+    LOGD("<< base64EncodeAddEndZero %d <= (%d - 1)", (int) outIndex, (int) outSize);
+    return resultP;
+}
diff --git a/mobicore/rootpa/Code/Common/base64.h b/mobicore/rootpa/Code/Common/base64.h
new file mode 100644 (file)
index 0000000..c739641
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+#include <stdlib.h>
+
+size_t base64DecodeStringRemoveEndZero(const char* toBeDecoded, char** resultP);
+char* base64EncodeAddEndZero(const char* toBeEncoded, size_t length);
+
+
+#endif // BASE64_H
diff --git a/mobicore/rootpa/Code/Common/cacerts.h b/mobicore/rootpa/Code/Common/cacerts.h
new file mode 100644 (file)
index 0000000..4a1d9d4
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CACERTS_H
+#define CACERTS_H
+
+#define CA_CERTIFICATES \
+"Trustonic Root CA, expires Feb 21 16:36:51 2038 GMT\n\
+================================================================\n\
+-----BEGIN CERTIFICATE-----\n\
+MIIDcjCCAlqgAwIBAgIEEjRWADANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJV\n\
+SzEaMBgGA1UECgwRVHJ1c3RvbmljIExpbWl0ZWQxFDASBgNVBAMMC1RMUyBSb290\n\
+IENBMB4XDTEzMDIyNzE2MzY1MVoXDTM4MDIyMTE2MzY1MVowPzELMAkGA1UEBhMC\n\
+VUsxGjAYBgNVBAoMEVRydXN0b25pYyBMaW1pdGVkMRQwEgYDVQQDDAtUTFMgUm9v\n\
+dCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMaJYI6y7hxdxBoI\n\
+nTkiYhL2qhBtD0Kcmfx+NTiUUkO+9u9qSyzbsN7kfgpsLO8Eq3AGg72zEjayXDfz\n\
+mlHW1CnO/0nWDiM4b4hDhpJRspE2BCnKvAHAvcQeGpzX5hhZLYh51Zrn/pOLCvoR\n\
+9XV1inlw6M0+M9A5n11l6tEEWGbgWRnna+LJFX+bSGnihP1Be2nHsVnqcIDMo/hz\n\
+Cj2ZX2G95e+UVPIc9JK/SVqFzYHltNjUyOFG7jGOncDhdG9vgHUoiikr6ZF7NHao\n\
+vqxhIOiiK2tDVos//3/PgjrVwPkAJlVenMLpfEdxCtwyHO2frQpmkHc1eWFD5NGd\n\
+8vzh2qECAwEAAaN2MHQwHQYDVR0OBBYEFE9Csq2lSvztAMSjVdll4sxTPwvbMB8G\n\
+A1UdIwQYMBaAFE9Csq2lSvztAMSjVdll4sxTPwvbMA8GA1UdEwEB/wQFMAMBAf8w\n\
+DgYDVR0PAQH/BAQDAgIEMBEGCWCGSAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQsF\n\
+AAOCAQEAQrnIh4jpJtNf6hqnCpmwmQFD4456gFh0B3cmQnVvkfDCApJ+9G3xSsaL\n\
+8LJRvK6c/pAV9p+0pvh3ftV4MFSw9AytZrihsrVykxlI1UGRHJmDO1hRh5QlfbMV\n\
+fstHI0W8ec2Al41g3C9pM+FgBBKIoG6ewpDlaUbMXk8033jf/OIyF5HTeQYqr788\n\
+/ykFY32Mz0lpC2GdIeRThlK4ka63WuffdtKAayyPcitMeZtajJpa7s02MZF9Dd5s\n\
+hISypnUvXAN/BZXIwQXSAOqajTGEv3X/wLyasm3nkEX29IgDvknLBoqnTS9rD2LQ\n\
+4BnqNQubr5XROBOlwdkrHTveN4Y9pA==\n\
+-----END CERTIFICATE-----\n\
+\n\
+Apache2 vHost CA\n\
+================================================================\n\
+-----BEGIN CERTIFICATE-----\n\
+MIIHGzCCBQOgAwIBAgIJAOoMGzaC8DnTMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n\
+VQQGEwJGSTEQMA4GA1UECBMHRmlubGFuZDERMA8GA1UEBxMISGVsc2lua2kxEjAQ\n\
+BgNVBAoTCVRydXN0b25pYzEWMBQGA1UECxMNVHJ1c3RvbmljIFBLSTEaMBgGA1UE\n\
+AxMRVHJ1c3RvbmljIFJvb3QgQ0ExJjAkBgkqhkiG9w0BCQEWF3dlYm1hc3RlckB0\n\
+cnVzdG9uaWMuY29tMB4XDTEzMDIwNzA5MjgxM1oXDTMzMDIwMjA5MjgxM1owgaIx\n\
+CzAJBgNVBAYTAkZJMRAwDgYDVQQIEwdGaW5sYW5kMREwDwYDVQQHEwhIZWxzaW5r\n\
+aTESMBAGA1UEChMJVHJ1c3RvbmljMRYwFAYDVQQLEw1UcnVzdG9uaWMgUEtJMRow\n\
+GAYDVQQDExFUcnVzdG9uaWMgUm9vdCBDQTEmMCQGCSqGSIb3DQEJARYXd2VibWFz\n\
+dGVyQHRydXN0b25pYy5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n\
+AQDVo+0b8pUmMQZtCMs23qQJFGMAGoeeDw0h7YL/IQsXdWVldyMi+dJKibQY+sK0\n\
+7kg/1EyqAzSm0XQd1WPoPrbz11jHjfNXCXn3UVrVaccO/SUznC7BQ7BGLQC5A/ll\n\
+hJ65Eg2V+N/nAqfdN2Dto+3Eq9Kveqoxl6+hDrGtg44NyKI1bByTy32ZeQ9SL64E\n\
+MJmN6FTAdfW9ngiQ+lijooQ1Rv+Z/bgIw2Pz1wqUHDic7HPuVt1DO2aBmfXH9/Wr\n\
+sVCZu2+lXOaveU7zGcI/tSQijWTIAqE9EvvIl30TUt4AnyFShApyoVYTxNtkDoMz\n\
+XyrIXTsKIEVWSkpmQin8Q17R8URrluWOIN7Fr6JS64Rs6ZuBFi1/Ly3a1JleXV72\n\
+y4gM5AaAA216ntppX7B9cvjbjuW20bcmwJJ7nTikaA0D90J9kHGBCmOKNxI+baiy\n\
+IUPH4l9TaGykuqQ6GCLNMjpeKpo5pnRYZQxIzKmvWWAo96wRYZ+5P3ViUhSfNn6f\n\
+5AhAOwyAiAIiC/3Vuc2dDS4cE/IaWLTfva9IxSdW5fW6oURTsft9dLPGM9vkFTjO\n\
+ODs00hM4Q6a6WsmeIoaH/WgVD+MVlIO3o8+fUhdiQJyZIgtt/cquAlkr4/xBaARZ\n\
+0NMMKOZmiQJ27xqO8F0YoGmIks5wsN9AMV7BwlDs+rVffwIDAQABo4IBUDCCAUww\n\
+MAYJYIZIAYb4QgENBCMWIVtSb290IGNlcnRpZmljYXRpb24gYXV0aG9yaXR5XSBD\n\
+QTAdBgNVHQ4EFgQUWE1tsuTxDUQ4e+C8KJR6Y1Icn30wgdcGA1UdIwSBzzCBzIAU\n\
+WE1tsuTxDUQ4e+C8KJR6Y1Icn32hgaikgaUwgaIxCzAJBgNVBAYTAkZJMRAwDgYD\n\
+VQQIEwdGaW5sYW5kMREwDwYDVQQHEwhIZWxzaW5raTESMBAGA1UEChMJVHJ1c3Rv\n\
+bmljMRYwFAYDVQQLEw1UcnVzdG9uaWMgUEtJMRowGAYDVQQDExFUcnVzdG9uaWMg\n\
+Um9vdCBDQTEmMCQGCSqGSIb3DQEJARYXd2VibWFzdGVyQHRydXN0b25pYy5jb22C\n\
+CQDqDBs2gvA50zASBgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkq\n\
+hkiG9w0BAQUFAAOCAgEAJfOt6/wv8CMV5eP6191m68N3Ig0FypzqQlsYbLmKlOmj\n\
+80lVydHqp2nJGaqnCwmwzf8G+TkhvGqF9V+sABkoh+d1vOZAz486gmZNtx4yTIXm\n\
+0/n/RmrDf6jRx1RP7nNa+vNHjhGAdcXnWkYSbD/vWqSU9ujRPRWghAczOX35zfF1\n\
+JwCSzwNHXkQ98YitO9vB00yUCnoczSA9Dn2ffJtHzeWU0gbouN5Lbb65yB0F+SFY\n\
+zmDXXk2RiBKOF5NJZMX2XfxubgeU+CVE9Upe/mt8aoYzovO/IEx6SgJw2pvEGvXS\n\
+nt7I1oI0xa4TSe4eGnqEwrvESpE4lBDHRtxZ6wtD4iYj30oMXbmg1OrLE9ZypVRa\n\
+7SJTiOCABTy4RxVU9A+jFDDvMjpgH3YTahGoctjJ/8LZwElYDS0eursyBtv/PwXH\n\
+V+P1fBz9s4tBeAzUGt7N4EbL82oB4nna8uc2r60+TOeRGQtVSyatPBZ6755WVS8U\n\
+msd5TjlPsNhZzA30D84Ww9qEXUa+5yNZNYyOZ5bnxa/3Wusmn27SKB7Pa6SijWdl\n\
+IbToFKVSPR5Ehzr2Z1Qw24tLJkVgJUPiu/O1T5WVwgIC36+dXrdUGtVJr7YX3NgI\n\
+2I+wG6EdzBYoWSWa7vkx1YqhLF2zY1SRECGGljUhXJhlziwAQFgzLGwAQ8RMsoU=\n\
+-----END CERTIFICATE-----\n"
+
+#endif
+//CACERTS_H
diff --git a/mobicore/rootpa/Code/Common/commandhandler.c b/mobicore/rootpa/Code/Common/commandhandler.c
new file mode 100644 (file)
index 0000000..4473698
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <wrapper.h>
+#ifdef WIN32
+       #include <windows.h>
+#else
+       #include <pthread.h>
+#endif
+#include <TlCm/3.0/tlCmApi.h>
+#include <MobiCoreDriverApi.h>
+
+#include "rootpaErrors.h"
+#include "logging.h"
+#include "provisioningagent.h"
+#include "registry.h"
+#include "contentmanager.h"
+#include "provisioningengine.h"
+#include "xmlmessagehandler.h"
+#include "seclient.h"
+
+
+#define GET_VERSION_COMMAND_LENGTH 4
+#define GET_SUID_COMMAND_LENGTH 4
+
+/*
+See provisioningagent.h for description of this function.
+*/
+rootpaerror_t executeCmpCommands(int numberOfCommands, CmpMessage* commandsP, CmpMessage* responsesP, uint32_t* internalError)
+{
+    LOGD("executeCmpCommands");
+    return executeContentManagementCommands(numberOfCommands, commandsP, responsesP, internalError);
+}
+
+rootpaerror_t openSessionToCmtl()
+{
+    return openCmtlSession();
+}
+
+void closeSessionToCmtl()
+{
+    closeCmtlSession();
+}
+
+rootpaerror_t getVersion(int* tag, mcVersionInfo_t* versionP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    uint32_t internalError=0;
+    CmpMessage command;
+    CmpMessage response;
+
+    LOGD(">>getVersion");
+    memset(&command,0,sizeof(CmpMessage));
+    memset(&response,0,sizeof(CmpMessage));
+
+    command.length=GET_VERSION_COMMAND_LENGTH;
+    command.contentP=(uint8_t*)malloc(GET_VERSION_COMMAND_LENGTH);
+    if(!command.contentP)
+    {
+        return ROOTPA_ERROR_OUT_OF_MEMORY;
+    }
+
+    *((uint32_t*)command.contentP)=MC_CMP_CMD_GET_VERSION;
+    command.hdr.ignoreError=false;
+
+    ret=executeContentManagementCommands(1, &command, &response, &internalError);
+
+    if(ROOTPA_OK==ret && 0 == internalError)
+    {
+        if(response.length != sizeof(cmpRspGetVersion_t))
+        {
+            ret=ROOTPA_ERROR_INTERNAL;
+        }
+        else
+        {
+            *tag=((cmpRspGetVersion_t*)(response.contentP))->tag;
+
+            if (CMP_VERSION_TAG2 == *tag)
+            {
+                memcpy(versionP, &((cmpRspGetVersion_t*)(response.contentP))->data.versionData2.versionInfo, sizeof(*versionP));
+            }
+            else
+            {
+                LOGE("getVersion, unsupported version tag %d", *tag);
+                ret=ROOTPA_ERROR_INTERNAL;
+            }
+        }
+    }
+    else
+    {
+        LOGE("getVersion, ERROR %d %d", ret, internalError);
+    }
+    free(response.contentP);
+    free(command.contentP);
+    LOGD("<<getVersion %d", ret);
+    return ret;
+}
+
+rootpaerror_t getSuid(mcSuid_t* suidP)
+{
+    rootpaerror_t  ret=ROOTPA_OK;
+    uint32_t internalError=0;
+    CmpMessage command;
+    CmpMessage response;
+
+    LOGD(">>getSuid");
+    memset(&command,0,sizeof(CmpMessage));
+    memset(&response,0,sizeof(CmpMessage));
+
+    command.length=GET_SUID_COMMAND_LENGTH;
+    command.contentP=(uint8_t*)malloc(GET_SUID_COMMAND_LENGTH);
+    if(!command.contentP)
+    {
+        return ROOTPA_ERROR_OUT_OF_MEMORY;
+    }
+
+    *((uint32_t*)command.contentP)=MC_CMP_CMD_GET_SUID;
+    command.hdr.ignoreError=false;
+
+    ret=executeContentManagementCommands(1, &command, &response, &internalError);
+
+    if(ROOTPA_OK==ret && 0 == internalError)
+    {
+        if(response.length != sizeof(cmpRspGetSuid_t))
+        {
+            ret=ROOTPA_ERROR_INTERNAL;
+        }
+        else
+        {
+            memcpy(suidP, &((cmpRspGetSuid_t*)(response.contentP))->suid, sizeof(*suidP));
+        }
+    }
+    free(response.contentP);
+    free(command.contentP);
+    LOGD("<<getSuid %d", ret);
+    return ret;
+}
+
+rootpaerror_t  isRootContainerRegistered(bool* isRegisteredP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    ROOTCONTAINERP rootContP=NULL;
+    uint32_t rootContSize=0;
+    mcResult_t result;
+    LOGD(">>isRootContainerRegistered");
+    if(NULL==isRegisteredP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+
+    result=regReadRoot(&rootContP, &rootContSize);
+
+    if(MC_DRV_OK == result)
+    {
+        if(rootContP->cont.attribs.state != MC_CONT_STATE_UNREGISTERED)
+        {
+            *isRegisteredP=true;
+        }
+        else
+        {
+            *isRegisteredP=false;
+        }
+
+    }
+    else if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
+    {
+        *isRegisteredP=false;
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+
+    free(rootContP);
+
+    LOGD("<<isRootContainerRegistered %d", *isRegisteredP);
+    return ret;
+}
+
+rootpaerror_t  isSpContainerRegistered(mcSpid_t spid, bool* isRegisteredP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    int state;
+    LOGD(">>isSpContainerRegistered");
+
+    if(NULL==isRegisteredP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+
+    ret=getSpContainerState(spid, (mcContainerState_t*)&state);
+
+    if(ROOTPA_OK == ret)
+    {
+        if(state != MC_CONT_STATE_UNREGISTERED)
+        {
+            *isRegisteredP=true;
+        }
+        else
+        {
+            *isRegisteredP=false;
+        }
+    }
+    else if(ROOTPA_ERROR_INTERNAL_NO_CONTAINER == ret)
+    {
+        *isRegisteredP=false;
+        ret=ROOTPA_OK;
+    }
+
+    LOGD("<<isSpContainerRegistered %d", *isRegisteredP);
+    return ret;
+}
+
+
+rootpaerror_t getSpContainerState(mcSpid_t spid, mcContainerState_t* stateP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+     mcResult_t result;
+
+    LOGD(">>getSpContainerState");
+    if(NULL==stateP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+
+    result=regGetSpState(spid, stateP);
+
+    if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
+    {
+        ret=ROOTPA_ERROR_INTERNAL_NO_CONTAINER; // using this since it is changed to ROOTPA_OK and state NO_CONTAINER in the wrapper.
+    }
+    else if (result!=MC_DRV_OK)
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+
+    LOGD("<<getSpContainerState %d", *stateP);
+    return ret;
+}
+
+bool containerExists(mcUuid_t uuid)
+{
+    return (memcmp(&uuid, &MC_UUID_FREE, sizeof(mcUuid_t))!=0);
+}
+
+rootpaerror_t  getSpContainerStructure(mcSpid_t spid, SpContainerStructure* spContainerStructure)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    SPCONTAINERP spP=NULL;
+    uint32_t spContSize=0;
+    mcResult_t result;
+    int i;
+    TLTCONTAINERP tltP=NULL;
+    LOGD(">>getSpContainerStructure");
+
+    if(NULL==spContainerStructure) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    memset(spContainerStructure, 0xFF, sizeof(SpContainerStructure));
+    spContainerStructure->nbrOfTlts=0;
+
+    result=regReadSp(spid, &spP, &spContSize);
+
+    if(MC_DRV_OK == result)
+    {
+        spContainerStructure->state=spP->cont.attribs.state;
+
+        for(i=0; i<MC_CONT_CHILDREN_COUNT; i++)
+        {
+            if(containerExists(spP->cont.children[i]))
+            {
+                memcpy(&spContainerStructure->tltContainers[spContainerStructure->nbrOfTlts].uuid, &(spP->cont.children[i]), sizeof(mcUuid_t));
+
+                if(ROOTPA_OK == ret)
+                {
+                    uint32_t tltContSize=0;
+                    result=regReadTlt(&spP->cont.children[i], &tltP, &tltContSize, spid);
+                    if(MC_DRV_OK == result)
+                    {
+                        spContainerStructure->tltContainers[spContainerStructure->nbrOfTlts].state=((mcTltContCommon_t*)(((uint8_t*)tltP)+sizeof(mcSoHeader_t)))->attribs.state;
+                        spContainerStructure->nbrOfTlts++;
+                    }
+                    else
+                    {
+                        LOGE("getSpContainerStructure regReadTlt %d returned an error %d", i, result);
+                        ret=ROOTPA_ERROR_REGISTRY;
+                    }
+                    free(tltP);
+                    tltP=NULL;
+                }
+            }
+        }
+    }
+    else if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
+    {
+        ret=ROOTPA_ERROR_INTERNAL_NO_CONTAINER; // using this since it is changed to ROOTPA_OK and state NO_CONTAINER in the wrapper.
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+
+    free(spP);
+    LOGD("<<getSpContainerStructure nr: %d st: %d ret: %d",spContainerStructure->nbrOfTlts, spContainerStructure->state, ret );
+    return ret;
+}
+
+rootpaerror_t storeTA(mcSpid_t spid, const mcUuid_t* uuidP, const uint8_t* taBinP,  uint32_t taBinLength)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    mcResult_t result=0;
+    mcContainerState_t state;
+
+    result=regGetTaState(spid, uuidP, &state);
+    LOGD("storeTA, TA state %d, result 0x%x", state, result);
+    if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
+    {
+        LOGW("storeTA, not storing, since TA container is missing");
+        ret=ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+    else if (result!=MC_DRV_OK)
+    {
+        LOGW("storeTA, not storing, due to TA container read error 0x%x", result);
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+    else
+    {
+        result =regStoreTA(spid, uuidP, taBinP, taBinLength);
+
+        if(result != MC_DRV_OK)
+        {
+            LOGE("storeTA, storing TA failed, result from registry 0x%x", result);
+            ret=ROOTPA_ERROR_REGISTRY;
+        }
+    }
+
+    return ret;
+}
+
+void dummyCallback(ProvisioningState state, rootpaerror_t error, tltInfo_t* tltInfoP)
+{
+    (void) state;
+    (void) error;
+    (void) tltInfoP;
+    LOGD("dummy callback %d %d %ld", state, error, (long int) tltInfoP);
+}
+
+rootpaerror_t dummySysInfoCallback(osInfo_t* osSpecificInfoP)
+{
+    LOGD("dummy sysinfo callback %ld", (long int) osSpecificInfoP);
+    if(NULL==osSpecificInfoP) return ROOTPA_ERROR_INTERNAL;
+    memset(osSpecificInfoP, 0, sizeof(osInfo_t));
+    return ROOTPA_OK;
+}
+
+typedef struct{
+    mcSpid_t spid;
+    mcSuid_t suid;
+    CallbackFunctionP callbackP;
+    SystemInfoCallbackFunctionP sysInfoCallbackP;
+    initialRel_t      initialRel;
+       trustletInstallationData_t* tltInstallationDataP;
+} provisioningparams_t;
+#ifdef WIN32
+       void* WINAPI provisioningThreadFunction(void* paramsP)
+#else
+    void* provisioningThreadFunction(void* paramsP)
+#endif
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    LOGD(">>provisioningThreadFunction %ld", (long int)((provisioningparams_t*)paramsP)->callbackP);
+    if((ret=openCmtlSession())==ROOTPA_OK)
+    {
+        doProvisioningWithSe(((provisioningparams_t*)paramsP)->spid,
+                             ((provisioningparams_t*)paramsP)->suid,
+                             ((provisioningparams_t*)paramsP)->callbackP,
+                             ((provisioningparams_t*)paramsP)->sysInfoCallbackP,
+                             getVersion,
+                             ((provisioningparams_t*)paramsP)->initialRel,
+                                                        ((provisioningparams_t*)paramsP)->tltInstallationDataP);
+        closeCmtlSession();
+    }
+    else
+    {
+        ((provisioningparams_t*)paramsP)->callbackP(ERROR_STATE, ret, NULL);
+        LOGE("provisioningThreadFunction: was not able to open session %d", ret);
+    }
+
+    ((provisioningparams_t*)paramsP)->callbackP(PROVISIONING_STATE_THREAD_EXITING, ROOTPA_OK, NULL);
+    if(((provisioningparams_t*)paramsP)->tltInstallationDataP)
+    {
+        free((char*)((provisioningparams_t*)paramsP)->tltInstallationDataP->dataP);
+        free((char*)((provisioningparams_t*)paramsP)->tltInstallationDataP->tltPukHashP);
+        free(((provisioningparams_t*)paramsP)->tltInstallationDataP);
+    }
+    if (paramsP != NULL) {
+        free(paramsP);
+        paramsP = NULL;
+    }
+
+    LOGD("<<provisioningThreadFunction");
+#ifdef WIN32
+       ExitThread(NULL);
+#else
+    pthread_exit(NULL);
+#endif
+    return NULL; // this is required by some compilers with some settings in order to avoid errors.
+}
+
+rootpaerror_t provision(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP, trustletInstallationData_t* tltDataP, initialRel_t initialRel)
+{
+    provisioningparams_t* paramsP;
+    rootpaerror_t ret;
+#ifdef WIN32
+    HANDLE provisioningThread;
+    DWORD threadID;
+#endif
+    LOGD(">>provision %ld %ld", (long int) callbackP, (long int) dummyCallback);
+
+    if(NULL==callbackP) callbackP=dummyCallback;
+    if(NULL==systemInfoCallbackP) systemInfoCallbackP=dummySysInfoCallback;
+
+    paramsP=(provisioningparams_t*)malloc(sizeof(provisioningparams_t));
+    if(!paramsP) return ROOTPA_ERROR_OUT_OF_MEMORY;
+
+    memset(paramsP,0,sizeof(provisioningparams_t)); // initialize in order to satisfy valgrind
+
+    paramsP->callbackP=callbackP;
+    paramsP->sysInfoCallbackP=systemInfoCallbackP;
+    paramsP->spid=spid;
+    if(tltDataP)
+    {
+               // Coverity complains that paramsP allocated here is not freed. It is done in "provisioningThreadFunction"
+        paramsP->tltInstallationDataP=(trustletInstallationData_t*)malloc(sizeof(trustletInstallationData_t));
+        if(!paramsP->tltInstallationDataP)
+        {
+            free(paramsP);
+            paramsP = NULL;
+            return ROOTPA_ERROR_OUT_OF_MEMORY;
+        }
+
+    // copy the whole struct
+
+        memset(paramsP->tltInstallationDataP,0,sizeof(trustletInstallationData_t)); // initialize in order to satisfy valgrind
+        memcpy(paramsP->tltInstallationDataP, tltDataP, sizeof(trustletInstallationData_t));
+
+    // malloc and copy data from/to the pointers
+
+        paramsP->tltInstallationDataP->dataP=(const uint8_t *)malloc(tltDataP->dataLength);
+        if(!paramsP->tltInstallationDataP->dataP)
+        {
+            free(paramsP->tltInstallationDataP);
+            free(paramsP);
+            paramsP = NULL;
+            return ROOTPA_ERROR_OUT_OF_MEMORY;
+        }
+        memset((char*)paramsP->tltInstallationDataP->dataP,0,tltDataP->dataLength); // initialize in order to satisfy valgrind
+        memcpy((char*)paramsP->tltInstallationDataP->dataP, tltDataP->dataP, tltDataP->dataLength);
+
+        paramsP->tltInstallationDataP->tltPukHashP=(const uint8_t *)malloc(tltDataP->tltPukHashLength);
+        if(!paramsP->tltInstallationDataP->tltPukHashP)
+        {
+            free((void*) paramsP->tltInstallationDataP->dataP);
+            free((void*) paramsP->tltInstallationDataP);
+            free(paramsP);
+            paramsP = NULL;
+            return ROOTPA_ERROR_OUT_OF_MEMORY;
+        }
+        memset((char*)paramsP->tltInstallationDataP->tltPukHashP,0,tltDataP->tltPukHashLength); // initialize in order to satisfy valgrind
+        memcpy((char*)paramsP->tltInstallationDataP->tltPukHashP, tltDataP->tltPukHashP, tltDataP->tltPukHashLength);
+    }
+    else
+    {
+        paramsP->tltInstallationDataP=NULL;
+    }
+
+       paramsP->initialRel = initialRel;
+
+    ret=ROOTPA_OK;
+    ret=getSuid(&paramsP->suid);
+
+    if(ROOTPA_OK==ret)
+    {
+
+#ifdef WIN32
+        provisioningThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)provisioningThreadFunction, (void*) paramsP, 0, &threadID);
+
+        if (provisioningThread == NULL)
+        {
+            LOGE("unable to create thread");
+            ret=ROOTPA_ERROR_INTERNAL;
+        }
+#else
+        pthread_t provisioningThread;
+        pthread_attr_t attributes;
+        int r=0;
+        r=pthread_attr_init(&attributes);
+        if(r)
+        {
+            LOGE("can not init thread attributes %d",r);
+            ret=ROOTPA_ERROR_INTERNAL;
+        }
+        else
+        {
+            r=pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
+            if(r)
+            {
+                LOGE("unable to set detached state, trying with defaults %d",r);
+            }
+
+            r=pthread_create(&provisioningThread, &attributes, provisioningThreadFunction, (void*) paramsP);   
+            if(r)
+            {
+                LOGE("unable to create thread %d",r);
+                free(paramsP);
+                paramsP = NULL;
+                ret=ROOTPA_ERROR_INTERNAL;
+            }
+            pthread_attr_destroy(&attributes);
+        }
+#endif
+    }
+    else
+    {
+        LOGE("provisioning can not get suid: %d",ret );
+    }
+    LOGD("<<provision ret: %d",ret );
+
+    return ret;
+}
+
+rootpaerror_t doProvisioning(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP)
+{
+    LOGD("doProvisioning");
+    return provision(spid, callbackP, systemInfoCallbackP, NULL, initialRel_POST);
+}
+
+rootpaerror_t installTrustlet(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP, trustletInstallationData_t* tltDataP)
+{
+    if(NULL == tltDataP || NULL == tltDataP->dataP || 0 == tltDataP->dataLength||
+      (REQUEST_DATA_TLT != tltDataP->dataType &&  REQUEST_DATA_KEY != tltDataP->dataType)) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    LOGD("installTrustlet");
+    return provision(spid, callbackP, systemInfoCallbackP, tltDataP, initialRel_POST);
+}
+
+rootpaerror_t setSeAddress(const char* addrP, uint32_t length)
+{
+    return setInitialAddress(addrP, length);
+}
+
+void setPaths(const char* storageDirP, const char* certDirP)
+{
+    setXsdPaths(storageDirP);
+    setCertPath(storageDirP, certDirP);
+}
+
+rootpaerror_t unregisterRootContainer(CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP)
+{
+       mcSpid_t spid;
+    LOGD("unregisterRootContainer");
+       memset(&spid, 0x0, sizeof(mcSpid_t));
+       return provision(spid, callbackP, systemInfoCallbackP, NULL, initialRel_DELETE);
+}
+
+
diff --git a/mobicore/rootpa/Code/Common/contentmanager.c b/mobicore/rootpa/Code/Common/contentmanager.c
new file mode 100644 (file)
index 0000000..6a2ffeb
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <MobiCoreDriverApi.h>
+
+#include "tools.h"
+#include "logging.h"
+#include "pacmp3.h"
+#include "pacmtl.h"
+#include "registry.h"
+#include "trustletchannel.h"
+#include "contentmanager.h"
+
+static CMTHANDLE handle_=NULL;
+
+void closeCmtlSession()
+{
+    tltChannelClose(handle_);
+    handle_=NULL;
+}
+
+rootpaerror_t openCmtlSession()
+{
+    mcResult_t error=0;
+    rootpaerror_t ret=ROOTPA_OK;
+
+    if(handle_)
+    {
+        closeCmtlSession();
+    }
+
+    handle_=tltChannelOpen(sizeOfCmp(), &error);
+    if(NULL==handle_)
+    {
+        if(MC_DRV_ERR_NO_FREE_MEMORY==error)
+        {
+            ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+        }
+        else
+        {
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+        }
+    }
+    return ret;
+}
+
+rootpaerror_t executeOneCmpCommand(CMTHANDLE handle, CmpMessage* commandP, CmpMessage* responseP);
+
+rootpaerror_t executeContentManagementCommands(int numberOfCommands, CmpMessage* commandsP, CmpMessage* responsesP, uint32_t* internalError)
+{
+    rootpaerror_t ret=ROOTPA_OK ;
+    rootpaerror_t iRet=ROOTPA_OK ;
+    bool selfOpened=false;
+    CMTHANDLE handle;
+    LOGD(">>executeContentManagementCommands");
+
+    *internalError=0;
+
+    if(handle_==NULL)
+    {
+        // doProvisioining opens session earlier. Lock opens and closes session when called by client
+        // this is for commands that do not require the client to call the lock.
+
+        ret=openCmtlSession();
+        selfOpened=true;
+    }
+    handle=handle_;
+
+    if (handle)
+    {
+        int i;
+        for(i=0; i<numberOfCommands;i++)
+        {
+            responsesP[i].hdr.id=commandsP[i].hdr.id; // match the id;
+            responsesP[i].hdr.ignoreError=commandsP[i].hdr.ignoreError;
+
+            if(commandsP[i].length>0)
+            {
+                if(((iRet=executeOneCmpCommand(handle, &commandsP[i], &responsesP[i]))!=ROOTPA_OK))
+                {
+                    // returning actual error in case of the command failed
+                    ret=iRet;
+                    if(ROOTPA_OK==responsesP[i].hdr.ret)
+                    {
+                        responsesP[i].hdr.ret=ret;
+                    }
+
+                    if(commandsP[i].hdr.ignoreError==false)
+                    {
+                        LOGE("executeContentManagementCommands, ignoreError==false, returning %d", ret);
+                        return ret;
+                    }
+                }
+            }
+            else
+            {
+                LOGE("executeContentManagementCommands, empty command");
+            }
+        }
+
+        if(ret!=ROOTPA_OK)
+        {
+            *internalError = handle->lasterror;
+        }
+    }
+    else
+    {
+        LOGE("no handle %d", *internalError);
+        if(MC_DRV_ERR_NO_FREE_MEMORY == *internalError)
+        {
+            ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+        }
+        else
+        {
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+        }
+    }
+
+    if(selfOpened)
+    {
+        closeCmtlSession();
+    }
+
+    LOGD("<<executeContentManagementCommands %d", ret);
+    return ret;
+}
+
+/**
+*/
+rootpaerror_t executeOneCmpCommand(CMTHANDLE handle, CmpMessage* commandP, CmpMessage* responseP)
+{
+    mcResult_t mcRet;
+    cmpCommandId_t commandId;
+    rootpaerror_t ret;
+    uint32_t neededBytes;
+    LOGD(">>executeOneCmpCommand");
+    if (unlikely( bad_write_ptr(handle,sizeof(CMTSTRUCT))))
+    {
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    if(unlikely(commandP->contentP==NULL || commandP->length< sizeof(cmpCommandId_t)))
+    {
+        return ROOTPA_ERROR_INTERNAL;
+    }
+
+    mcRet=MC_DRV_OK;
+    commandId=getCmpCommandId(commandP->contentP);
+
+    handle->mappedSize=getTotalMappedBufferSize(commandP);
+    if(0==handle->mappedSize)
+    {
+        LOGE("<<executeOneCmpCommand, command %d not supported", commandId);
+        return ROOTPA_COMMAND_NOT_SUPPORTED;
+    }
+
+    ret=ROOTPA_OK;
+    while(true)
+    {
+        handle->mappedP=(uint8_t*)malloc((size_t) handle->mappedSize);
+        if(NULL==handle->mappedP)
+        {
+            ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+            break;
+        }
+        memset(handle->mappedP, 0,handle->mappedSize);
+        mcRet=mcMap(&handle->session, handle->mappedP, handle->mappedSize, &handle->mapInfo);
+        if(mcRet!=MC_DRV_OK)
+        {
+            LOGE("executeOneCmpCommand not able to map memory %d", mcRet);
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+            commandP->hdr.intRet=mcRet;
+            responseP->hdr.intRet=mcRet;
+            break;
+        }
+
+        if((ret = prepareCommand(commandId, commandP, handle, responseP))!=ROOTPA_OK)
+        {
+            LOGE("prepareCommand failed %d", ret);
+            break;
+        }
+
+        if (unlikely( !tltChannelTransmit(handle, NOTIFICATION_WAIT_TIMEOUT_MS)))
+        {
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+            commandP->hdr.intRet=handle->lasterror;
+            responseP->hdr.intRet=handle->lasterror;
+            break;
+        }
+
+        neededBytes=getNeededBytesFromResponse(handle->wsmP);
+
+        if(0==neededBytes)
+        {
+            break;
+        }
+
+        if((uint32_t)-1==neededBytes)
+        {
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+            break;
+        }
+
+        if(neededBytes <= handle->mappedSize)
+        {
+            LOGE("executeOneCmpCommand, there is something wrong. CMTL is requesting smaller buffer than we originally had. Command: %d, original %d requested %d",
+                commandId, handle->mappedSize, neededBytes);
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+            break;
+        }
+
+        // this is Info level LOGI on purpose
+        LOGI("executeOneCmpCommand, updating RootPA recommended (%d bytes was not enough for %d response, allocating %d bytes and retrying)", handle->mappedSize, commandId, neededBytes);
+        mcRet=mcUnmap(&handle->session, handle->mappedP, &handle->mapInfo);
+        if(mcRet!=MC_DRV_OK)
+        {
+            LOGE("executeOneCmpCommand not able to free mapped memory %d", mcRet);
+            ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+            commandP->hdr.intRet=mcRet;
+            responseP->hdr.intRet=mcRet;
+            break;
+        }
+
+        free(handle->mappedP);
+        memset(&handle->mapInfo, 0 , sizeof(handle->mapInfo));
+        handle->mappedSize=neededBytes;
+    }
+
+    if(ROOTPA_OK==ret)
+    {
+        ret=handleResponse(commandId, responseP, handle);
+    }
+    else
+    {
+        responseP->hdr.ret=ret;
+    }
+    LOGD("cleaning up mapped memory %ld",(long int) handle->mappedP);
+    mcRet=mcUnmap(&handle->session, handle->mappedP, &handle->mapInfo);
+    if(mcRet!=MC_DRV_OK)
+    {
+        LOGE("executeOneCmpCommand not able to free mapped memory %d", mcRet);
+        ret=ROOTPA_ERROR_MOBICORE_CONNECTION;
+    }
+    LOGD("freeing mapped memory %ld", (long int) handle->mappedP);
+    free(handle->mappedP);
+    if(commandP->hdr.ret==ROOTPA_OK) commandP->hdr.ret=ret;
+    if(responseP->hdr.ret==ROOTPA_OK) responseP->hdr.ret=ret;
+    LOGD("<<executeOneCmpCommand %d %d",commandId, ret);
+    return ret;
+}
+
+rootpaerror_t uploadSo(uint8_t* containerDataP, uint32_t containerLength, uint32_t* regRetP)
+{
+    *regRetP = regWriteAuthToken((AUTHTOKENCONTAINERP) containerDataP, containerLength);
+    if( *regRetP != MC_DRV_OK)
+    {
+        LOGE("uploadSo regWriteAuthToken failed %d", *regRetP);
+        return ROOTPA_ERROR_REGISTRY;
+    }
+    return ROOTPA_OK;
+}
diff --git a/mobicore/rootpa/Code/Common/contentmanager.h b/mobicore/rootpa/Code/Common/contentmanager.h
new file mode 100644 (file)
index 0000000..165e8f1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CONTENTMANAGER_H
+#define CONTENTMANAGER_H
+
+#include "rootpa.h"
+
+#define NOTIFICATION_WAIT_TIMEOUT_MS 3000 // wait for 3 seconds max
+
+rootpaerror_t executeContentManagementCommands(int numberOfCommands, CmpMessage* commandsP, CmpMessage* responsesP, uint32_t* internalError);
+rootpaerror_t uploadSo(uint8_t* containerDataP, uint32_t containerLength, uint32_t* regRetP);
+rootpaerror_t openCmtlSession();
+void closeCmtlSession();
+
+
+#endif // CONTENTMANAGER_H
diff --git a/mobicore/rootpa/Code/Common/enrollmentservicexmlschema.h b/mobicore/rootpa/Code/Common/enrollmentservicexmlschema.h
new file mode 100644 (file)
index 0000000..4f326b4
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ENROLLMENTSERVICEXMLSCHEMA_H
+#define ENROLLMENTSERVICEXMLSCHEMA_H
+
+#define ENROLLMENT_SERVICE_XSD_NAME  "EnrollmentService.xsd"
+#define PLATFORM_TYPES_XSD_NAME      "MCPlatformTypes.xsd"
+
+#define ENROLLMENT_SERVICE_XSD "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
+<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \
+       targetNamespace=\"http://www.mcore.gi-de.com/2012/04/schema/EnrollmentService\" \
+       xmlns:mces=\"http://www.mcore.gi-de.com/2012/04/schema/EnrollmentService\" \
+       xmlns:mcpt=\"http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes\" \
+       elementFormDefault=\"qualified\"> \
+ \
+       <xsd:import namespace=\"http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes\" \
+               schemaLocation=\"MCPlatformTypes.xsd\" /> \
+ \
+       <xsd:simpleType name=\"CommandType\"> \
+               <xsd:restriction base=\"xsd:string\"> \
+                       <xsd:enumeration value=\"CMP\" /> \
+                       <xsd:enumeration value=\"SO_UPLOAD\" /> \
+                       <xsd:enumeration value=\"TLT_UPLOAD\" /> \
+               </xsd:restriction> \
+       </xsd:simpleType> \
+ \
+       <xsd:complexType name=\"Command\"> \
+               <xsd:sequence> \
+                       <xsd:element name=\"commandValue\" type=\"xsd:base64Binary\"/> \
+               </xsd:sequence> \
+               <xsd:attribute name=\"id\" type=\"xsd:int\" use=\"required\" /> \
+               <xsd:attribute name=\"type\" type=\"mces:CommandType\" use=\"required\" /> \
+               <xsd:attribute name=\"ignoreError\" type=\"xsd:boolean\" \
+                       default=\"false\" /> \
+       </xsd:complexType> \
+ \
+       <xsd:simpleType name=\"CommandExecutionErrorCode\"> \
+               <xsd:restriction base=\"xsd:string\"> \
+                       <xsd:enumeration value=\"COMMAND_NOT_SUPPORTED_ERROR\" /> \
+                       <xsd:enumeration value=\"INTERNAL_ERROR\" /> \
+                       <xsd:enumeration value=\"BUSY_ERROR\" /> \
+                       <xsd:enumeration value=\"REGISTRY_ERROR\" /> \
+            <xsd:enumeration value=\"REGISTRY_OBJECT_NOT_AVAILABLE\" /> \
+                       <xsd:enumeration value=\"MOBICORE_CONNECTION_ERROR\" /> \
+                       <xsd:enumeration value=\"OUT_OF_MEMORY_ERROR\" /> \
+                       <xsd:enumeration value=\"XML_ERROR\" /> \
+        </xsd:restriction> \
+       </xsd:simpleType> \
+ \
+       <xsd:complexType name=\"CommandExecutionError\"> \
+               <xsd:attribute name=\"errorCode\" type=\"mces:CommandExecutionErrorCode\" \
+                       use=\"required\" /> \
+               <xsd:attribute name=\"errorDetail\" type=\"xsd:int\" /> \
+       </xsd:complexType> \
+ \
+       <xsd:complexType name=\"CommandResult\"> \
+               <xsd:sequence> \
+                       <xsd:choice> \
+                               <xsd:element name=\"resultValue\" type=\"xsd:base64Binary\" /> \
+                               <xsd:element name=\"resultError\" type=\"mces:CommandExecutionError\" /> \
+                       </xsd:choice> \
+               </xsd:sequence> \
+               <xsd:attribute name=\"id\" type=\"xsd:int\" use=\"required\" /> \
+       </xsd:complexType> \
+ \
+       <xsd:complexType name=\"TrustletEncryptionKey\"> \
+               <xsd:simpleContent> \
+                       <xsd:extension base=\"xsd:base64Binary\"> \
+                               <xsd:attribute name=\"minTltVersion\" type=\"mcpt:Version\" use=\"required\" /> \
+                               <xsd:attribute name=\"tltPukHash\" type=\"xsd:base64Binary\" use=\"required\" /> \
+                       </xsd:extension> \
+               </xsd:simpleContent> \
+       </xsd:complexType> \
+\
+       <xsd:simpleType name=\"TrustletMemoryType\"> \
+               <xsd:restriction base=\"xsd:int\"> \
+                       <xsd:enumeration value=\"0\"> \
+                               <xsd:annotation> \
+                                       <xsd:documentation> \
+       If enough space is available in the internal \
+       memory the trustlet will be loaded into the internal memory, else into the external \
+                                       </xsd:documentation> \
+                               </xsd:annotation> \
+                       </xsd:enumeration> \
+                       <xsd:enumeration value=\"1\"> \
+                               <xsd:annotation> \
+                                       <xsd:documentation> \
+                                               Use internal memory only. \
+                                       </xsd:documentation> \
+                               </xsd:annotation> \
+                       </xsd:enumeration> \
+                       <xsd:enumeration value=\"2\"> \
+                               <xsd:annotation> \
+                                       <xsd:documentation> \
+                                               Use external memory only. \
+                                       </xsd:documentation> \
+                               </xsd:annotation> \
+                       </xsd:enumeration> \
+               </xsd:restriction> \
+       </xsd:simpleType> \
+ \
+       <xsd:complexType name=\"TrustletAXF\"> \
+               <xsd:simpleContent> \
+                       <xsd:extension base=\"xsd:base64Binary\"> \
+                               <xsd:attribute name=\"minTltVersion\" type=\"mcpt:Version\" \
+                                       use=\"required\" /> \
+                               <xsd:attribute name=\"tltPukHash\" type=\"xsd:base64Binary\" \
+                                       use=\"required\" /> \
+                               <xsd:attribute name=\"memoryType\" type=\"mces:TrustletMemoryType\" \
+                                       default=\"2\" /> \
+                               <xsd:attribute name=\"numberOfInstances\" type=\"xsd:int\" \
+                                       default=\"1\" /> \
+                               <xsd:attribute name=\"flags\" type=\"xsd:int\" default=\"0\" /> \
+                       </xsd:extension> \
+               </xsd:simpleContent> \
+       </xsd:complexType> \
+\
+       <xsd:complexType name=\"TrustletInstallationRequest\"> \
+               <xsd:annotation> \
+                       <xsd:documentation> \
+                               This element defines data required to be able to \
+                               install a trustlet over PA. The schema below supports \
+                               following \
+                               combinations: \
+                               1. encrypted trustlet binary key (enables the \
+                               installation of the tltBin using the static tlt \
+                               encryption schema. \
+                               Trustlet remains on the device. \
+                               Just the key gets decrypted and \
+                               pushed back to the \
+                               device using corresponding cmp commands) \
+                               2. \
+                               encrypted tltBin (enables the installation \
+                               of the tltBin using the \
+                               dynamic tlt encryption scheme. \
+                               Trustlet get reencrypted by the SE \
+                               with a new key \
+                               generated by the SE during the execution of the \
+                               workflow and pushed back to \
+                               the device). \
+                               In both cases the key for \
+                               either the encryption of \
+                               the key or the tltBin must be known to the \
+                               SE \
+                       </xsd:documentation> \
+               </xsd:annotation> \
+               <xsd:sequence> \
+                       <xsd:choice> \
+                               <xsd:element name=\"trustletAxf\" type=\"mces:TrustletAXF\" /> \
+                               <xsd:element name=\"trustletEncryptionKey\" type=\"mces:TrustletEncryptionKey\" /> \
+                       </xsd:choice> \
+               </xsd:sequence> \
+       </xsd:complexType> \
+\
+       <xsd:complexType name=\"CommandResultList\"> \
+               <xsd:sequence> \
+                       <xsd:element name=\"commandResult\" type=\"mces:CommandResult\" maxOccurs=\"unbounded\" /> \
+               </xsd:sequence> \
+       </xsd:complexType> \
+ \
+       <xsd:element name=\"ContentManagementResponse\"> \
+               <xsd:complexType> \
+                       <xsd:annotation> \
+                               <xsd:documentation> \
+                                       This element is a top level element sent by PA to \
+                                       the SE. It contains either a SystemInformation of \
+                                       the device the PA \
+                                       is running on, a responses for \
+                                       previously received \
+                                       ContentManagementRequest, or \
+                                       data about the trustlet to be \
+                                       installed. \
+                               </xsd:documentation> \
+                       </xsd:annotation> \
+                       <xsd:choice> \
+                               <xsd:element name=\"systemInformation\" type=\"mcpt:SystemInformation\" /> \
+                               <xsd:element name=\"tltInstallationRequest\" type=\"mces:TrustletInstallationRequest\" /> \
+                               <xsd:element name=\"commandResultList\" type=\"mces:CommandResultList\"/> \
+                       </xsd:choice> \
+               </xsd:complexType> \
+       </xsd:element> \
+ \
+       <xsd:complexType name=\"CommandList\"> \
+               <xsd:sequence> \
+                       <xsd:element name=\"command\" type=\"mces:Command\" \
+                               minOccurs=\"1\" maxOccurs=\"unbounded\" /> \
+               </xsd:sequence> \
+       </xsd:complexType> \
+ \
+       <xsd:element name=\"ContentManagementRequest\"> \
+               <xsd:complexType> \
+                       <xsd:annotation> \
+                               <xsd:documentation> \
+                                       This element is a top level element sent from SE \
+                                       to PA as a result of previously received HTTP message. \
+                               </xsd:documentation> \
+                       </xsd:annotation> \
+                       <xsd:sequence> \
+                               <xsd:element name=\"commands\" type=\"mces:CommandList\"/> \
+                       </xsd:sequence> \
+               </xsd:complexType> \
+       </xsd:element> \
+</xsd:schema>"
+
+#define PLATFORM_TYPES_XSD "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \
+<xsd:schema \
+       xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"  \
+       xmlns:mcpt=\"http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes\" \
+       targetNamespace=\"http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes\" \
+       elementFormDefault=\"qualified\"> \
+\
+       <xsd:simpleType name=\"Version\"> \
+               <xsd:annotation> \
+                       <xsd:documentation> \
+                               Version of an object withing MobiCore eco system \
+                       </xsd:documentation> \
+               </xsd:annotation> \
+               <xsd:restriction base=\"xsd:int\" /> \
+       </xsd:simpleType> \
+\
+       <xsd:complexType name=\"McVersion\"> \
+               <xsd:annotation> \
+                       <xsd:documentation> \
+                               This element contains version data of MobiCore \
+                               components \
+                       </xsd:documentation> \
+               </xsd:annotation> \
+               <xsd:attribute name=\"productId\" type=\"xsd:string\" use=\"required\" /> \
+               <xsd:attribute name=\"versionMci\" type=\"mcpt:Version\" use=\"required\" /> \
+               <xsd:attribute name=\"versionSo\" type=\"mcpt:Version\" use=\"required\" /> \
+               <xsd:attribute name=\"versionMclf\" type=\"mcpt:Version\" use=\"required\" /> \
+               <xsd:attribute name=\"versionContainer\" type=\"mcpt:Version\" \
+                       use=\"required\" /> \
+               <xsd:attribute name=\"versionMcConfig\" type=\"mcpt:Version\" \
+                       use=\"required\" /> \
+               <xsd:attribute name=\"versionTlApi\" type=\"mcpt:Version\" use=\"required\" /> \
+               <xsd:attribute name=\"versionDrApi\" type=\"mcpt:Version\" use=\"required\" /> \
+               <xsd:attribute name=\"versionCmp\" type=\"mcpt:Version\" use=\"required\" /> \
+       </xsd:complexType> \
+ \
+       <xsd:complexType name=\"SystemInformation\"> \
+               <xsd:annotation> \
+                       <xsd:documentation> \
+                               This element contains system information of a \
+                               device \
+                       </xsd:documentation> \
+               </xsd:annotation> \
+               <xsd:sequence> \
+                       <xsd:element name=\"mcVersion\" type=\"mcpt:McVersion\" /> \
+               </xsd:sequence> \
+               <xsd:attribute name=\"imei\" type=\"xsd:string\" use=\"optional\" /> \
+               <xsd:attribute name=\"mno\" type=\"xsd:string\" use=\"optional\" /> \
+               <xsd:attribute name=\"brand\" type=\"xsd:string\" use=\"optional\" /> \
+               <xsd:attribute name=\"manufacturer\" type=\"xsd:string\" use=\"optional\" /> \
+               <xsd:attribute name=\"hardware\" type=\"xsd:string\" use=\"optional\" /> \
+               <xsd:attribute name=\"model\" type=\"xsd:string\" use=\"optional\" /> \
+        <xsd:attribute name=\"sip\" type=\"xsd:string\" use=\"optional\" /> \
+               <xsd:attribute name=\"version\" type=\"xsd:string\" use=\"optional\" /> \
+       </xsd:complexType> \
+</xsd:schema>"
+
+
+#endif //ENROLLMENTSERVICEXMLSCHEMA_H
diff --git a/mobicore/rootpa/Code/Common/include/logging.h b/mobicore/rootpa/Code/Common/include/logging.h
new file mode 100644 (file)
index 0000000..034bfd7
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#ifndef LOG_TAG
+#define LOG_TAG "RootPA-C"
+#endif
+
+#ifdef ANDROID
+    #include <android/log.h>
+    #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+    #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+    #ifdef __DEBUG
+        #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+    #else
+        #define LOGD(scite ...)
+    #endif
+#else
+#ifdef WIN32
+    #include <stdio.h>
+       #include <windows.h>
+    void MyOutputFunction(const char *str, ...);
+       void OutputToLogfile(char buf[]);
+
+
+#ifdef __cplusplus
+
+       extern "C" void MyOutputFunctionC(const char *str, ...);
+
+       #define LOGE(fmt, ...)  MyOutputFunction(fmt "\n", ##__VA_ARGS__)
+    #define LOGW(fmt, ...)  MyOutputFunction(fmt "\n", ##__VA_ARGS__)
+    #define LOGI(fmt, ...)  MyOutputFunction(fmt "\n", ##__VA_ARGS__)
+
+    #ifdef __DEBUG
+        #define LOGD(fmt, ...)  MyOutputFunction(fmt "\n", ##__VA_ARGS__)
+    #else
+        #define LOGD(fmt, ...)
+    #endif
+#else
+
+       #define LOGE(fmt, ...)  MyOutputFunctionC(fmt "\n", ##__VA_ARGS__)
+    #define LOGW(fmt, ...)  MyOutputFunctionC(fmt "\n", ##__VA_ARGS__)
+    #define LOGI(fmt, ...)  MyOutputFunctionC(fmt "\n", ##__VA_ARGS__)
+
+    #ifdef __DEBUG
+        #define LOGD(fmt, ...)  MyOutputFunctionC(fmt "\n", ##__VA_ARGS__)
+    #else
+        #define LOGD(fmt, ...)
+    #endif
+
+#endif
+
+#else
+#ifdef TIZEN
+    #include <stdio.h>
+#endif /*Tizen*/
+    #define LOGE(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)
+    #define LOGW(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)
+    #define LOGI(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)
+    #ifdef __DEBUG
+           #define LOGD(fmt, ...)  printf(fmt "\n", ##__VA_ARGS__)
+    #else
+#ifdef TIZEN
+        #define LOGD(fmt, ...)  do { } while(0)
+#else
+        #define LOGD(fmt, ...)
+#endif/*Tizen*/
+    #endif
+#endif // WIN32
+#endif // ANDROID
+#endif // LOGGING_H
diff --git a/mobicore/rootpa/Code/Common/include/provisioningagent.h b/mobicore/rootpa/Code/Common/include/provisioningagent.h
new file mode 100644 (file)
index 0000000..bf47bcb
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PROVISIONINGAGENT_H
+#define PROVISIONINGAGENT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <wrapper.h>
+#include <TlCm/3.0/cmp.h>
+#include <mcVersionInfo.h>
+
+#include "rootpaErrors.h"
+#include "rootpa.h"
+
+/**
+since the CMP commands that require authentication need to be executed during
+the same session the actual authentication, the client needs to handle opening
+and closing the session before
+*/
+rootpaerror_t openSessionToCmtl();
+void closeSessionToCmtl();
+
+/**
+Executes all given content management protocol commands in the order they are given and returns response to all of them.
+
+The calling operating system specific part has to take care that no other calls are executed before
+executeCmpCommands has exited.
+
+@param numberOfCommands number of commands given in this request. The array of
+                        commands and responses must be allocated with the same
+                        number of CmpMessage structs.
+@param commandsP an array of commands to be executed. The commands will be executed in the given order.
+@param responsesP an array of responses that have to be empty when the call is made.
+                  Memory for the responses need to be freed (with free) by the caller,
+                  after the call.
+@param internalError if returning an error, rootPA copies here error code it received from Cmtl or MC.
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful.
+        Note that when ROOTPA_ERROR_COMMAND_EXECUTION is returned, execution of some of the commands
+        may have been successful. The status of individual commands can be checked from the actual
+        content of the individual response.
+*/
+rootpaerror_t executeCmpCommands(int numberOfCommands, CmpMessage* commandsP, CmpMessage* responsesP, uint32_t* internalError);
+
+
+/**
+Obtains and returns version information from CMTL
+
+The calling operating system specific part has to take care that no other calls are executed before
+the command has exited.
+
+@param tag version of the version. See mcVersionInfo_t for more information.
+@param versionP version information. In case version info tag is 1, the version
+               is written in the first four bytes of mcVersionInfo_t.productId
+
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful.
+
+*/
+rootpaerror_t getVersion(int* tag, mcVersionInfo_t* versionP);
+
+/**
+Returns SUID
+
+The calling operating system specific part has to take care that no other calls are executed before
+the command has exited.
+
+@param suidP pointer to the emory area where the suid is copied to
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful.
+
+*/
+rootpaerror_t getSuid(mcSuid_t* suidP);
+
+/**
+
+@param isRegisteredP writes here true if the container is registered, false otherwise
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful.
+
+*/
+rootpaerror_t isRootContainerRegistered(bool* isRegisteredP);
+
+/**
+
+
+@param spid service provider id
+@param isRegisteredP writes here true if the container is registered, false otherwise
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful.
+
+*/
+rootpaerror_t isSpContainerRegistered(mcSpid_t spid, bool* isRegisteredP);
+
+/**
+
+
+@param spid service provider id
+@param stateP writes here the state of the container
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful,
+        ROOTPA_ERROR_INTERNAL_NO_CONTAINER if the container does not exist.
+
+*/
+rootpaerror_t getSpContainerState(mcSpid_t spid, mcContainerState_t* stateP);
+
+
+/**
+
+@param spid service provider id
+@param spContainerStructureP writes here the structure of the container. The structure must be allocated before the call.
+@return one of the return values defined in rootpaErrors.h ROOTPA_OK in case the call is successful,
+        ROOTPA_ERROR_INTERNAL_NO_CONTAINER if the container does not exist.
+
+*/
+rootpaerror_t getSpContainerStructure(mcSpid_t spid, SpContainerStructure* spContainerStructureP);
+
+/**
+Creates a thread and returns, the thread contacts SE and executes the commands received from SE.
+
+The state of the execution is informed in the calls to callback. The last callback, just before
+the thread exits contains always state PROVISIONING_STATE_THREAD_EXITING.
+
+The calling operating system specific part has to take care that no other calls are executed before
+doProvisioning and the actual provisioining thread have exited.
+
+@param spid service provider id
+
+@param callbackP callback function that handles information delivery to operating system specific client.
+       This is called at different states of provisioining (see type ProvisioningState to find out more
+       about the states). Since doProvisioining executes it's own thread the callback function has to be
+       thread safe.
+
+@param systemInfoCallbackP pointer to a function that can provide RootPA system information
+       that is only available in the operting system specific part. Since doProvisioining executes it's own thread the
+       callback function has to be thread safe.
+
+
+@return ROOTPA_OK on success and and error code if thread creation fails.  The results of actual execution of
+the provisioining are returned in the callback functions.
+*/
+rootpaerror_t doProvisioning(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP);
+
+/**
+Creates a thread and returns, the thread contacts SE and executes the commands received from SE.
+This is similar to do provisioning but takes in information on trustlet to be installed and asks SE
+to "install the trustlet". This is used for testing and developer trustlet installation.
+
+The state of the execution is informed in the calls to callback. The last callback, just before
+the thread exits contains always state PROVISIONING_STATE_THREAD_EXITING.
+
+The calling operating system specific part has to take care that no other calls are executed before
+doProvisioning and the actual provisioining thread have exited.
+
+@param spid service provider id
+
+@param callbackP callback function that handles information delivery to operating system specific client.
+       This is called at different states of provisioining (see type ProvisioningState to find out more
+       about the states). Since doProvisioining executes it's own thread the callback function has to be
+       thread safe.
+
+@param systemInfoCallbackP pointer to a function that can provide RootPA system information
+       that is only available in the operting system specific part. Since doProvisioining executes it's own thread the
+       callback function has to be thread safe.
+
+@param dataP pointer to the data needed in trutlet installation
+
+@return ROOTPA_OK on success and and error code if thread creation fails. ROOTPA_ERROR_ILLEGAL_ARGUMENT if dataP is NULL.
+The results of actual execution of the provisioining are returned in the callback functions.
+*/
+rootpaerror_t installTrustlet(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP, trustletInstallationData_t* dataP);
+
+
+/**
+This is helper function for unregistering root container.
+
+@param callbackP callback function that handles information delivery to operating system specific client.
+       This is called at different states of provisioining (see type ProvisioningState to find out more
+       about the states). Since doProvisioining executes it's own thread the callback function has to be
+       thread safe.
+
+@param systemInfoCallbackP pointer to a function that can provide RootPA system information
+       that is only available in the operating system specific part. Since doProvisioining executes it's own thread the
+       callback function has to be thread safe.
+
+@return ROOTPA_OK is unregistering root container succeeds, an error code otherwise
+*/
+rootpaerror_t unregisterRootContainer(CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP);
+
+
+/**
+Store's the GP TA binary to the registry. The corresponding TA container has to exists and contain correct information for decrypting the TA.
+
+@param spid service provider ID
+@param uuidP pointer to the UUID of the TA binary. This is the UUID that all t-base TA's have, NOT the UUID specific to GP TA's
+@param taBinP pointer to the actual TA binary
+@param taBinLength size of the actual TA binary
+
+@return ROOTPA_OK is unregistering root container succeeds, an error code otherwise
+*/
+rootpaerror_t storeTA(mcSpid_t spid, const mcUuid_t* uuidP, const uint8_t* taBinP, uint32_t taBinLength);
+
+/**
+This is helper function for the platform dependent part to inform the platform independent part
+on the file storage location
+
+@param storageDirP NULL terminated char array containing the path to the storage location
+@param certDirP NULL terminated char array containing the path to the location where ssl should look for ce certificates.
+  note that since the certificates are also hardcoded, it is possible that this path is not used, however it must be given anyway
+*/
+
+void setPaths(const char* storageDirP, const char* certDirP);
+
+/**
+This is helper function for setting SE address.
+
+@param addrP pointer to the address, it can but does not need to be null terminated. The address needs
+       to begin with "http(s)://" and end with "/".
+@param length length of the address
+@return ROOTPA_OK is setting succeeded, an error code otherwise
+*/
+rootpaerror_t setSeAddress(const char* addrP, uint32_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PROVISIONINGAGENT_H
diff --git a/mobicore/rootpa/Code/Common/include/rootpa.h b/mobicore/rootpa/Code/Common/include/rootpa.h
new file mode 100644 (file)
index 0000000..b694b92
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ROOTPA_H
+#define ROOTPA_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <wrapper.h>
+#include <mcUuid.h>
+#include <mcContainer.h>
+
+#include "rootpaErrors.h"
+
+#define UUID_LENGTH 16
+
+typedef enum {
+    CONNECTING_SERVICE_ENABLER=1,
+    AUTHENTICATING_SOC=2,
+    CREATING_ROOT_CONTAINER=3,
+    AUTHENTICATING_ROOT=4,
+    CREATING_SP_CONTAINER=5,
+    FINISHED_PROVISIONING=6,
+    ERROR_STATE=7,
+    UNREGISTERING_ROOT_CONTAINER=8,
+    PROVISIONING_STATE_INSTALL_TRUSTLET=0xFEED,
+    PROVISIONING_STATE_THREAD_EXITING=0xDEAD
+}  ProvisioningState;
+
+typedef struct
+{
+    char* imeiEsnP;      // IMEI or ESN (CDMA) code
+       char* mnoP;          // network operator (based on the SIM card, not current network)
+       char* brandP;
+       char* manufacturerP;
+       char* hardwareP;
+       char* modelP;
+       char* versionP;
+} osInfo_t;
+
+typedef struct
+{
+    uint8_t* trustletP;
+    uint32_t trustletSize;
+} tltInfo_t;
+
+/**
+ callback function that has to be imlemented in the os specific wrapper. RootPA calls this at various stages of
+ provisioning, depending on the messages sent by SE. Note that PROVISIONING_STATE_THREAD_EXITING is always the
+ last state, even if errors are retrned beforehand. This alows the wrapper to perform necessary cleanup actions
+ just before the provisioning thread exists
+
+ @param st state of the provisioning
+ @param err in case the state is ERROR, this field contains error code, otherwise the value is indetermined
+ @param tltInfo, in case the state is PROVISIONING_STATE_INSTALL_TRUSTLET this field contains information on
+        the trustlet to be installed. The callback function has to copy the trustlet before it returns.
+        In other states the field is NULL.
+*/
+typedef void (*CallbackFunctionP)(ProvisioningState st, rootpaerror_t err, tltInfo_t* tltInfo);
+
+/**
+ callback function for RootPA to get information on the device. The os specific part needs to reserve the memory
+ to the pointers of osInfo_t with malloc, RootPA the frees it when it does not need it anymore. Possible memory
+ allocation and relase for the actual osInfo_t struct is in the hands of the wrapper.
+*/
+typedef rootpaerror_t (*SystemInfoCallbackFunctionP)(osInfo_t* );
+
+typedef struct
+{
+    /**
+    used with commands, true if the execution should continue even if error is received in this command, false otherwise.
+    */
+    bool     ignoreError;
+
+    /**
+    possible error that occurred when executing this command
+    */
+    rootpaerror_t ret;
+
+    /**
+    possible internal error that occurred when executing this command
+    */
+    uint32_t intRet;
+
+    /**
+    used for matching reply with corresponding command in xml messages
+    */
+    uint32_t id;
+
+} CommonMessage;
+
+typedef struct
+{
+
+    /**
+    length of the memory allocated in the contentP
+    */
+    uint32_t length;
+
+    /**
+    pointer to the actual content of the message. Care has to be taken on allocating and freeing the memory properly.
+    */
+    uint8_t* contentP;
+
+    /**
+    data needed to
+    */
+    CommonMessage hdr;
+
+}  CmpMessage;
+
+/**
+*/
+typedef struct
+{
+    /**
+    UUID of the trustlet container
+    */
+    mcUuid_t uuid;
+
+    /**
+    state of the trustlet container
+    */
+    int state;
+}  TltContainerData;
+
+typedef struct
+{
+    /**
+    state of the servce provider container
+    */
+    int state;
+
+    /**
+    number of trustlets in the container
+    */
+    int nbrOfTlts;
+
+    /**
+    array of trustlet containers in the service provider container. Only the number of elements indicated in nbrOfTlts are set.
+    */
+    TltContainerData tltContainers[MC_CONT_CHILDREN_COUNT];
+}  SpContainerStructure;
+
+typedef enum {
+    REQUEST_DATA_NO_DATA=0,
+    REQUEST_DATA_TLT=1,
+    REQUEST_DATA_KEY=2
+}TltInstallationRequestDataType;
+
+typedef struct {
+    /**
+    pointer to either the trustlet binary or encryption key, depending on the request type
+    */
+    const uint8_t* dataP;
+    /**
+    length of the data pointed by the pointer
+    */
+    uint32_t dataLength;
+    /**
+    tells whether dataP points to trustlet binary (REQUEST_DATA_TLT) or encryption key (REQUEST_DATA_KEY)
+    */
+    TltInstallationRequestDataType dataType;
+    /**
+    uuid of the trustlet
+    */
+    mcUuid_t uuid;
+
+    /**
+    minimum version of the trustlet
+    */
+    uint32_t minTltVersion;
+
+    /**
+    pointer to tltPukHash
+    */
+    const uint8_t* tltPukHashP;
+
+    /**
+    length of data pointed by tltPukHashP
+    */
+    uint32_t tltPukHashLength;
+
+    /**
+    memory where the trustlet is to be loaded and executed:
+    0 - if enough space is available, load the Trustlet into the internal memory, otherwise into the external memory,
+    1 - internal memory,
+    2 - external memory
+    */
+    uint32_t memoryType;
+
+    /**
+    indicates how many instances of a trustlet can be installed (run) in parallel
+    */
+    uint32_t numberOfInstances;
+
+    /**
+    current flags are: 1 - permanent, 2 - service has no WSW control interface, 4 - debuggable
+    */
+    uint32_t flags;
+
+}trustletInstallationData_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ROOTPA_H
diff --git a/mobicore/rootpa/Code/Common/include/rootpaErrors.h b/mobicore/rootpa/Code/Common/include/rootpaErrors.h
new file mode 100644 (file)
index 0000000..1419ef8
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ROOTPAERRORS_H
+#define ROOTPAERRORS_H
+
+#include<stdint.h>
+
+typedef uint32_t rootpaerror_t;
+
+/*
+NOTE to the maintainer. These values and documentation needs to be in line with the ones in CommandResult.java
+*/
+
+
+/**
+ No errors detected, successful execution.
+*/
+#define ROOTPA_OK                               0x00000000
+
+/**
+ Client has requested unsupported CMP command or command that it can not execute via the used interface.
+ Possible steps to recover: send only supported CMP commands or update to RootPA that supports handling the particular command in the used interface.
+*/
+#define ROOTPA_COMMAND_NOT_SUPPORTED            0x00000001
+#define STRING_ROOTPA_COMMAND_NOT_SUPPORTED    "COMMAND_NOT_SUPPORTED_ERROR"
+
+/**
+Either rootpa is locked by another client, or the client requests lock or unlock when it is not allowed to do that.
+Possible steps to recover: wait until the lock is released
+*/
+#define ROOTPA_ERROR_LOCK                       0x00000002
+#define STRING_ROOTPA_ERROR_LOCK                "BUSY_ERROR"
+
+/**
+ Error in one of the CMP commands, see command specific response for more details.
+ */
+#define ROOTPA_ERROR_COMMAND_EXECUTION          0x00000003
+#define STRING_ROOTPA_ERROR_COMMAND_EXECUTION   "COMMAND_EXECUTION_ERROR"
+
+/**
+Registry returned an error when trying to write a container.  mcDaemon could be dead or something seriously wrong in the file system.
+Possible steps to recover: rebooting the device may help
+*/
+#define ROOTPA_ERROR_REGISTRY                   0x00000004
+#define STRING_ROOTPA_ERROR_REGISTRY            "REGISTRY_ERROR"
+
+/**
+Error in communicating with t-base secure side. This is returned when any of the mcDeamon API calls related to communication with secure side fails.
+Possible steps to recover: rebooting the device may help
+*/
+#define ROOTPA_ERROR_MOBICORE_CONNECTION        0x00000005
+#define STRING_ROOTPA_ERROR_MOBICORE_CONNECTION "MOBICORE_CONNECTION_ERROR"
+
+/**
+Either Nwd or Swd software is out of memory.
+Possible steps to recover: release memory
+*/
+#define ROOTPA_ERROR_OUT_OF_MEMORY              0x00000006
+#define STRING_ROOTPA_ERROR_OUT_OF_MEMORY       "OUT_OF_MEMORY_ERROR"
+
+/**
+Rootpa internal error. This error is returned in various situations when something unexpected went wrong e.g. message from CMTL can‘t be interpreted, SE returned an error indicating invalid data, bad request or similar or base64 decoding failed
+Possible steps to recover: rebooting or updating the device may help
+*/
+#define ROOTPA_ERROR_INTERNAL                   0x00000007
+#define STRING_ROOTPA_ERROR_INTERNAL            "INTERNAL_ERROR"
+
+/**
+Given argument is not allowed (in many cases it is NULL) or e.g. the format of xml is unsupported.
+Possible steps to recover: give correct argument
+*/
+#define ROOTPA_ERROR_ILLEGAL_ARGUMENT           0x00000008
+
+
+/**
+Error in network connection or use of networking library.
+Possible steps to recover: create working network connection (avoid firewalls and proxies that require password)
+*/
+#define ROOTPA_ERROR_NETWORK                    0x00000009
+
+
+/**
+Error returned by XML library. Problems in parsing received XML command or creating new XML response.
+*/
+#define ROOTPA_ERROR_XML                        0x0000000A
+#define STRING_ROOTPA_ERROR_XML                 "XML_ERROR"
+
+/**
+Registry returned an error when trying to read a container. Most likely the container does not exist.
+*/
+#define ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE          0x0000000B
+#define STRING_ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE   "REGISTRY_OBJECT_NOT_AVAILABLE"
+
+/**
+CMP version of the device is not supported by SE.
+Possible steps to recover: use CMP version supported by SE (>=3.0)
+*/
+#define ROOTPA_ERROR_SE_CMP_VERSION                0x0000000C
+
+/**
+Precoditions for SP container installation are not met in SE.
+Possible steps to recover: register used SPID to SE
+*/
+#define ROOTPA_ERROR_SE_PRECONDITION_NOT_MET        0x0000000D
+
+/**
+Requested SP container does not exist. This is not always considered an error but is used as an informative return code. As this is internal return code, user of RootPA services should never see this.
+Possible steps to recover: add SP container or request container with different SPID
+*/
+#define ROOTPA_ERROR_INTERNAL_NO_CONTAINER      0x00000030
+
+#endif // ROOTPAERRORS_H
diff --git a/mobicore/rootpa/Code/Common/include/version.h b/mobicore/rootpa/Code/Common/include/version.h
new file mode 100644 (file)
index 0000000..8b3f8cb
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ROOTPA
+ */
+#ifndef ROOTPA_VERSION_H_
+#define ROOTPA_VERSION_H_
+
+#define ROOTPA_VERSION_MAJOR 3
+#define ROOTPA_VERSION_MINOR 96
+
+#endif /** ROOTPA_VERSION_H_ */
diff --git a/mobicore/rootpa/Code/Common/include/wrapper.h b/mobicore/rootpa/Code/Common/include/wrapper.h
new file mode 100644 (file)
index 0000000..d48143f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef WRAPPER_H_
+#define WRAPPER_H_
+
+#ifdef WIN32
+    #ifdef __cplusplus
+    extern "C" {
+    #endif
+    #include <stdint.h>
+    #include <inttypes.h>
+
+       #define snprintf _snprintf
+
+    typedef int pid_t;
+
+    #define bool int
+    #define TRUE 1
+    #define FALSE 0
+
+    #define false FALSE
+    #define true TRUE
+
+    #define sleep(x) Sleep(x)
+
+    #ifdef __cplusplus
+    }
+    #endif // __cplusplus
+#else
+       #include <stdbool.h>
+#endif // WINDOWS_BUILD
+#endif //WRAPPER_H_
diff --git a/mobicore/rootpa/Code/Common/pacmp3.c b/mobicore/rootpa/Code/Common/pacmp3.c
new file mode 100644 (file)
index 0000000..b931566
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <wrapper.h>
+#include <TlCm/3.0/cmpMap.h>
+#include <TlCm/tlCmApiCommon.h>
+
+#include "tools.h"
+#include "logging.h"
+#include "rootpaErrors.h"
+#include "pacmtl.h"
+#include "pacmp3.h"
+#include "registry.h"
+
+static mcSpid_t spid_;
+static mcUuid_t tltUuid_;
+static CallbackFunctionP callbackP_=NULL;
+
+void setCallbackP(CallbackFunctionP callbackP)
+{
+    callbackP_=callbackP;
+}
+
+// recovery from factory reset
+bool factoryResetAssumed()
+{
+    uint32_t contSize=0;
+    void* containerP=NULL;
+    mcResult_t result1=MC_DRV_OK;
+    mcResult_t result2=MC_DRV_OK;
+
+    if((result1=regReadAuthToken((AUTHTOKENCONTAINERP*)&containerP, &contSize))==MC_DRV_OK)
+    {
+        free(containerP);
+        return false;
+    }
+
+    if((result2=regReadRoot((ROOTCONTAINERP*)&containerP, &contSize))==MC_DRV_OK)
+    {
+        free(containerP);
+        return false;
+    }
+
+    // if neither root container, nor auth token container exists, we assume that factory reset has been performed.
+    if(MC_DRV_ERR_INVALID_DEVICE_FILE==result1 && MC_DRV_ERR_INVALID_DEVICE_FILE==result2)
+    {
+        LOGD("factoryResetAssumed returning true");
+        return true;
+    }
+
+    return false;
+}
+// recovery from factory reset
+
+/*
+*/
+uint32_t sizeOfCmp()
+{
+    return (sizeof(cmp_t)); // could also use CMP_SIZE, but this way we only allocate the amount we really need
+}
+
+cmpCommandId_t getCmpCommandId(const uint8_t* commandP)
+{
+    if(NULL==commandP) return 0xFFFFFFFF;
+    return ((cmpCommandHeaderMap_t*)commandP)->commandId;
+}
+
+
+uint32_t getCmpReturnCode(const uint8_t* cmpMsgP)
+{
+    return ((cmpResponseHeader_t*)cmpMsgP)->returnCode;
+}
+
+rootpaerror_t allocateResponseBuffer(CmpMessage* responseP, CMTHANDLE handle )
+{
+    uint32_t elementIndex=1;
+    uint32_t offset=0;
+
+    if(!getRspElementInfo(&elementIndex, handle, &offset, &(responseP->length)))
+    {
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    LOGD("allocateResponseBuffer, size %d", responseP->length);
+    responseP->contentP=(uint8_t*)malloc(responseP->length);
+    if(responseP->contentP==NULL) return ROOTPA_ERROR_OUT_OF_MEMORY;
+    return ROOTPA_OK;
+}
+
+bool ensureMappedBufferSize(CMTHANDLE handle, uint32_t neededSize)
+{
+    if( neededSize > handle->mappedSize)
+    {
+        uint8_t* newMappedP = (uint8_t*)realloc(handle->mappedP, neededSize);
+        if(!newMappedP)
+        {
+            LOGE("ensureMappedBufferSize, unable to allocate more memory %d", neededSize);
+            return false;
+        }
+        handle->mappedP = newMappedP;
+    }
+    return true;
+}
+
+rootpaerror_t addAuthTokenContainer(uint32_t* indexP, uint32_t* offsetP, CMTHANDLE handle, mcResult_t* mcRetP)
+{
+    rootpaerror_t ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+    AUTHTOKENCONTAINERP authTokenP = NULL;
+    uint32_t contSize=0;
+
+    if((*mcRetP=regReadAuthToken(&authTokenP, &contSize))==MC_DRV_OK)
+    {
+        if(ensureMappedBufferSize(handle, (*offsetP) + contSize))
+        {
+            memcpy(handle->mappedP+(*offsetP), authTokenP, contSize);
+            setCmdElementInfo(indexP, handle->wsmP, offsetP, contSize);
+            ret=ROOTPA_OK;
+        }
+    }
+    else if (MC_DRV_ERR_INVALID_DEVICE_FILE==*mcRetP)
+    {
+        ret=ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE;
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+    free(authTokenP);
+    return ret;
+}
+
+rootpaerror_t addRootContainer(uint32_t* indexP, uint32_t* offsetP, CMTHANDLE handle, mcResult_t* mcRetP)
+{
+    rootpaerror_t ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+    ROOTCONTAINERP rootP = NULL;
+    uint32_t contSize=0;
+
+    if((*mcRetP=regReadRoot(&rootP, &contSize))==MC_DRV_OK)
+    {
+        if(ensureMappedBufferSize(handle, (*offsetP) + contSize))
+        {
+            memcpy(handle->mappedP+(*offsetP), rootP, contSize);
+            setCmdElementInfo(indexP, handle->wsmP, offsetP, contSize);
+            ret=ROOTPA_OK;
+        }
+    }
+    else if (MC_DRV_ERR_INVALID_DEVICE_FILE==*mcRetP)
+    {
+        ret=ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE;
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+    free(rootP);
+    return ret;
+}
+
+rootpaerror_t addSpContainer(uint32_t* indexP, uint32_t* offsetP, mcSpid_t spid, CMTHANDLE handle, mcResult_t* mcRetP)
+{
+    rootpaerror_t ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+    SPCONTAINERP spP = NULL;
+    uint32_t contSize=0;
+
+    if((*mcRetP=regReadSp(spid, &spP, &contSize))==MC_DRV_OK)
+    {
+        if(ensureMappedBufferSize(handle, (*offsetP) + contSize))
+        {
+            memcpy(handle->mappedP+(*offsetP),spP,contSize);
+            setCmdElementInfo(indexP, handle->wsmP, offsetP, contSize);
+            ret=ROOTPA_OK;
+        }
+    }
+    else if (MC_DRV_ERR_INVALID_DEVICE_FILE==*mcRetP)
+    {
+        ret=ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE;
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+    free(spP);
+    return ret;
+}
+
+
+rootpaerror_t addTltContainer(uint32_t* indexP, uint32_t* offsetP, const mcUuid_t* uuidP, mcSpid_t spid, CMTHANDLE handle, mcResult_t* mcRetP)
+{
+    rootpaerror_t ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+    TLTCONTAINERP tltP = NULL;
+    uint32_t contSize=0;
+
+    if((*mcRetP=regReadTlt(uuidP, &tltP, &contSize, spid))==MC_DRV_OK)
+    {
+        if(ensureMappedBufferSize(handle, (*offsetP) + contSize))
+        {
+            memcpy(handle->mappedP+(*offsetP),tltP,contSize);
+            setCmdElementInfo(indexP, handle->wsmP, offsetP, contSize);
+            ret=ROOTPA_OK;
+        }
+    }
+    else if (MC_DRV_ERR_INVALID_DEVICE_FILE==*mcRetP)
+    {
+        ret=ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE;
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_REGISTRY;
+    }
+
+    free(tltP);
+    return ret;
+}
+
+
+rootpaerror_t prepareCommand(cmpCommandId_t commandId, CmpMessage* inCommandP,  CMTHANDLE handle, CmpMessage* responseP)
+{
+    uint8_t* outCommandP =handle->mappedP;
+
+    uint32_t offset=0;
+    uint32_t elementIndex=1;
+    rootpaerror_t ret=ROOTPA_OK;
+    mcResult_t mcRet=MC_DRV_OK;
+    LOGI("prepareCommand command id %d length %d", commandId, inCommandP->length);  // this is LOGI level on purpose to indicate that CMP command has reached RootPA
+
+    memset(handle->wsmP,0,sizeOfCmp());
+
+    setCmdMapInfo(handle->wsmP, &handle->mapInfo);
+    setCmdCmpVersionAndCmdId(handle->wsmP, commandId);
+    setCmdElementInfo(&elementIndex, handle->wsmP, &offset, inCommandP->length);
+    if(ensureMappedBufferSize(handle, inCommandP->length))
+    {
+        memcpy(handle->mappedP, inCommandP->contentP, inCommandP->length);
+    }
+    else
+    {
+        responseP->hdr.ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+        return ROOTPA_ERROR_OUT_OF_MEMORY;
+    }
+    switch(commandId)
+    {
+        case MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION:
+            if (callbackP_) callbackP_(AUTHENTICATING_SOC, ROOTPA_OK, NULL);
+            ret=addAuthTokenContainer(&elementIndex, &offset, handle, &mcRet);
+            break;
+
+        case MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION:
+            if (callbackP_) callbackP_(AUTHENTICATING_ROOT, ROOTPA_OK, NULL);
+            ret=addRootContainer(&elementIndex, &offset, handle, &mcRet);
+            break;
+
+        case MC_CMP_CMD_BEGIN_SP_AUTHENTICATION:
+            ret=addRootContainer(&elementIndex, &offset, handle, &mcRet);
+            if(ROOTPA_OK==ret)
+            {
+                mcSpid_t spid=((cmpCmdBeginSpAuthentication_t*)outCommandP)->cmd.spid;
+                ret=addSpContainer(&elementIndex, &offset, spid, handle, &mcRet);
+            }
+            break;
+        case MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE:
+            if (callbackP_) callbackP_(CREATING_ROOT_CONTAINER, ROOTPA_OK, NULL);
+            break;
+
+        case MC_CMP_CMD_ROOT_CONT_UNREGISTER:
+            if (callbackP_) callbackP_(UNREGISTERING_ROOT_CONTAINER, ROOTPA_OK, NULL);
+            break;
+
+        case MC_CMP_CMD_SP_CONT_ACTIVATE:
+            spid_=((cmpCmdSpContActivate_t*)outCommandP)->cmd.sdata.spid;
+            break;
+        case MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT:
+            spid_=((cmpCmdSpContLockByRoot_t*)outCommandP)->cmd.sdata.spid;
+            ret=addSpContainer(&elementIndex, &offset, spid_, handle, &mcRet);
+            break;
+        case MC_CMP_CMD_SP_CONT_LOCK_BY_SP :
+            spid_=((cmpCmdSpContLockBySp_t*)outCommandP)->cmd.sdata.spid;
+            break;
+        case MC_CMP_CMD_SP_CONT_REGISTER:
+            if (callbackP_) callbackP_(CREATING_SP_CONTAINER, ROOTPA_OK, NULL);
+            spid_=((cmpCmdSpContRegister_t*)outCommandP)->cmd.sdata.spid;
+            break;
+        case MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE :
+            if (callbackP_) callbackP_(CREATING_SP_CONTAINER, ROOTPA_OK, NULL);
+            spid_=((cmpCmdSpContRegister_t*)outCommandP)->cmd.sdata.spid;
+            break;
+        case MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT:
+            spid_=((cmpCmdSpContUnlockByRoot_t*)outCommandP)->cmd.sdata.spid;
+            ret=addSpContainer(&elementIndex, &offset, spid_, handle, &mcRet);
+            break;
+        case MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP :
+            spid_=((cmpCmdSpContUnlockBySp_t*)outCommandP)->cmd.sdata.spid;
+            break;
+        case MC_CMP_CMD_SP_CONT_UNREGISTER:
+            spid_=((cmpCmdSpContUnregister_t*)outCommandP)->cmd.sdata.spid;
+            break;
+        case MC_CMP_CMD_TLT_CONT_ACTIVATE:
+            spid_=((cmpCmdTltContActivate_t*)outCommandP)->cmd.sdata.spid;
+            memcpy(&tltUuid_,&((cmpCmdTltContActivate_t*)outCommandP)->cmd.sdata.uuid, sizeof(mcUuid_t));
+            ret=addTltContainer(&elementIndex, &offset, &tltUuid_, spid_, handle, &mcRet);
+            break;
+        case MC_CMP_CMD_TLT_CONT_LOCK_BY_SP:
+            spid_=((cmpCmdTltContLockBySp_t*)outCommandP)->cmd.sdata.spid;
+            memcpy(&tltUuid_,&((cmpCmdTltContLockBySp_t*)outCommandP)->cmd.sdata.uuid, sizeof(mcUuid_t));
+            ret=addTltContainer(&elementIndex, &offset, &tltUuid_, spid_, handle, &mcRet);
+            break;
+        case MC_CMP_CMD_TLT_CONT_PERSONALIZE:
+            ret=addTltContainer(&elementIndex, &offset, &((cmpCmdTltContPersonalize_t*)outCommandP)->cmd.sdata.uuid,
+                                                        ((cmpCmdTltContPersonalize_t*)outCommandP)->cmd.sdata.spid,
+                                                        handle, &mcRet);
+            break;
+        case MC_CMP_CMD_TLT_CONT_REGISTER:
+            spid_=((cmpCmdTltContRegister_t*)outCommandP)->cmd.sdata.spid;
+            memcpy(&tltUuid_,&((cmpCmdTltContRegister_t*)outCommandP)->cmd.sdata.uuid, sizeof(mcUuid_t));
+            break;
+        case MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE:
+            spid_=((cmpCmdTltContRegisterActivate_t*)outCommandP)->cmd.sdata.spid;
+            memcpy(&tltUuid_,&((cmpCmdTltContRegisterActivate_t*)outCommandP)->cmd.sdata.uuid, sizeof(mcUuid_t));
+            break;
+        case MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP:
+            spid_=((cmpCmdTltContUnlockBySp_t*)outCommandP)->cmd.sdata.spid;
+            memcpy(&tltUuid_,&((cmpCmdTltContUnlockBySp_t*)outCommandP)->cmd.sdata.uuid, sizeof(mcUuid_t));
+            ret=addTltContainer(&elementIndex, &offset, &tltUuid_, spid_, handle, &mcRet);
+            break;
+        case MC_CMP_CMD_TLT_CONT_UNREGISTER:
+            spid_=((cmpCmdTltContUnlockBySp_t*)outCommandP)->cmd.sdata.spid;
+            memcpy(&tltUuid_,&((cmpCmdTltContUnlockBySp_t*)outCommandP)->cmd.sdata.uuid, sizeof(mcUuid_t));
+            break;
+        default:
+            // nothing extra to do, just return ret at the end of function
+            break;
+
+    }
+    responseP->hdr.ret=ret;
+    responseP->hdr.intRet=mcRet;
+    return ret;
+}
+
+
+mcResult_t storeContainers(cmpCommandId_t commandId, CMTHANDLE handle, uint32_t elementIndex, uint32_t  offset)
+{
+    mcResult_t mcRet=MC_DRV_OK;
+    uint32_t length=0;
+    LOGD(">>pacmp3 storeContainers for %d element %d offset %d", commandId, elementIndex, offset);
+
+// store the containers when needed
+    switch(commandId)
+    {
+        case MC_CMP_CMD_GENERATE_AUTH_TOKEN:
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteAuthToken((AUTHTOKENCONTAINERP) (handle->mappedP+offset), length);
+            }
+            else
+            {
+                mcRet=-1;
+            }
+            break;
+
+        case MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE:
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteRoot((ROOTCONTAINERP) (handle->mappedP+offset), length);
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            if(MC_DRV_OK==mcRet)
+            {
+                mcSoAuthTokenCont_t* authTokenP=NULL;
+                uint32_t authTokenSize=0;
+
+                mcRet=regReadAuthToken(&authTokenP, &authTokenSize);
+                if(mcRet!=MC_DRV_OK)
+                {
+                    LOGE("pacmp3 storeContainers for %d regReadAuthToken failed %d, since this was only precaution, continuing", commandId, mcRet);
+                }
+                mcRet=regDeleteAuthToken();
+                if(mcRet!=MC_DRV_OK)
+                {
+                    LOGE("pacmp3 storeContainers for %d regDeleteAuthToken failed %d, trying to recover", commandId, mcRet);
+                    // try to recover, remove root, but only if there is auth token stored
+                    if(authTokenP)
+                    {
+                        mcRet=regWriteAuthToken((AUTHTOKENCONTAINERP) authTokenP, authTokenSize); // trying to be failsafe here. Deleting failed but rewriting the token anyway
+                        if(MC_DRV_OK==mcRet)
+                        {
+                            regCleanupRoot(); // since we were able to restore authToken we delete root (due to an error in registry handling)
+                        }
+                    }
+                }
+                free(authTokenP);
+            }
+            else
+            {
+                LOGE("pacmp3 storeContainers for %d regWriteRoot failed %d", commandId, mcRet);
+            }
+            break;
+
+
+        case MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT:
+        case MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT:
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteRoot((ROOTCONTAINERP) (handle->mappedP+offset), length);
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            break;
+
+        case MC_CMP_CMD_ROOT_CONT_UNREGISTER:
+            mcRet=regCleanupRoot();
+            break;
+
+        case MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT:
+        case MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP:
+        case MC_CMP_CMD_SP_CONT_ACTIVATE:
+        case MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT:
+        case MC_CMP_CMD_SP_CONT_LOCK_BY_SP:
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteSp(spid_, (SPCONTAINERP) (handle->mappedP+offset), length);
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            break;
+
+        case MC_CMP_CMD_SP_CONT_REGISTER:
+        case MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE:
+        {
+            // Root container is in the buffer first, that is why we read it first
+            // we write it last since if SP container writing fails we do not want
+            // to write root container
+            uint32_t rootLength=0;
+            ROOTCONTAINERP rootP=NULL;
+            if(getRspElementInfo(&elementIndex, handle, &offset, &rootLength))
+            {
+                rootP=(ROOTCONTAINERP) (handle->mappedP+offset);
+                if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+                {
+                    mcRet=regWriteSp(spid_, (SPCONTAINERP) (handle->mappedP+offset), length);
+                }
+                else
+                {
+                    mcRet=-1;
+                }
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            if(MC_DRV_OK==mcRet)
+            {
+                mcRet=regWriteRoot(rootP, rootLength);
+            }
+            else
+            {
+                LOGE("pacmp3 storeContainers for %d regWriteSp failed %d", commandId, mcRet);
+            }
+            break;
+
+        }
+        case MC_CMP_CMD_SP_CONT_UNREGISTER:
+            mcRet=regCleanupSp(spid_);
+            if(MC_DRV_OK!=mcRet)
+            {
+                LOGE("pacmp3 storeContainers for %d regCleanupSp failed %d, , still attempting storing root", commandId, mcRet);
+            }
+
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteRoot((ROOTCONTAINERP) (handle->mappedP+offset), length);
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            break;
+
+
+        case MC_CMP_CMD_TLT_CONT_REGISTER:
+        case MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE:
+        {
+            // SP container is in the buffer first, that is why we read it first
+            // we write it last since if TLT container writing fails we do not want
+            // to write SP container
+            uint32_t spLength=0;
+            SPCONTAINERP spP=NULL;
+            if(getRspElementInfo(&elementIndex, handle, &offset, &spLength))
+            {
+                spP=(SPCONTAINERP) (handle->mappedP+offset);
+                if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+                {
+                    mcRet=regWriteTlt(&tltUuid_,(TLTCONTAINERP) (handle->mappedP+offset), length, spid_);
+                }
+                else
+                {
+                    mcRet=-1;
+                }
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            if(MC_DRV_OK==mcRet)
+            {
+                mcRet=regWriteSp(spid_, spP, spLength);
+                if(MC_DRV_OK!=mcRet)
+                {
+                    LOGE("pacmp3 storeContainers for %d regWriteSp failed %d", commandId, mcRet);
+                    regCleanupTlt(&tltUuid_, spid_);
+                }
+            }
+            else
+            {
+                LOGE("pacmp3 storeContainers for %d regWriteTlt failed %d", commandId, mcRet);
+            }
+            break;
+
+        }
+        case MC_CMP_CMD_TLT_CONT_ACTIVATE:
+        case MC_CMP_CMD_TLT_CONT_LOCK_BY_SP:
+        case MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP:
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteTlt(&tltUuid_,(TLTCONTAINERP) (handle->mappedP+offset), length, spid_);
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            break;
+
+        case MC_CMP_CMD_TLT_CONT_UNREGISTER:
+            mcRet=regCleanupTlt(&tltUuid_, spid_);
+            if(MC_DRV_OK!=mcRet)
+            {
+                LOGE("pacmp3 storeContainers for %d regCleanupTlt failed %d, still attempting storing sp", commandId, mcRet);
+            }
+
+            if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+            {
+                mcRet=regWriteSp(spid_, (SPCONTAINERP) (handle->mappedP+offset), length);
+                if(MC_DRV_OK!=mcRet)
+                {
+                    LOGE("pacmp3 storeContainers for %d regWriteSp failed %d", commandId, mcRet);
+                }
+            }
+            else
+            {
+                mcRet=-1;
+            }
+
+            break;
+
+         default:
+            LOGD("pacmp3 storeContainers nothing to store");
+            // nothing to do
+            break;
+    }
+    LOGD("<<pacmp3 storeContainers %d %d", commandId, mcRet);
+    return mcRet;
+}
+/**
+handleResponse stores the container received in response and copies the response to the buffer to be returned
+to the client Note that the container is not store id cmtl returned an error, but the content of the response is
+returned to the client.
+*/
+rootpaerror_t handleResponse(cmpCommandId_t commandId, CmpMessage* outResponseP, CMTHANDLE handle)
+{
+    mcResult_t mcRet=MC_DRV_OK;
+    rootpaerror_t ret=ROOTPA_OK;
+    uint32_t elementIndex=1;
+    uint32_t offset=0;
+    uint32_t length=0;
+
+    LOGD(">>handleResponse for command %d ", commandId);
+
+    if(isValidResponseTo(commandId, handle->wsmP)==false)
+    {
+        LOGE("no valid response to %d", commandId);
+        outResponseP->hdr.ret=ROOTPA_ERROR_COMMAND_EXECUTION;
+        return ROOTPA_ERROR_COMMAND_EXECUTION;
+    }
+
+    ret=allocateResponseBuffer(outResponseP, handle);
+
+    if(ROOTPA_OK==ret)
+    {
+        if(getRspElementInfo(&elementIndex, handle, &offset, &length))
+        {
+            memcpy(outResponseP->contentP, handle->mappedP+offset, length );
+        }
+        else
+        {
+            return ROOTPA_ERROR_INTERNAL;
+        }
+
+        if (getCmpReturnCode(handle->mappedP)!=SUCCESSFUL) // this checking is here since we want the response to be returned even in case of CMP error
+        {
+            LOGE("executeOneCmpCommand: command execution failed 0x%x", getCmpReturnCode(handle->mappedP));
+            outResponseP->hdr.intRet=getCmpReturnCode(handle->mappedP);
+            return ROOTPA_ERROR_COMMAND_EXECUTION;
+        }
+    }
+    else
+    {
+        outResponseP->hdr.ret=ret;
+        LOGE("executeOneCmpCommand: response buffer allocation failed %d (0x%x)", ret, handle->lasterror);
+        return ret;
+    }
+
+    mcRet=storeContainers(commandId, handle, elementIndex, offset);
+
+    if(mcRet != MC_DRV_OK)
+    {
+        LOGE("pacmp3 handleResponse for %d registry failed %d", commandId, mcRet);
+        if((mcResult_t)-1==mcRet)
+        {
+            ret = ROOTPA_ERROR_INTERNAL;
+        }
+        else
+        {
+            ret = ROOTPA_ERROR_REGISTRY;
+        }
+        if(0==outResponseP->hdr.intRet)
+        {
+            outResponseP->hdr.intRet=mcRet;
+        }
+        outResponseP->hdr.ret=ret;
+    }
+    LOGD("<<handleResponse returning %d ", ret);
+    return ret;
+}
diff --git a/mobicore/rootpa/Code/Common/pacmp3.h b/mobicore/rootpa/Code/Common/pacmp3.h
new file mode 100644 (file)
index 0000000..293b30a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PACMP3_H
+#define PACMP3_H
+
+
+#include <TlCm/3.0/tlCmApi.h>
+
+#include "rootpa.h"
+#include "trustletchannel.h"
+
+uint32_t sizeOfCmp();
+
+// recovery from factory reset
+bool factoryResetAssumed();
+// recovery from factory reset
+
+cmpCommandId_t getCmpCommandId(const uint8_t* commandP);
+
+rootpaerror_t prepareCommand(cmpCommandId_t commandId, CmpMessage* inCommandP,  CMTHANDLE handle, CmpMessage* inResponseP);
+rootpaerror_t handleResponse(cmpCommandId_t commandId, CmpMessage* outResponseP, CMTHANDLE handle);
+void setCallbackP(CallbackFunctionP callbackP);
+
+#endif // PACMP3_H
diff --git a/mobicore/rootpa/Code/Common/pacmtl.c b/mobicore/rootpa/Code/Common/pacmtl.c
new file mode 100644 (file)
index 0000000..3e9792c
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include "logging.h"
+
+#include "pacmp3.h"
+#include "registry.h"
+#include "pacmtl.h"
+
+#define ILLEGAL_ELEMENT 0
+#define FIRST_ELEMENT 1
+#define FIRST_ELEMENT_OFFSET 0
+
+void setCmdElementInfo(uint32_t* elementNbrP, uint8_t* wsmP, uint32_t* elementOffsetP, uint32_t elementLength)
+{
+    cmpMapOffsetInfo_t* elementP;
+    if(NULL==elementNbrP || NULL == elementOffsetP || NULL == wsmP)
+    {
+        LOGE("pacmtl setCmdElementInfo NULL's in input, not setting the element %ld %ld", (long int) elementNbrP, (long int) elementOffsetP);
+        return;
+    }
+
+    if(ILLEGAL_ELEMENT==*elementNbrP || (*elementNbrP==FIRST_ELEMENT && *elementOffsetP != FIRST_ELEMENT_OFFSET))
+    {
+        LOGE("pacmtl setCmdElementInfo error in input, not setting the element %d %d", *elementNbrP, *elementOffsetP);
+        return;
+    }
+
+    elementP=(&((cmpCommandHeaderTci_t*)wsmP)->cmpCmdMapOffsetInfo);
+    elementP+=((*elementNbrP)-1);
+
+    elementP->offset=*elementOffsetP;
+    elementP->len=elementLength;
+    (*elementNbrP)++;                  // returning number of next element
+    (*elementOffsetP)+=elementLength;  // returning offset to next element
+}
+
+
+void setCmdMapInfo(uint8_t* wsmP, const mcBulkMap_t* mapInfoP)
+{
+    // mapInfo and *mapinfoP are of different type, thats why assignment instead of memcpy.
+
+   ((cmpCommandHeaderTci_t*)wsmP)->mapInfo.addr=mapInfoP->sVirtualAddr;
+   ((cmpCommandHeaderTci_t*)wsmP)->mapInfo.len=mapInfoP->sVirtualLen;
+}
+
+void setCmdCmpVersionAndCmdId(uint8_t* wsmP, cmpCommandId_t commandId)
+{
+    ((cmpCommandHeaderTci_t*)wsmP)->version=CMP_VERSION;
+    ((cmpCommandHeaderTci_t*)wsmP)->commandId=commandId;
+}
+
+bool getRspElementInfo(uint32_t* elementNbrP, CMTHANDLE handle, uint32_t* elementOffsetP, uint32_t* elementLengthP)
+{
+    uint8_t* wsmP=NULL;
+    cmpMapOffsetInfo_t* elementP=NULL;
+
+    if(NULL==handle)
+    {
+        LOGE("pacmtl setCmdElementInfo ho handle");
+        *elementLengthP=0;
+        return false;
+    }
+    wsmP=handle->wsmP;
+    LOGD(">>pacmtl getRspElementInfo %x %x %d %d %d %d", ((cmpResponseHeaderTci_t*)wsmP)->version,
+                                                         ((cmpResponseHeaderTci_t*)wsmP)->responseId,
+                                                         ((cmpResponseHeaderTci_t*)wsmP)->len,
+                                                         *((uint32_t*)(wsmP+12)),
+                                                         *((uint32_t*)(wsmP+16)),
+                                                         *((uint32_t*)(wsmP+20)));
+    if(NULL==elementNbrP || NULL == elementOffsetP || NULL == elementLengthP || NULL == handle->wsmP)
+    {
+        LOGE("pacmtl getRspElementInfo NULL's in input, not setting the element %ld %ld", (long int) elementNbrP, (long int) elementOffsetP);
+        return false;
+    }
+
+
+    if(ILLEGAL_ELEMENT==*elementNbrP)
+    {
+        LOGE("pacmtl getRspElementInfo error in input (illegal element), not getting the element %d", *elementNbrP);
+        *elementLengthP=0;
+        return false;
+    }
+
+    elementP=(cmpMapOffsetInfo_t*)(wsmP+sizeof(cmpResponseHeaderTci_t));
+    elementP+=((*elementNbrP)-1);
+
+    if(elementP->offset+elementP->len > handle->mappedSize)
+    {
+        LOGE("pacmtl getRspElementInfo error in input (offset+len too big), not getting the element %d", *elementNbrP);
+        *elementLengthP=0;
+        return false;
+    }
+
+    *elementOffsetP=elementP->offset;
+    *elementLengthP=elementP->len;
+    LOGD("<<pacmtl getRspElementInfo element %d offset %d length %d", *elementNbrP, *elementOffsetP, *elementLengthP);
+    (*elementNbrP)++;  // returning number of next element
+    return true;
+}
+
+uint32_t getRspCmpVersion(const uint8_t* wsmP)
+{
+    return ((cmpResponseHeaderTci_t*)wsmP)->version;
+}
+
+uint32_t getRspCmpId(const uint8_t* wsmP)
+{
+    return ((cmpResponseHeaderTci_t*)wsmP)->responseId;
+}
+
+
+bool isValidResponse(const uint8_t* wsmP)
+{
+
+    if(NULL==wsmP)
+    {
+        LOGE("pacmtl isValidResponse returning false due to NULL wsmP");
+        return false;
+    }
+    if(getRspCmpVersion(wsmP) != CMP_VERSION )
+    {
+        LOGE("pacmtl isValidResponse returning false due to cmpVersion 0x%x", getRspCmpVersion(wsmP));
+        return false;
+    }
+
+    if(IS_RSP(getRspCmpId(wsmP)))
+    {
+        return true;
+    }
+    LOGE("pacmtl isValidResponse returning false IS_RSP %d", getRspCmpId(wsmP));
+    return false;
+}
+
+bool isValidResponseTo(cmpCommandId_t commandId, const uint8_t* wsmP)
+{
+    LOGD(">>pacmtl isValidResponseTo %d", commandId);
+    if(isValidResponse(wsmP))
+    {
+        if(getRspCmpId(wsmP)==RSP_ID(commandId))
+        {
+            LOGD("<<pacmtl isValidResponseTo returning true");
+            return true;
+        }
+    }
+    LOGE("<<pacmtl isValidResponseTo returning false");
+    return false;
+}
+
+uint32_t getNeededBytesFromResponse(const uint8_t* wsmP)
+{
+    if(!isValidResponse(wsmP))
+    {
+        return -1;
+    }
+    return ((cmpResponseHeaderTci_t*)wsmP)->len;
+}
+
+typedef struct {
+    uint32_t cmdId;
+    uint32_t cmdRspSize;
+    uint32_t cmdContainerSize;
+    uint32_t rspContainerSize;
+} cmpSizes_t;
+//
+// note that the container sizes are
+//
+static const cmpSizes_t sizeTable_[] = {
+    {
+        MC_CMP_CMD_AUTHENTICATE,
+        sizeof(cmpMapAuthenticate_t),
+        0,
+        0
+    },
+    {
+        MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION,
+        sizeof(cmpMapBeginRootAuthentication_t),
+        SIZEOFROOTCONTAINER,
+        0
+    },
+    {
+        MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION,
+        sizeof(cmpMapBeginSocAuthentication_t),
+        SIZEOFAUTHTOKENCONTAINER,
+        0
+    },
+    {
+        MC_CMP_CMD_BEGIN_SP_AUTHENTICATION,
+        sizeof(cmpMapBeginSpAuthentication_t),
+        SIZEOFROOTCONTAINER+SIZEOFSPCONTAINER,
+        0
+    },
+    {
+        MC_CMP_CMD_GENERATE_AUTH_TOKEN,
+        sizeof(cmpMapGenAuthToken_t),
+        0,
+        0 //SIZEOFAUTHTOKENCONTAINER
+    },
+    {
+        MC_CMP_CMD_GET_VERSION,
+        sizeof(cmpMapGetVersion_t),
+        0,
+        0
+    },
+    {
+        MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT,
+        sizeof(cmpMapRootContLockByRoot_t),
+        0,
+        SIZEOFROOTCONTAINER
+    },
+    {
+        MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE,
+        sizeof(cmpMapRootContRegisterActivate_t),
+        0,
+        SIZEOFROOTCONTAINER
+    },
+    {
+        MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT,
+        sizeof(cmpMapRootContUnlockByRoot_t),
+        0,
+        SIZEOFROOTCONTAINER
+    },
+    {
+        MC_CMP_CMD_ROOT_CONT_UNREGISTER,
+        sizeof(cmpMapRootContUnregister_t),
+        0,
+        0
+    },
+    {
+        MC_CMP_CMD_SP_CONT_ACTIVATE,
+        sizeof(cmpMapSpContActivate_t),
+        0,
+        SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT,
+        sizeof(cmpMapSpContLockByRoot_t),
+        SIZEOFSPCONTAINER,
+        SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_LOCK_BY_SP,
+        sizeof(cmpMapSpContLockBySp_t),
+        0,
+        SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_REGISTER,
+        sizeof(cmpMapSpContRegister_t),
+        0,
+        SIZEOFROOTCONTAINER+SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE,
+        sizeof(cmpMapSpContRegisterActivate_t),
+        0,
+        SIZEOFROOTCONTAINER+SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT,
+        sizeof(cmpMapSpContUnlockByRoot_t),
+        SIZEOFSPCONTAINER,
+        SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP,
+        sizeof(cmpMapSpContUnlockBySp_t),
+        0,
+        SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_SP_CONT_UNREGISTER,
+        sizeof(cmpMapSpContUnregister_t),
+        0,
+        SIZEOFROOTCONTAINER
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_ACTIVATE,
+        sizeof(cmpMapTltContActivate_t),
+        SIZEOFTLTCONTAINER,
+        SIZEOFTLTCONTAINER
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_LOCK_BY_SP,
+        sizeof(cmpMapTltContLockBySp_t),
+        SIZEOFTLTCONTAINER,
+        SIZEOFTLTCONTAINER
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_PERSONALIZE,
+        sizeof(cmpMapTltContPersonalize_t),
+        SIZEOFTLTCONTAINER,
+        0
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_REGISTER,
+        sizeof(cmpMapTltContRegister_t),
+        0,
+        SIZEOFSPCONTAINER+SIZEOFTLTCONTAINER
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE,
+        sizeof(cmpMapTltContRegisterActivate_t),
+        0,
+        SIZEOFSPCONTAINER+SIZEOFTLTCONTAINER
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP,
+        sizeof(cmpMapTltContUnlockBySp_t),
+        SIZEOFTLTCONTAINER,
+        SIZEOFTLTCONTAINER
+    },
+    {
+        MC_CMP_CMD_TLT_CONT_UNREGISTER,
+        sizeof(cmpMapTltContUnregister_t),
+        0,
+        SIZEOFSPCONTAINER
+    },
+    {
+        MC_CMP_CMD_GET_SUID,
+        sizeof(cmpMapGetSuid_t),
+        0,
+        0
+    },
+    {
+        MC_CMP_CMD_AUTHENTICATE_TERMINATE,
+        sizeof(cmpMapAuthenticateTerminate_t),
+        0,
+        0
+    }
+};
+
+const cmpSizes_t* getCmpSizeInfo(uint32_t cmdId)
+{
+    size_t i = 0;
+    for ( i = 0; i < sizeof(sizeTable_)/sizeof(cmpSizes_t); i++)
+    {
+        if (cmdId == sizeTable_[i].cmdId)
+        {
+            return &sizeTable_[i];
+        }
+    }
+    LOGE("getCmpSizeInfo command %d not supported", cmdId);
+    return NULL;
+}
+
+uint32_t bigger(uint32_t first, uint32_t second)
+{
+    return (first>second?first:second);
+}
+
+uint32_t getTotalMappedBufferSize(CmpMessage* commandP)
+{
+    uint32_t commandSize;
+    uint32_t containerSize;
+    const cmpSizes_t* sizesP=getCmpSizeInfo(getCmpCommandId(commandP->contentP));
+    if(NULL==sizesP) return 0;
+    commandSize=bigger(sizesP->cmdRspSize, commandP->length);
+    containerSize=bigger(sizesP->cmdContainerSize, sizesP->rspContainerSize);
+    LOGD("pacmtl getTotalMappedBufferSize %d returning %d (%d (%d %d) %d (%d %d))", sizesP->cmdId, commandSize+containerSize,
+                                                                                    commandSize, sizesP->cmdRspSize, commandP->length,
+                                                                                    containerSize, sizesP->cmdContainerSize, sizesP->rspContainerSize);
+    return (commandSize+containerSize);
+}
diff --git a/mobicore/rootpa/Code/Common/pacmtl.h b/mobicore/rootpa/Code/Common/pacmtl.h
new file mode 100644 (file)
index 0000000..538d9ce
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PACMTL_H
+#define PACMTL_H
+
+#include <MobiCoreDriverApi.h>
+#include <TlCm/3.0/tlCmApi.h>
+#include "trustletchannel.h"
+#include "rootpa.h"
+
+#define CMP_VERSION 0x00030000
+
+/**
+set the element info (offset and size) to wsmP in correct location
+
+@param elementNbrP number of the element, starting from one, increased by one before return
+@param wsmP pointer to the beginnign of wsm buffer
+@param &elementOffsetP offset to the element, 0 when the element number is 1, increased by length before return
+@param elementLength length of the element
+*/
+void setCmdElementInfo(uint32_t* elementNbrP, uint8_t* wsmP, uint32_t* elementOffsetP, uint32_t elementLength);
+
+void setCmdMapInfo(uint8_t* wsmP, const mcBulkMap_t* mapInfoP);
+
+void setCmdCmpVersionAndCmdId(uint8_t* wsmP, cmpCommandId_t commandId);
+
+bool getRspElementInfo(uint32_t* elementNbrP, CMTHANDLE handle, uint32_t* elementOffsetP, uint32_t* elementLengthP);
+
+uint32_t getRspCmpVersion(const uint8_t* wsmP);
+
+uint32_t getRspCmpId(const uint8_t* wsmP);
+
+bool isValidResponseTo(cmpCommandId_t commandId, const uint8_t* wsmP);
+/**
+@param pointer to the buffer containing response from CMTL
+@return needed bytes from the response, -1 if wsmP is not valid response. Accoriding to the specification 0 if the response fit into the buffer.
+*/
+uint32_t getNeededBytesFromResponse(const uint8_t* wsmP);
+
+uint32_t getTotalMappedBufferSize(CmpMessage* commandP);
+#endif // PACMTL_H
diff --git a/mobicore/rootpa/Code/Common/provisioningengine.c b/mobicore/rootpa/Code/Common/provisioningengine.c
new file mode 100644 (file)
index 0000000..9168952
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <wrapper.h>
+
+
+#include "rootpaErrors.h"
+#include "logging.h"
+#include "pacmp3.h"  // for setCallbackP
+#include "seclient.h"
+#include "xmlmessagehandler.h"
+#include "provisioningengine.h"
+
+
+static const char* const SE_URL="https://se.cgbe.trustonic.com:8443/service-enabler/enrollment/"; // note that there has to be slash at the end since we are adding suid to it next
+
+
+static const char* const RELATION_SELF  =      "relation/self";
+static const char* const RELATION_SYSTEMINFO = "relation/system_info";
+static const char* const RELATION_RESULT   =   "relation/command_result";
+static const char* const RELATION_NEXT    =    "relation/next";
+static const uint8_t* const SLASH= (uint8_t*)"/";
+
+static const char* const RELATION_INITIAL_POST="initial_post"; // this will make us to send HTTP GET, which
+                                      // is the right thing to do since we do not
+                                      // have any data to send to SE, this will need to be different in RootPA initiated trustet installation
+static const char* const RELATION_INITIAL_DELETE="initial_delete"; // this will make us to send HTTP DELETE
+
+#define INT_STRING_LENGTH 12 // (32 bit <= 10 decimal numbers) + "/" + trailing zero.
+#define INITIAL_URL_BUFFER_LENGTH 255
+
+static char initialUrl_[INITIAL_URL_BUFFER_LENGTH];
+static CallbackFunctionP callbackP_=NULL;
+
+void addSlashToUri(char* uriP)
+{
+    int uriidx;
+    LOGD(">>addSlashToUri");
+    uriidx=strlen(uriP);
+    uriP[uriidx]='/';
+    LOGD("<<addSlashToUri %s", uriP);
+}
+
+void addBytesToUri(char* uriP, uint8_t* bytes, uint32_t length, bool uuid )
+{
+    int uriidx=strlen(uriP);
+    uint32_t i;
+    uint8_t singleNumber=0;
+    LOGD(">>addBytesToUri %d", length);
+    for(i=0; i<length; i++)
+    {
+        singleNumber=(bytes[i]>>4);
+        singleNumber=((singleNumber<0xA)?(singleNumber+0x30):(singleNumber+0x57));
+        uriP[uriidx++]=singleNumber;
+        singleNumber=(bytes[i]&0x0F);
+        singleNumber=((singleNumber<0xA)?(singleNumber+0x30):(singleNumber+0x57));
+        uriP[uriidx++]=singleNumber;
+
+        if(true==uuid && (3 == i || 5 == i || 7 == i || 9 == i))
+        {
+            uriP[uriidx++]='-';
+        }
+    }
+    LOGD("<<addBytesToUri %s %d", uriP, uriidx);
+}
+
+void addIntToUri(char* uriP, uint32_t addThis)
+{
+    char intInString[INT_STRING_LENGTH];
+    memset(intInString, 0, INT_STRING_LENGTH);
+    // using signed integer since this is how SE wants it
+    snprintf(intInString, INT_STRING_LENGTH, "/%d", addThis);
+    strncpy((uriP+strlen(uriP)), intInString, INT_STRING_LENGTH); // we have earlier made sure there is enough room in uriP, using strncpy here instead strcpy is just to avoid static analysis comments
+    LOGD("add int to URI %s %d", uriP, addThis);
+}
+
+void cleanup(char** linkP, char** relP, char** commandP)
+{
+    if(commandP!=NULL)
+    {
+        free(*commandP);
+        *commandP=NULL;
+    }
+
+    if(relP!=NULL)
+    {
+        if((*relP!=RELATION_INITIAL_POST) &&
+           (*relP!=RELATION_INITIAL_DELETE)) free(*relP);
+        *relP=NULL;
+    }
+
+    if(linkP!=NULL)
+    {
+        free(*linkP);
+        *linkP=NULL;
+    }
+}
+
+rootpaerror_t setInitialAddress(const char* addrP, uint32_t length)
+{
+    if(NULL==addrP || 0==length)
+    {
+        return ROOTPA_ERROR_INTERNAL;
+    }
+
+    if(INITIAL_URL_BUFFER_LENGTH < (length + 1))
+    {
+        return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+    memset(initialUrl_, 0, INITIAL_URL_BUFFER_LENGTH);
+    memcpy(initialUrl_, addrP, length);
+    return ROOTPA_OK;
+}
+
+bool empty(const char* zeroTerminatedArray)
+{
+    return(strlen(zeroTerminatedArray)==0);
+}
+
+char* createBasicLink(mcSuid_t suid)
+{
+    char* tmpLinkP=NULL;
+    size_t urlLength=0;
+
+    urlLength=strlen(initialUrl_) + (sizeof(mcSuid_t)*2) + (sizeof(mcSpid_t)*2) + (sizeof(mcUuid_t)*2)+6; //possible slash and end zero and four dashes
+    tmpLinkP=(char*)malloc(urlLength);
+    if(tmpLinkP != NULL)
+    {
+        memset(tmpLinkP,0,urlLength);
+        strncpy(tmpLinkP, initialUrl_, urlLength);
+        addBytesToUri(tmpLinkP, (uint8_t*) &suid, sizeof(suid), false);
+    }
+    else
+    {
+        LOGE("createBasicLink, out of memory");
+    }
+    return tmpLinkP;
+}
+
+
+void doProvisioningWithSe(
+    mcSpid_t spid,
+    mcSuid_t suid,
+    CallbackFunctionP callbackP,
+    SystemInfoCallbackFunctionP getSysInfoP,
+    GetVersionFunctionP getVersionP,
+    initialRel_t initialRel,
+    trustletInstallationData_t* tltDataP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    rootpaerror_t tmpRet=ROOTPA_OK;
+    bool workToDo = true;
+    const char* linkP=NULL;
+    const char* relP=NULL;
+    const char* pendingLinkP=NULL;
+    const char* pendingRelP=NULL;
+    const char* commandP=NULL;  // "command" received from SE
+    const char* responseP=NULL; // "response" to be sent to SE
+
+    const char* usedLinkP=NULL;
+    const char* usedRelP=NULL;
+    const char* usedCommandP=NULL;
+
+    LOGD(">>doProvisioningWithSe");
+
+    callbackP_=callbackP;
+
+    if(empty(initialUrl_))
+    {
+        memset(initialUrl_, 0, INITIAL_URL_BUFFER_LENGTH);
+        strncpy(initialUrl_, SE_URL, strlen(SE_URL));
+    }
+
+    linkP=createBasicLink(suid);
+    if(NULL==linkP)
+    {
+        callbackP(ERROR_STATE, ROOTPA_ERROR_OUT_OF_MEMORY, NULL);
+        return;
+    }
+    else
+    {
+        LOGD("SE_ADDRESS %s", linkP);
+    }
+
+    if (initialRel == initialRel_DELETE)
+    {
+       relP = RELATION_INITIAL_DELETE;
+    }
+    else
+    {
+       relP = RELATION_INITIAL_POST;
+        if(spid!=0) // SPID 0 is not legal. We use it for requesting root container creation only (no sp)
+        {
+            addIntToUri((char*)linkP, (uint32_t) spid);
+        }
+    }
+
+    LOGD("calling first callback %ld", (long int) callbackP);
+    callbackP(CONNECTING_SERVICE_ENABLER, ROOTPA_OK, NULL);
+
+    ret=openSeClientAndInit();
+    if(ROOTPA_OK!=ret)
+    {
+        callbackP(ERROR_STATE, ret, NULL);
+        workToDo=false;
+    }
+
+    if(tltDataP != NULL) // we are installing trustlet
+    {
+        ret=buildXmlTrustletInstallationRequest(&responseP, *tltDataP );
+        if(ROOTPA_OK!=ret || NULL==responseP)
+        {
+            if(ROOTPA_OK==ret) ret=ROOTPA_ERROR_XML;
+            callbackP(ERROR_STATE, ret, NULL);
+            workToDo=false;
+        }
+        else
+        {
+            addSlashToUri((char*) linkP);
+            addBytesToUri((char*) linkP, (uint8_t*) tltDataP->uuid.value, UUID_LENGTH, true);
+        }
+    }
+
+// begin recovery from factory reset 1
+    if(factoryResetAssumed() && relP != RELATION_INITIAL_DELETE && workToDo == true)
+    {
+        pendingLinkP=linkP;
+        pendingRelP=relP;
+        relP=RELATION_INITIAL_DELETE;
+        linkP=createBasicLink(suid);
+    }
+// end recovery from factory reset 1
+
+    while(workToDo)
+    {
+        LOGD("in loop link: %s\nrel: %s\ncommand: %s\nresponse: %s\n", (linkP==NULL)?"null":linkP,
+                                                                       (relP==NULL)?"null":relP,
+                                                                       (commandP==NULL)?"null":commandP,
+                                                                       (responseP==NULL)?"null":responseP);
+
+        if(NULL==relP)
+        {
+// begin recovery from factory reset 2
+            if(pendingLinkP!=NULL && pendingRelP!=NULL)
+            {
+                free((void*)linkP);
+                linkP=pendingLinkP;
+                relP=pendingRelP;
+                pendingLinkP=NULL;
+                pendingRelP=NULL;
+                workToDo=true;
+                continue;
+            }
+// end recovery from factory reset 2
+
+
+            callbackP(FINISHED_PROVISIONING, ROOTPA_OK, NULL); // this is the only place where we can be sure
+                                                         // SE does not want to send any more data to us
+                                                         // the other option would be to keep track on the
+                                                         // commands received from SE but since we want
+                                                         // SE to have option to execute also other commands
+                                                         // and also allow modification in provisioning sequence
+                                                         // without modifying RootPA we use this simpler way.
+            workToDo=false;
+        }
+        else if(strstr(relP, RELATION_SELF))  // do it again. So we need to restore pointer to previous stuff.
+        {
+            if(relP!=usedRelP && linkP!=usedLinkP && commandP!=usedCommandP)
+            {
+                cleanup((char**) &linkP, (char**) &relP, (char**) &commandP);
+                relP=usedRelP;
+                linkP=usedLinkP;
+                commandP=usedCommandP;
+            }
+        }
+        else
+        {
+            // store the current pointers to "used" pointers just before using them, the current ones will then be updated
+            // this is to prepare for the case where we receive RELATION_SELF as next relation.
+            usedLinkP=linkP;            // originally linkP
+            usedRelP=relP;              // originally NULL
+            usedCommandP=commandP;      // originally NULL
+
+            if(strstr(relP, RELATION_SYSTEMINFO))
+            {
+                osInfo_t osSpecificInfo;
+                int mcVersionTag=0;
+                mcVersionInfo_t mcVersion;
+
+#ifdef WIN32
+// TODO- remove the memory allocation from here and handle it properly on C# code
+
+                osSpecificInfo.brandP = (char*)calloc(64, sizeof(char));
+                osSpecificInfo.mnoP = (char*)calloc(64, sizeof(char));
+                osSpecificInfo.imeiEsnP = (char*)calloc(64, sizeof(char));
+                osSpecificInfo.manufacturerP = (char*)calloc(64, sizeof(char));
+                osSpecificInfo.hardwareP = (char*)calloc(64, sizeof(char));
+                osSpecificInfo.modelP = (char*)calloc(64, sizeof(char));
+                osSpecificInfo.versionP = (char*)calloc(64, sizeof(char));
+#endif
+                tmpRet=getSysInfoP(&osSpecificInfo);
+                if(tmpRet!=ROOTPA_OK) ret=tmpRet;
+
+                tmpRet=getVersionP(&mcVersionTag, &mcVersion);
+                if(tmpRet!=ROOTPA_OK) ret=tmpRet;
+
+                tmpRet=buildXmlSystemInfo(&responseP, mcVersionTag, &mcVersion, &osSpecificInfo);
+                if(tmpRet!=ROOTPA_OK) ret=tmpRet;
+
+                free(osSpecificInfo.imeiEsnP);
+                free(osSpecificInfo.mnoP);
+                free(osSpecificInfo.brandP);
+                free(osSpecificInfo.manufacturerP);
+                free(osSpecificInfo.hardwareP);
+                free(osSpecificInfo.modelP);
+                free(osSpecificInfo.versionP);
+
+                if(responseP!=NULL)
+                {
+                    tmpRet=httpPutAndReceiveCommand(responseP, &linkP, &relP, &commandP);
+                    if(tmpRet!=ROOTPA_OK) ret=tmpRet;
+                }
+                else if(ROOTPA_OK==ret)
+                {
+                    workToDo=false;
+                    ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+                }
+
+                if(ret!=ROOTPA_OK)
+                {
+                    LOGE("getSysInfoP, getVersionP or buildXmlSystemInfo or httpPutAndReceiveCommand returned an error %d", ret);
+                    callbackP(ERROR_STATE, ret, NULL);
+                    if(tmpRet!=ROOTPA_OK) workToDo=false; // if sending response succeeded, we rely on "relP" to tell whether we should continue or not
+                }
+            }
+            else if(strstr(relP, RELATION_INITIAL_DELETE))
+            {
+                ret=httpDeleteAndReceiveCommand(&linkP, &relP, &commandP);
+
+                if(ret!=ROOTPA_OK)
+                {
+                    LOGE("httpDeleteAndReceiveCommand returned an error %d", ret);
+                    callbackP(ERROR_STATE, ret, NULL);
+                    workToDo=false;
+                }
+            }
+            else if(strstr(relP, RELATION_INITIAL_POST))
+            {
+                // response may be NULL or trustlet installation request
+                ret=httpPostAndReceiveCommand(responseP, &linkP, &relP, &commandP);
+
+                if(ret!=ROOTPA_OK)
+                {
+                    LOGE("httpPostAndReceiveCommand returned an error %d", ret);
+                    callbackP(ERROR_STATE, ret, NULL);
+                    workToDo=false;
+                }
+            }
+            else if(strstr(relP, RELATION_RESULT))
+            {
+                setCallbackP(callbackP);
+                ret=handleXmlMessage(commandP, &responseP);
+                setCallbackP(NULL);
+
+                if(NULL==responseP)
+                {
+                    if(ROOTPA_OK==ret) ret=ROOTPA_ERROR_XML;
+                    // have to set these to NULL since we are not even trying to get them from SE now
+                    linkP=NULL;
+                    relP=NULL;
+                    commandP=NULL;
+                    LOGE("no responseP");
+                }
+                else
+                {
+                    // attempting to return response to SE even if there was something wrong in handleXmlMessage
+                    tmpRet=httpPostAndReceiveCommand(responseP, &linkP, &relP, &commandP);
+                    if(tmpRet!=ROOTPA_OK) ret=tmpRet;
+                }
+
+                if(ret!=ROOTPA_OK && ret!=ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE) // if container is not found, not sending error intent to SP.PA since it is possible that SE can recover.
+                {                                                                     // If it can not, it will return an error code anyway.
+                    LOGE("httpPostAndReceiveCommand or handleXmlMessage returned an error %d %d", ret, tmpRet);
+                    callbackP(ERROR_STATE, ret, NULL);
+                    if(tmpRet!=ROOTPA_OK) workToDo=false; // if sending response succeeded, we rely on "relP" to tell whether we should continue or not
+                }
+
+            }
+            else if(strstr(relP, RELATION_NEXT))
+            {
+                ret=httpGetAndReceiveCommand(&linkP, &relP, &commandP);
+                if(ret!=ROOTPA_OK)
+                {
+                    LOGE("httpGetAndReceiveCommand returned an error %d", ret);
+                    callbackP(ERROR_STATE, ret, NULL);
+                    workToDo=false;
+                }
+            }
+            else
+            {
+                LOGE("DO NOT UNDERSTAND REL %s", relP);
+                ret=ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+                callbackP(ERROR_STATE, ret, NULL);
+                workToDo=false;
+            }
+
+            LOGD("end of provisioning loop work to do: %d, responseP %ld", workToDo, (long int) responseP);
+        }
+
+        // last round cleaning in order to make sure both original and user pointers are released, but only once
+
+        if(!workToDo)
+        {
+            LOGD("no more work to do %ld - %ld %ld - %ld %ld - %ld", (long int) linkP, (long int) usedLinkP,
+                                                                     (long int) relP, (long int) usedRelP,
+                                                                     (long int) commandP, (long int) usedCommandP);
+            // final cleanup
+
+            // ensure that we do not clean up twice in case used pointers opint to the original one
+            if(linkP==usedLinkP) usedLinkP=NULL;
+            if(relP==usedRelP) usedRelP=NULL;
+            if(commandP==usedCommandP) usedCommandP=NULL;
+
+            cleanup((char**) &linkP, (char**) &relP, (char**) &commandP);
+        }
+
+        // free the used pointers since all the necessary pointers point to new direction.
+        // when relation is self we need to give the previous command again and so we keep the
+        // data
+
+        if(relP==NULL || strstr(relP, RELATION_SELF)==NULL)
+        {
+            cleanup((char**) &usedLinkP, (char**) &usedRelP, (char**) &usedCommandP);
+        }
+
+        // responseP can be freed at every round
+        free((void*)responseP);
+        responseP=NULL;
+
+    } // while
+    closeSeClientAndCleanup();
+
+    if(responseP!=NULL) {
+       free((void*)responseP);
+       responseP = NULL;
+    }
+    
+    if(linkP!=NULL){
+       free((void*)linkP);
+       linkP = NULL;
+    }
+    
+    if(ROOTPA_OK != ret)  LOGE("doProvisioningWithSe had some problems: %d",ret );
+    LOGD("<<doProvisioningWithSe ");
+    
+    return;
+}
+
+rootpaerror_t uploadTrustlet(uint8_t* containerDataP, uint32_t containerLength)
+{
+    if(callbackP_)
+    {
+        tltInfo_t tltInfo;
+        tltInfo.trustletP = containerDataP;
+        tltInfo.trustletSize = containerLength;
+        callbackP_(PROVISIONING_STATE_INSTALL_TRUSTLET, ROOTPA_OK, &tltInfo);
+        return ROOTPA_OK;
+    }
+    LOGE("uploadTrustlet, no callbackP_");
+    return ROOTPA_COMMAND_NOT_SUPPORTED;
+}
+
diff --git a/mobicore/rootpa/Code/Common/provisioningengine.h b/mobicore/rootpa/Code/Common/provisioningengine.h
new file mode 100644 (file)
index 0000000..a91f96c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PROVISIONINGENGINE_H
+#define PROVISIONINGENGINE_H
+
+#include <mcSpid.h>
+#include "rootpa.h"
+
+/**
+ * Enum definition for initial provisioning relations.
+ * Used while calling doProvisioningWithSe(..)
+ */
+typedef enum
+{
+       initialRel_POST    = 0,
+       initialRel_DELETE  = 1
+} initialRel_t;
+
+rootpaerror_t setInitialAddress(const char* addrP, uint32_t length);
+
+typedef rootpaerror_t (*GetVersionFunctionP) (int*, mcVersionInfo_t*);
+
+void doProvisioningWithSe(
+       mcSpid_t spid,
+       mcSuid_t suid,
+       CallbackFunctionP callbackP,
+       SystemInfoCallbackFunctionP getSysInfoP,
+       GetVersionFunctionP getVersionP,
+       initialRel_t initialRel,
+    trustletInstallationData_t* tltDataP);
+
+rootpaerror_t uploadTrustlet(uint8_t* containerDataP, uint32_t containerLength);
+#endif // PROVISIONINGENGINE_H
+
diff --git a/mobicore/rootpa/Code/Common/registry.c b/mobicore/rootpa/Code/Common/registry.c
new file mode 100644 (file)
index 0000000..4889e40
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <MobiCoreRegistry.h>
+#include "registry.h"
+
+// AuthToken
+int regWriteAuthToken(const AUTHTOKENCONTAINERP atP, uint32_t containerSize)
+{
+    return mcRegistryStoreAuthToken(atP, containerSize);
+}
+
+int regReadAuthToken(AUTHTOKENCONTAINERP* atP, uint32_t* containerSize)
+{
+    *containerSize = CONTAINER_BUFFER_SIZE; // this will be updated to actual size with the registry call
+    *atP=(AUTHTOKENCONTAINERP)malloc(CONTAINER_BUFFER_SIZE);
+    if(NULL==*atP) return MC_DRV_ERR_NO_FREE_MEMORY;
+    return mcRegistryReadAuthToken(*atP, containerSize);
+}
+
+int regDeleteAuthToken(void)
+{
+    return mcRegistryDeleteAuthToken();
+}
+
+// Root
+
+int regReadRoot(ROOTCONTAINERP* rootP, uint32_t* containerSize)
+{
+    *containerSize = CONTAINER_BUFFER_SIZE; // this will be updated to actual size with the registry call
+    *rootP=(ROOTCONTAINERP)malloc(CONTAINER_BUFFER_SIZE);
+    if(NULL==*rootP) return MC_DRV_ERR_NO_FREE_MEMORY;
+    return mcRegistryReadRoot(*rootP, containerSize);
+}
+
+
+int regWriteRoot(const ROOTCONTAINERP rootP, uint32_t containerSize)
+{
+    return mcRegistryStoreRoot(rootP, containerSize);
+}
+
+
+int regCleanupRoot(void)
+{
+    return mcRegistryCleanupRoot();
+}
+
+// sp
+
+int regReadSp(mcSpid_t spid, SPCONTAINERP* spP, uint32_t* containerSize)
+{
+    *containerSize = CONTAINER_BUFFER_SIZE; // this will be updated to actual size with the registry call
+    *spP= (SPCONTAINERP)malloc(CONTAINER_BUFFER_SIZE);
+    if(NULL==*spP) return MC_DRV_ERR_NO_FREE_MEMORY;
+    return mcRegistryReadSp(spid, *spP, containerSize);
+}
+
+int regWriteSp(mcSpid_t spid, const SPCONTAINERP spP, uint32_t containerSize)
+{
+    return mcRegistryStoreSp(spid, spP, containerSize);
+}
+
+int regCleanupSp(mcSpid_t spid)
+{
+    return mcRegistryCleanupSp(spid);
+}
+
+
+int regGetSpState(mcSpid_t spid, mcContainerState_t* stateP)
+{
+    int ret;
+    SPCONTAINERP spP=NULL;
+    uint32_t containerSize=0;
+    containerSize = CONTAINER_BUFFER_SIZE; // this will be updated to actual size with the registry call
+    ret=regReadSp(spid, &spP, &containerSize);
+    if(MC_DRV_OK==ret)
+    {
+        *stateP=spP->cont.attribs.state;
+    }
+    free(spP);
+    return ret;
+}
+
+
+// tlt
+
+int regReadTlt(const mcUuid_t* uuidP, TLTCONTAINERP* tltP, uint32_t* containerSize, mcSpid_t spid)
+{
+    *containerSize = CONTAINER_BUFFER_SIZE; // this will be update to actual size with the registry call
+    *tltP=(TLTCONTAINERP)malloc(CONTAINER_BUFFER_SIZE);
+    if(NULL==*tltP) return MC_DRV_ERR_NO_FREE_MEMORY;
+    return mcRegistryReadTrustletCon(uuidP, spid, *tltP, containerSize);
+}
+
+int regWriteTlt(const mcUuid_t* uuidP, const TLTCONTAINERP tltP, uint32_t containerSize, mcSpid_t spid)
+{
+    return mcRegistryStoreTrustletCon(uuidP, spid, tltP, containerSize);
+}
+
+int regCleanupTlt(const mcUuid_t* uuidP, mcSpid_t spid)
+{
+    return mcRegistryCleanupTrustlet(uuidP, spid);
+}
+
+int regStoreTA(mcSpid_t spid, const mcUuid_t* uuidP, const uint8_t* taBinary, uint32_t taBinLength)
+{
+       (void) uuidP;
+#ifdef WIN32
+       return MC_DRV_ERR_INVALID_OPERATION; // TODO-fix Currently the Windows version of mcRegistry does not support mcRegistryStoreTABlob
+#else
+    return mcRegistryStoreTABlob(spid, (void*) taBinary, taBinLength);
+#endif
+}
+
+int regGetTaState(mcSpid_t spid, const mcUuid_t* uuidP, mcContainerState_t* stateP)
+{
+    TLTCONTAINERP taP=NULL;
+    uint32_t containerSize=0;
+    containerSize = CONTAINER_BUFFER_SIZE; // this will be updated to actual size with the registry call
+    int ret=regReadTlt(uuidP, &taP, &containerSize, spid);
+    if(MC_DRV_OK==ret)
+    {
+        *stateP=taP->cont.common.attribs.state;
+    }
+    free(taP);
+    return ret;
+}
diff --git a/mobicore/rootpa/Code/Common/registry.h b/mobicore/rootpa/Code/Common/registry.h
new file mode 100644 (file)
index 0000000..546a830
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <mcContainer.h>
+
+#define CONTAINER_BUFFER_SIZE 4096
+
+// container sizes are and must be used for memory allocation only, since there is possibility to increase the buffer size these
+// are informative and RootPA should work fine also when the container sizes change after RootPA deployment
+#define SIZEOFAUTHTOKENCONTAINER (sizeof(mcSoAuthTokenCont_t))
+#define SIZEOFROOTCONTAINER (sizeof(mcSoRootCont_t))
+#define SIZEOFSPCONTAINER (sizeof(mcSoSpCont_t))
+#define SIZEOFTLTCONTAINER (sizeof(mcSoTltCont_2_1_t))
+
+typedef mcSoAuthTokenCont_t* AUTHTOKENCONTAINERP;
+typedef mcSoRootCont_t* ROOTCONTAINERP;
+typedef mcSoSpCont_t* SPCONTAINERP;
+typedef mcSoTltCont_t* TLTCONTAINERP;
+
+int regReadAuthToken(AUTHTOKENCONTAINERP* atP, uint32_t* containerSize);
+int regWriteAuthToken(const AUTHTOKENCONTAINERP atP, uint32_t containerSize);
+int regDeleteAuthToken(void);
+
+int regReadRoot(ROOTCONTAINERP* rootP, uint32_t* containerSize);
+int regWriteRoot(const ROOTCONTAINERP rootP, uint32_t containerSize);
+int regCleanupRoot(void);
+
+int regReadSp(mcSpid_t spid, SPCONTAINERP* spP, uint32_t* containerSize);
+int regWriteSp(mcSpid_t spid, const SPCONTAINERP spP, uint32_t containerSize);
+int regCleanupSp(mcSpid_t spid);
+
+int regGetSpState(mcSpid_t spid, mcContainerState_t* stateP);
+
+int regReadTlt(const mcUuid_t* uuidP, TLTCONTAINERP* tltP, uint32_t* containerSize, mcSpid_t spid);
+int regWriteTlt(const mcUuid_t* uuidP, const TLTCONTAINERP tltP, uint32_t containerSize, mcSpid_t spid);
+int regCleanupTlt(const mcUuid_t* uuidP, mcSpid_t spid);
+
+int regStoreTA(mcSpid_t spid, const mcUuid_t* uuidP, const uint8_t* taBinary, uint32_t taBinLength);
+int regGetTaState(mcSpid_t spid, const mcUuid_t* uuidP, mcContainerState_t* stateP);
\ No newline at end of file
diff --git a/mobicore/rootpa/Code/Common/seclient.c b/mobicore/rootpa/Code/Common/seclient.c
new file mode 100644 (file)
index 0000000..417f275
--- /dev/null
@@ -0,0 +1,861 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <wrapper.h>
+#include <time.h>
+#include <math.h>
+#ifdef TIZEN
+#include <string.h>
+#endif
+
+#include <curl/curl.h>
+
+#include "logging.h"
+#include "rootpaErrors.h"
+#include "seclient.h"
+#include "cacerts.h"
+
+#define HTTP_CODE_MOVED                 301
+#define HTTP_CODE_BAD_REQUEST           400
+#define HTTP_CODE_NOT_FOUND             404
+#define HTTP_CODE_METHOD_NOT_ALLOWED    405
+#define HTTP_CODE_NOT_ACCEPTABLE        406
+#define HTTP_CODE_REQUEST_TIMEOUT       408
+#define HTTP_CODE_CONFLICT              409
+#define HTTP_CODE_LENGTH_REQUIRED       411
+#define HTTP_CODE_TOO_LONG              414
+#define HTTP_CODE_UNSUPPORTED_MEDIA     415
+#define HTTP_CODE_INVALID_DATA          422
+#define HTTP_CODE_FAILED_DEPENDENCY     424
+#define HTTP_CODE_INTERNAL_ERROR        500
+#define HTTP_CODE_CMP_VERSION           501
+#define HTTP_CODE_SERVICE_UNAVAILABLE   503
+#define HTTP_CODE_HTTP_VERSION          505
+
+#ifdef __DEBUG
+#define NONEXISTENT_TEST_URL "http://10.255.255.253/"
+#endif
+
+#define CERT_PATH_MAX_LEN 256
+#define CECERT_FILENAME "cacert.pem"
+static char certificatePath_[CERT_PATH_MAX_LEN];
+static char certificateFilePath_[CERT_PATH_MAX_LEN];
+static long int SE_CONNECTION_DEFAULT_TIMEOUT=58L; // timeout after 58 seconds
+static int MAX_ATTEMPTS=30; //30x0.3 = 9 seconds
+#ifdef WIN32
+       static const DWORD SLEEPTIME_MS=300; // 0.3 seconds
+#else
+       static const struct timespec SLEEPTIME={0,300*1000*1000}; // 0.3 seconds
+#endif
+
+rootpaerror_t httpCommunicate(const char* const inputP, const char** linkP, const char** relP, const char** commandP, httpMethod_t method);
+
+#ifdef WIN32
+
+       char* strcasestr(char const *s, char const *find)
+       {
+               char* pos;
+               char* ret;
+               char* ls=_strdup(s);
+               char* lfind=_strdup(find);
+
+               ls=_strlwr(ls);
+               lfind=_strlwr(lfind);
+               pos = strstr(ls, lfind);
+               ret = pos == NULL ? NULL : (char *)(s + (pos-ls));
+               free(ls);
+               free(lfind);
+               return ret;
+       }
+
+
+#endif
+
+#ifdef TIZEN
+#include <sys/types.h>
+#include <string.h>
+#include <ctype.h>
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+char *
+strcasestr(s, find)
+       const char *s, *find;
+{
+       char c, sc;
+       size_t len;
+
+       if ((c = *find++) != 0) {
+               c = tolower((unsigned char)c);
+               len = strlen(find);
+               do {
+                       do {
+                               if ((sc = *s++) == 0)
+                                       return (NULL);
+                       } while ((char)tolower((unsigned char)sc) != c);
+               } while (strncasecmp(s, find, len) != 0);
+               s--;
+       }
+       return ((char *)s);
+}
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+       register char *d = dst;
+       register const char *s = src;
+       register size_t n = siz;
+       size_t dlen;
+
+       /* Find the end of dst and adjust bytes left but don't go past end */
+       while (n-- != 0 && *d != '\0')
+               d++;
+       dlen = d - dst;
+       n = siz - dlen;
+
+       if (n == 0)
+               return(dlen + strlen(s));
+       while (*s != '\0') {
+               if (n != 1) {
+                       *d++ = *s;
+                       n--;
+               }
+               s++;
+       }
+       *d = '\0';
+
+       return(dlen + (s - src));       /* count does not include NUL */
+}
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+       register char *d = dst;
+       register const char *s = src;
+       register size_t n = siz;
+
+       /* Copy as many bytes as will fit */
+       if (n != 0 && --n != 0) {
+               do {
+                       if ((*d++ = *s++) == 0)
+                               break;
+               } while (--n != 0);
+       }
+
+       /* Not enough room in dst, add NUL and traverse rest of src */
+       if (n == 0) {
+               if (siz != 0)
+                       *d = '\0';              /* NUL-terminate dst */
+               while (*s++)
+                       ;
+       }
+
+       return(s - src - 1);    /* count does not include NUL */
+}
+#endif
+
+rootpaerror_t httpPostAndReceiveCommand(const char* const inputP, const char** linkP, const char** relP, const char** commandP)
+{
+    LOGD("httpPostAndReceiveCommand %ld", (long int) inputP);
+    return httpCommunicate(inputP, linkP, relP, commandP, httpMethod_POST);
+}
+
+rootpaerror_t httpPutAndReceiveCommand(const char* const inputP, const char** linkP, const char** relP, const char** commandP)
+{
+    LOGD("httpPutAndReceiveCommand %ld", (long int) inputP);
+    if(NULL==inputP)
+    {
+        return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+    LOGD("%s", inputP);
+    return httpCommunicate(inputP, linkP, relP, commandP, httpMethod_PUT);
+}
+
+
+rootpaerror_t httpGetAndReceiveCommand(const char** linkP, const char** relP, const char** commandP)
+{
+    LOGD("httpGetAndReceiveCommand");
+    return httpCommunicate(NULL, linkP, relP, commandP, httpMethod_GET);
+}
+
+rootpaerror_t httpDeleteAndReceiveCommand(const char** linkP, const char** relP, const char** commandP)
+{
+    LOGD("httpDeleteAndReceiveCommand");
+    return httpCommunicate(NULL, linkP, relP, commandP, httpMethod_DELETE);
+}
+
+
+typedef struct
+{
+    char*  memoryP;
+    size_t    size;
+} MemoryStruct;
+
+
+typedef struct
+{
+    char*  linkP;
+    size_t    linkSize;
+    char*  relP;
+    size_t    relSize;
+} HeaderStruct;
+
+typedef struct
+{
+    const char*      responseP;
+    size_t           size;
+    uint32_t         offset;
+} ResponseStruct;
+
+
+static size_t readResponseCallback(void *ptr, size_t size, size_t nmemb, void *userp)
+{
+    size_t totalSize=nmemb*size;
+    size_t readSize;
+    ResponseStruct* rspP=(ResponseStruct*) userp;
+    LOGD(">>readResponseCallback %d %d %d\n", (int) totalSize, (int) rspP->size, rspP->offset);
+
+    if(rspP->offset>=rspP->size) return 0;
+
+    if(totalSize<((rspP->size)))
+    {
+        readSize=totalSize;
+    }
+    else
+    {
+        readSize=rspP->size;
+    }
+
+    memcpy(ptr, (rspP->responseP+rspP->offset), readSize);
+
+    rspP->offset+=readSize;
+
+    LOGD("<<readResponseCallback %d %d %d\n", (int) readSize, (int) rspP->size, rspP->offset);
+    return readSize;
+}
+
+static size_t writeMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+    size_t realsize = size * nmemb;
+    MemoryStruct* mem = (MemoryStruct *)userp;
+    mem->memoryP = (char*)realloc(mem->memoryP, mem->size + realsize + 1);
+    if (mem->memoryP == NULL) {
+        /* out of memory! */
+        LOGE("not enough memory (realloc returned NULL)\n");
+        return 0; // returning anything different from what was passed to this function indicates an error
+    }
+
+    memcpy(&(mem->memoryP[mem->size]), contents, realsize);
+    mem->size += realsize;
+    mem->memoryP[mem->size] = 0;
+
+    return realsize;
+}
+
+#ifdef __DEBUG
+int debug_function (CURL * curl_handle, curl_infotype info, char* debugMessageP, size_t debugMessageSize, void * extrabufferP)
+{
+    if(debugMessageP!=NULL && debugMessageSize!=0)
+    {
+        char* msgP=(char*)malloc(debugMessageSize+1);
+        if(NULL==msgP)return 0;
+        memcpy(msgP, debugMessageP, debugMessageSize);
+        msgP[debugMessageSize]=0;
+        LOGD("curl: %d %s",info, msgP);
+        free(msgP);
+    }
+    else
+    {
+        LOGD("curl: no debug msg %d %d", info, (int) debugMessageSize);
+    }
+    return 0;
+}
+#endif
+
+bool copyHeader(void *contents, size_t length, char** headerP)
+{
+    *headerP = (char *)malloc(length + 1);
+    if (*headerP == NULL) {
+        /* out of memory! */
+        LOGE("not enough memory (malloc returned NULL)\n");
+        return false;
+    }
+
+    memcpy(*headerP , contents, length);
+    (*headerP)[length] = 0;
+    return true;
+}
+
+//
+// The header format is as follow
+// Link <https://se.cgbe.trustonic.com:8443/activity/00000000-4455-6677-8899-aabbccddeeff>;rel="http://10.0.2.2/relation/system_info"
+// parse out uri's specified in Link and rel
+//
+bool updateLinkAndRel(HeaderStruct* memP, void* ptr)
+{
+    char* startP=NULL;
+    char* endP=NULL;
+
+    // first update link
+
+    startP=strcasestr((char*) ptr, "Link");
+    if(NULL==startP) return false;
+
+    startP=strstr(startP,"<");
+    if(NULL==startP) return false;
+    startP++;
+
+    endP=strstr(startP,">");
+    if(NULL==endP) return false;
+
+    memP->linkSize=endP-startP;
+    if(copyHeader(startP, memP->linkSize, &(memP->linkP))==false)
+    {
+        return false;
+    }
+
+    // then update rel, we will be successful even if it is not found
+
+    startP=strcasestr(endP, "rel=");
+    if(NULL==startP)
+    {
+        return true;
+    }
+    startP+=5; // sizeof "rel="
+
+    endP=strstr(startP,"\"");
+    if(NULL==endP)
+    {
+        return true;
+    }
+    memP->relSize=endP-startP;
+    if(copyHeader(startP, memP->relSize, &(memP->relP))==false)
+    {
+        LOGE("could not copy rel, but since we are this far, continuing anyway");
+    }
+
+    return true;
+}
+
+static size_t writeHeaderCallback( void *ptr, size_t size, size_t nmemb, void *userp)
+{
+    size_t realSize = size * nmemb;
+    HeaderStruct* memP = (HeaderStruct *)userp;
+
+    if(realSize>=sizeof("Link:") && memcmp(ptr, "Link:", sizeof("Link:")-1)==0)
+    {
+        if(updateLinkAndRel(memP, ptr)==false)
+        {
+            LOGE("Problems in updating Link and rel");
+        }
+    }
+
+    return realSize;
+}
+
+uint32_t shorter(uint32_t first, uint32_t second)
+{
+    return (first>second?second:first);
+}
+
+void setCertPath(const char* localPathP, const char* certPathP)
+{
+    memset(certificatePath_, 0, CERT_PATH_MAX_LEN);
+    memset(certificateFilePath_, 0, CERT_PATH_MAX_LEN);
+
+    if (certPathP!=NULL && (strlen(certPathP)+1)<CERT_PATH_MAX_LEN)
+    {
+#ifdef TIZEN
+        strlcpy(certificatePath_, certPathP, sizeof(certificatePath_));
+#else
+/* Fix coverity */
+//        strncpy(certificatePath_, certPathP, sizeof(certificatePath_));
+        strncpy(certificatePath_, certPathP, sizeof(certificatePath_)-1);
+#endif
+    }
+
+    if (localPathP!=NULL && (strlen(localPathP)+1+sizeof(CECERT_FILENAME))<CERT_PATH_MAX_LEN)
+    {
+#ifdef TIZEN
+        strlcpy(certificateFilePath_, localPathP,sizeof(certificateFilePath_));
+        strlcat(certificateFilePath_, "/",sizeof(certificateFilePath_));
+#else
+/* Fix coverity */
+//        strncpy(certificateFilePath_, localPathP,sizeof(certificateFilePath_));
+//        strncat(certificateFilePath_, "/",sizeof(certificateFilePath_));
+        strncpy(certificateFilePath_, localPathP,sizeof(certificateFilePath_)-1);
+        strncat(certificateFilePath_, "/",strlen("/"));
+#endif
+    }
+#ifdef TIZEN
+    strlcat(certificateFilePath_, CECERT_FILENAME,sizeof(certificateFilePath_));
+#else
+//    strncat(certificateFilePath_, CECERT_FILENAME,sizeof(certificateFilePath_));
+    strncat(certificateFilePath_, CECERT_FILENAME,strlen(CECERT_FILENAME));
+#endif
+}
+//
+// TODO-refactor: saveCertFile is duplicate from saveFile in xmlMessageHandler.c, move these to common place
+//
+void saveCertFile(char* filePath, char* fileContent)
+{
+    FILE* fh;
+    LOGD(">>saveCertFile %s", filePath);
+    if ((fh = fopen(filePath, "w")) != NULL) // recreating the file every time, this is not the most efficient way, but ensures
+       {                                        // the file is updated in case rootpa and the required content is updated
+        fprintf(fh, "%s", fileContent);
+        fclose(fh);
+       }
+    else
+    {
+        LOGE("saveCertFile no handle %s", filePath);
+    }
+    LOGD("<<saveCertFile");
+}
+
+bool setBasicOpt(CURL* curl_handle, MemoryStruct* chunkP, HeaderStruct* headerChunkP, const char* linkP,  struct curl_slist* headerListP)
+{
+    long int se_connection_timeout=SE_CONNECTION_DEFAULT_TIMEOUT;
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_URL, linkP)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_URL failed");
+        return false;
+    }
+
+    /* reading response to memory instead of file */
+    if(curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeMemoryCallback)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_WRITEFUNCTION failed");
+        return false;
+    }
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, writeHeaderCallback)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_HEADERFUNCTION failed");
+        return false;
+    }
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) chunkP)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_WRITEDATA failed");
+        return false;
+    }
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) headerChunkP)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_WRITEHEADER failed");
+        return false;
+    }
+
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headerListP)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_HTTPHEADER failed");
+        return false;
+    }
+
+    /* some servers don't like requests that are made without a user-agent
+       field, so we provide one */
+    if(curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "rpa/1.0")!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_USERAGENT failed");
+        return false;
+    }
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_USERAGENT failed");
+        return false;
+    }
+
+
+    saveCertFile(certificateFilePath_, CA_CERTIFICATES);
+
+    LOGD("curl_easy_setopt CURLOPT_CAINFO %s", certificateFilePath_);
+    if(curl_easy_setopt(curl_handle, CURLOPT_CAINFO,  certificateFilePath_)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_CAINFO failed");
+        return false;
+    }
+
+    LOGD("curl_easy_setopt CURLOPT_CAPATH %s", certificatePath_);
+    if(curl_easy_setopt(curl_handle, CURLOPT_CAPATH,  certificatePath_)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_CAPATH failed");
+        return false;
+    }
+
+#ifdef __DEBUG
+    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
+    curl_easy_setopt(curl_handle, CURLOPT_DEBUGFUNCTION, debug_function);
+
+    if(strncmp(linkP, NONEXISTENT_TEST_URL, shorter(strlen(NONEXISTENT_TEST_URL), strlen(linkP)))==0)
+    {
+        se_connection_timeout=3L; // reducing the connection timeout for testing purposes
+        MAX_ATTEMPTS=1; // this is for testint code, we are using nonexitent url here so no unncessary attempts
+        LOGD("setBasicOpt timeout set to %ld", se_connection_timeout);
+    }
+#endif
+
+    if(curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, se_connection_timeout)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_TIMEOUT failed");
+        return false;
+    }
+
+/** libcurl uses the http_proxy and https_proxy environment variables for proxy settings.
+    That variable is set in the OS specific wrapper. These are left here in order to make
+    this comment earier to be found in searches.
+
+    curl_easy_setopt(curl_handle,CURLOPT_PROXY, "http://proxyaddress");
+    curl_easy_setopt(curl_handle,CURLOPT_PROXYPORT, "read_proxy_port");
+    curl_easy_setopt(curl_handle,CURLOPT_PROXYUSERNAME, "read_proxy_username");
+    curl_easy_setopt(curl_handle,CURLOPT_PROXYPASSWORD, "read_proxy_password");
+*/
+
+    return true;
+}
+
+
+
+bool setPutOpt(CURL* curl_handle, ResponseStruct* responseChunk)
+{
+    long chunkSize=responseChunk->size;
+    LOGD(">>setPutOpt");
+    if (curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, readResponseCallback)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_READFUNCTION failed");
+        return false;
+    }
+
+    if (curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1L)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_UPLOAD failed");
+        return false;
+    }
+
+    if (curl_easy_setopt(curl_handle, CURLOPT_PUT, 1L)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_PUT failed");
+        return false;
+    }
+
+    if (curl_easy_setopt(curl_handle, CURLOPT_READDATA, responseChunk)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_READDATA failed");
+        return false;
+    }
+
+
+    if (curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE, chunkSize)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_INFILESIZE_LARGE failed");
+        return false;
+    }
+
+    LOGD("<<setPutOpt");
+    return true;
+}
+
+bool setPostOpt(CURL* curl_handle, const char* inputP)
+{
+    LOGD(">>setPostOpt %ld %d", (long int) inputP, inputP?(int)strlen(inputP):0);
+
+    if (curl_easy_setopt(curl_handle, CURLOPT_POST, 1L)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_POST failed");
+        return false;
+    }
+
+    if(NULL==inputP)
+    {
+        if (curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, 0L)!=CURLE_OK)
+        {
+            LOGE("curl_easy_setopt CURLOPT_POSTFIELDSIZE failed");
+            return false;
+        }
+    }
+
+    if (curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void*) inputP)!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_POSTFIELDS failed");
+        return false;
+    }
+
+    LOGD("<<setPostOpt");
+    return true;
+}
+
+bool setDeleteOpt(CURL* curl_handle, const char* inputP)
+{
+       (void) inputP;
+    LOGD(">>setDeleteOpt %s", inputP);
+    if (curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "DELETE")!=CURLE_OK)
+    {
+        LOGE("curl_easy_setopt CURLOPT_CUSTOMREQUEST failed");
+        return false;
+    }
+
+    LOGD("<<setDeleteOpt");
+    return true;
+}
+
+
+CURL* curl_handle_=NULL;
+
+rootpaerror_t openSeClientAndInit()
+{
+    if(curl_global_init(CURL_GLOBAL_ALL)!=CURLE_OK)
+    {
+        LOGE("curl_global_init failed");
+        return ROOTPA_ERROR_NETWORK;
+    }
+    curl_handle_=curl_easy_init();
+    if(NULL==curl_handle_)
+    {
+        LOGE("curl_easy_init failed");
+        return ROOTPA_ERROR_NETWORK;
+    }
+
+    return ROOTPA_OK;
+}
+
+void closeSeClientAndCleanup()
+{
+    if(curl_handle_)
+    {
+        curl_easy_cleanup(curl_handle_);
+        curl_handle_=NULL;
+    }
+    curl_global_cleanup();
+}
+
+rootpaerror_t httpCommunicate(const char * const inputP, const char** linkP, const char** relP, const char** commandP, httpMethod_t method)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    long int curlRet=CURLE_COULDNT_CONNECT;
+    long int http_code = 0;
+    int attempts=0;
+    struct curl_slist* httpHeaderP = NULL;
+    time_t begintime=0;
+    time_t endtime=0;
+    int timediff=0;
+
+    ResponseStruct responseChunk;
+    MemoryStruct chunk;
+    HeaderStruct headerChunk;
+    headerChunk.linkSize = 0;
+    headerChunk.relSize = 0;
+    headerChunk.linkP = NULL;
+    headerChunk.relP = NULL;
+
+    LOGD(">>httpCommunicate");
+    if(NULL==linkP || NULL==relP || NULL==commandP || NULL==*linkP)
+    {
+        return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+    LOGD("url %s", *linkP);
+    *commandP=NULL;
+    *relP=NULL;
+
+    chunk.size = 0;    /* no data at this point */
+    chunk.memoryP = (char *)malloc(1);  /* will be grown as needed by the realloc above */
+    if(NULL==chunk.memoryP)
+    {
+        return ROOTPA_ERROR_OUT_OF_MEMORY;
+    }
+    chunk.memoryP[0]=0;
+
+    LOGD("HTTP method %d", method);
+
+    //Process HTTP methods
+       if(method == httpMethod_PUT)
+       {
+               responseChunk.responseP=inputP;
+               responseChunk.size=strlen(responseChunk.responseP);
+               responseChunk.offset=0;
+               if(setPutOpt(curl_handle_, &responseChunk)==false)
+               {
+                       LOGE("setPutOpt failed");
+                       free(chunk.memoryP);
+                       return ROOTPA_ERROR_NETWORK;
+               }
+       }
+       else if(method == httpMethod_POST)
+       {
+               if (setPostOpt(curl_handle_, inputP)==false)
+               {
+                       LOGE("setPostOpt failed");
+                       free(chunk.memoryP);
+                       return ROOTPA_ERROR_NETWORK;
+               }
+       }
+       else if(method == httpMethod_DELETE)
+       {
+           LOGD("DELETE method. Calling setDeleteOpt..");
+               if (setDeleteOpt(curl_handle_, inputP)==false)
+               {
+                       LOGE("setDeleteOpt failed");
+                       free(chunk.memoryP);
+                       return ROOTPA_ERROR_NETWORK;
+               }
+       }
+       else
+       {
+               if(method != httpMethod_GET)
+               {
+               LOGE("Unsupported HTTP method");
+               free(chunk.memoryP);
+               return ROOTPA_ERROR_NETWORK;
+               }
+       }
+
+    /* disable Expect: 100-continue since it creates problems with some proxies, it is only related to post but we do it here for simplicity */
+    httpHeaderP = curl_slist_append(httpHeaderP, "Expect:");
+    httpHeaderP = curl_slist_append(httpHeaderP, "Content-Type: application/vnd.mcorecm+xml;v=1.0");
+    httpHeaderP = curl_slist_append(httpHeaderP, "Accept: application/vnd.mcorecm+xml;v=1.0");
+    if(setBasicOpt(curl_handle_, &chunk, &headerChunk, *linkP, httpHeaderP)==false)
+    {
+        LOGE("setBasicOpt failed");
+        free(chunk.memoryP);
+        return ROOTPA_ERROR_NETWORK;
+    }
+
+    begintime=time(NULL);
+    while(curlRet!=CURLE_OK && attempts++ < MAX_ATTEMPTS)
+    {
+        curlRet=curl_easy_perform(curl_handle_);
+        LOGD("curl_easy_perform %ld %d", curlRet, attempts );
+        if(CURLE_OK==curlRet) break;
+#ifdef WIN32
+               Sleep(SLEEPTIME_MS);
+#else
+        nanosleep(&SLEEPTIME,NULL);
+#endif
+        endtime=time(NULL);
+        timediff=(int)ceil(difftime(endtime, begintime));
+        LOGD("timediff (ceil) %d", timediff);
+        if(timediff>(SE_CONNECTION_DEFAULT_TIMEOUT/2))
+        {
+            LOGE("No connection to SE. Exiting retry loop for curl_easy_perform due to timeout %d", timediff);
+            break;
+        }
+    }
+
+    curl_easy_getinfo (curl_handle_, CURLINFO_RESPONSE_CODE, &http_code);
+    if(curlRet!=CURLE_OK)
+    {
+        LOGE("curl_easy_perform failed %ld", curlRet);
+        free(chunk.memoryP);
+        free(headerChunk.linkP);
+        free(headerChunk.relP);
+        curl_easy_reset(curl_handle_);
+        return ROOTPA_ERROR_NETWORK;
+    }
+
+    LOGD("http return code from SE %ld", (long int) http_code);
+    if ((200 <= http_code &&  http_code < 300))
+    {
+        ret=ROOTPA_OK;
+    }
+    else if (HTTP_CODE_BAD_REQUEST == http_code ||
+             HTTP_CODE_METHOD_NOT_ALLOWED == http_code ||
+             HTTP_CODE_NOT_ACCEPTABLE == http_code ||
+             HTTP_CODE_CONFLICT == http_code ||
+             HTTP_CODE_LENGTH_REQUIRED == http_code ||
+             HTTP_CODE_TOO_LONG == http_code ||
+             HTTP_CODE_UNSUPPORTED_MEDIA == http_code ||
+             HTTP_CODE_INVALID_DATA == http_code ||
+             HTTP_CODE_INTERNAL_ERROR == http_code ||
+             HTTP_CODE_HTTP_VERSION == http_code)
+    {
+        LOGE("SE returned http error %ld", (long int) http_code);
+        ret=ROOTPA_ERROR_INTERNAL;
+    }
+    else if(HTTP_CODE_MOVED == http_code ||  // new URL would be in Location: header but RootPA does not support in currently (unless libcurl supports it transparently)
+            HTTP_CODE_REQUEST_TIMEOUT == http_code  ||
+            HTTP_CODE_SERVICE_UNAVAILABLE == http_code)
+    {
+        LOGE("SE returned http error %ld", (long int) http_code);
+        ret=ROOTPA_ERROR_NETWORK;
+    }
+    else if (HTTP_CODE_CMP_VERSION == http_code)
+    {
+        LOGE("SE returned http error %ld", (long int) http_code);
+        ret=ROOTPA_ERROR_SE_CMP_VERSION;
+    }
+    else if (HTTP_CODE_FAILED_DEPENDENCY == http_code)
+    {
+        LOGE("SE returned http error %ld", (long int) http_code);
+        ret=ROOTPA_ERROR_SE_PRECONDITION_NOT_MET;
+    }
+    else if (HTTP_CODE_NOT_FOUND == http_code)
+    {
+        LOGE("SE returned http error %ld", (long int) http_code);
+        ret=ROOTPA_ERROR_ILLEGAL_ARGUMENT; // since the arguments (spid, in some cases uuid) for the URL are received from the client,
+                                           // this can be returned. It is also possible that suid is wrong (corrupted in device or info
+                                           // from device binding missing from SE, but we can not detect that easily.
+    }
+    else
+    {
+        LOGE("unexpected http return code from SE %ld", (long int)http_code);
+        ret=ROOTPA_ERROR_NETWORK;
+    }
+
+    /* cleanup curl stuff */
+
+    *commandP=chunk.memoryP;  // this needs to be freed by client
+    *linkP=headerChunk.linkP; // this needs to be freed by client
+    *relP=headerChunk.relP;   // this needs to be freed by client
+    if (httpHeaderP) curl_slist_free_all(httpHeaderP); // since we disabled some headers
+
+    curl_easy_reset(curl_handle_);
+    LOGD("%lu bytes retrieved\n", (long)chunk.size);
+
+    LOGD("<<httpCommunicate %d %ld %ld", (int) ret, (long int) http_code, (long int) curlRet);
+    return ret;
+}
+
diff --git a/mobicore/rootpa/Code/Common/seclient.h b/mobicore/rootpa/Code/Common/seclient.h
new file mode 100644 (file)
index 0000000..88e0ab5
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SECLIENT_H
+#define SECLIENT_H
+
+
+typedef enum
+{
+       httpMethod_GET     = 0,   /* HTTP GET method */
+       httpMethod_POST    = 1,   /* HTTP POST method */
+       httpMethod_PUT     = 2,   /* HTTP PUT method */
+       httpMethod_DELETE  = 3    /* HTTP DELETE method */
+} httpMethod_t;
+
+/**
+    @param linkP note that client has to free the memory from *linkP after using it
+    @param relP note that client has to free he memory from *relP after using it
+    @param commandP note that client has to free he memory from *commandP after using it
+
+    @return ROOTPA_OK on success. In case of an error *relP and *commandP are set to NULL;
+            linkP is not change but the original link remains.
+*/
+
+typedef rootpaerror_t (*SeclientFuntionP)(const char* const inputP, const char** linkP, const char** relP, const char** commandP);
+
+rootpaerror_t openSeClientAndInit();
+void closeSeClientAndCleanup();
+
+rootpaerror_t httpGetAndReceiveCommand(const char** linkP, const char** relP, const char** commandP);
+rootpaerror_t httpPostAndReceiveCommand(const char* const inputP, const char** linkP, const char** relP, const char** commandP);
+rootpaerror_t httpPutAndReceiveCommand(const char* const inputP, const char** linkP, const char** relP, const char** commandP);
+rootpaerror_t httpDeleteAndReceiveCommand(const char** linkP, const char** relP, const char** commandP);
+
+void setCertPath(const char* localPathP, const char* certPathP);
+
+
+#endif //SECLIENT_H
diff --git a/mobicore/rootpa/Code/Common/tools.h b/mobicore/rootpa/Code/Common/tools.h
new file mode 100644 (file)
index 0000000..8452850
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OWNTOOLS_H
+#define OWNTOOLS_H
+
+#ifdef WIN32
+
+#include <windows.h>
+
+#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))
+
+#else
+
+#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))
+
+#endif
+
+#endif // OWNTOOLS_H
diff --git a/mobicore/rootpa/Code/Common/trustletchannel.c b/mobicore/rootpa/Code/Common/trustletchannel.c
new file mode 100644 (file)
index 0000000..1d1e60f
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#ifdef WIN32
+       #include <cstring>
+       #include <sys/stat.h>
+#endif
+#include <wrapper.h>
+#include <stdlib.h>
+#include <TlCm/tlCmUuid.h>
+#include "tools.h"
+#include "logging.h"
+#include "trustletchannel.h"
+
+
+/* keep this in global variable with file scope so that we can easily start
+start using other than default device id if need arises */
+
+static uint32_t tltChannelDeviceId=MC_DEVICE_ID_DEFAULT;
+
+#ifdef WIN32
+
+#define MAX_TL_FILENAME 1024
+
+/**
+Since Windows version of "mcDaemon" does not access registry, this function is used to load system TA and open session to it.
+*/
+mcResult_t OpenSysTaFromRegistry(
+               mcSessionHandle_t * session,
+               const mcUuid_t * uuid,
+               uint8_t  * tci,
+               uint32_t   tciLen)
+  {
+
+
+    size_t      taSize;
+    int         result;
+    struct stat fstat;
+    mcResult_t  status = MC_DRV_ERR_UNKNOWN;
+    uint8_t *   taBlob;
+    int lastErr;
+
+
+    // get registry path
+    // TODO-2013-07-17-jearig01 import registry from global variable
+
+       char registryPath[MAX_TL_FILENAME] = "C:\\Windows\\tbaseregistry\\";
+       char trustedAppPath[MAX_TL_FILENAME];
+       char hx[MAX_TL_FILENAME];
+
+        for (size_t i = 0; i < sizeof(*uuid); i++) {
+        sprintf(&hx[i * 2], "%02x", ((uint8_t *)uuid)[i]);
+    }
+
+        snprintf(trustedAppPath, sizeof(trustedAppPath), "%s%s%s", registryPath,hx, ".tlbin");
+
+        printf("app path--> %s\n",trustedAppPath);
+     printf("registryPath path--> %s\n",registryPath);
+        printf("hx--> %s\n",hx);
+
+    //check file
+    result = stat(trustedAppPath, &fstat);
+       if (result!=0) return  MC_DRV_ERR_TRUSTLET_NOT_FOUND;
+    taSize = fstat.st_size;
+
+    // import file in a blob
+    FILE *infile = fopen(trustedAppPath, "rb");
+
+    if (infile == NULL) return MC_DRV_ERR_TRUSTLET_NOT_FOUND;
+
+    taBlob = (uint8_t *) malloc(taSize);
+       if (taBlob == NULL)
+    {
+      fclose(infile);
+      return MC_DRV_ERR_NO_FREE_MEMORY;
+    }
+
+    result = fread (taBlob, 1, taSize, infile);
+
+       printf("FREAD--> %d - %d\n",result, taSize);
+    if (result == taSize)
+    {
+      // Call OpenTrustlet
+               printf("app path--> %d - %d\n",tciLen, taSize);
+      status = mcOpenTrustlet(session, 0, taBlob, taSize, tci, tciLen);
+    }
+
+    // free blobs, necessary data are supposed to have been sent to SWd and are now useless in NWd
+    fclose(infile);
+    free(taBlob);
+
+    return status;
+  }
+#endif
+
+/*
+Open session to content management trustlet and allocate enough memory for communication
+*/
+CMTHANDLE tltChannelOpen(int sizeOfWsmBuffer,  mcResult_t* result)
+{
+    const mcUuid_t      UUID = TL_CM_UUID;
+    return taChannelOpen(sizeOfWsmBuffer, result, &UUID, NULL, 0,0);
+}
+
+
+/*
+*/
+CMTHANDLE taChannelOpen(int sizeOfWsmBuffer,  mcResult_t* result, const mcUuid_t* uuidP, uint8_t* taBinaryP, uint32_t taLength, mcSpid_t spid)
+{
+    CMTHANDLE           handle = (CMTHANDLE)malloc(sizeof(CMTSTRUCT));
+
+    if (unlikely( NULL==handle ))
+    {
+        *result=MC_DRV_ERR_NO_FREE_MEMORY;
+        return NULL;
+    }
+
+    memset(handle,0,sizeof(CMTSTRUCT));
+
+    *result = mcOpenDevice(tltChannelDeviceId);
+
+    if (MC_DRV_OK != *result)
+    {
+      LOGE("taChannelOpen: Unable to open device, error: %d", *result);
+      free(handle);
+
+      return NULL;
+    }
+
+
+    *result = mcMallocWsm(tltChannelDeviceId, 0, sizeOfWsmBuffer, &handle->wsmP, 0);
+    if (MC_DRV_OK != *result)
+    {
+        LOGE("taChannelOpen: Allocation of CMP WSM failed, error: %d", *result);
+        mcCloseDevice(tltChannelDeviceId);
+        free(handle);
+        return NULL;
+    }
+
+    if(taBinaryP!=NULL && taLength!=0)
+    {
+        *result = mcOpenTrustlet(&handle->session, spid, taBinaryP, taLength, handle->wsmP,(uint32_t)sizeOfWsmBuffer);
+    }
+    else
+    {
+#ifdef WIN32
+        *result = OpenSysTaFromRegistry(&handle->session,uuidP,handle->wsmP,(uint32_t)sizeOfWsmBuffer);
+#else
+        *result = mcOpenSession(&handle->session,uuidP, handle->wsmP,(uint32_t)sizeOfWsmBuffer);
+#endif
+    }
+
+    if (MC_DRV_OK != *result)
+    {
+        LOGE("taChannelOpen: Open session failed, error: %d", *result);
+        mcFreeWsm(tltChannelDeviceId,handle->wsmP);
+        mcCloseDevice(tltChannelDeviceId);
+        free(handle);
+        return NULL;
+    }
+    return handle;
+}
+
+
+/*
+Close the communication channel and free resources
+*/
+void tltChannelClose(CMTHANDLE handle){
+    mcResult_t          result;
+
+    if (!bad_read_ptr(handle,sizeof(CMTSTRUCT)))
+    {
+        result = mcCloseSession(&handle->session);
+        if (MC_DRV_OK != result)
+        {
+        LOGE("tltChannelClose: Closing session failed:, error: %d", result);
+        }
+
+        if (NULL!=handle->wsmP) mcFreeWsm(tltChannelDeviceId, handle->wsmP);
+
+        result = mcCloseDevice(tltChannelDeviceId);
+        if (MC_DRV_OK != result)
+        {
+            LOGE("tltChannelClose: Closing MobiCore device failed, error: %d", result);
+        }
+        free(handle);
+    }
+}
+
+/*
+Initiate transfer of the data between NWD and SWD. The actual data needs to be copied to wsmP beforehand
+(and from it afterwards in case of response)
+*/
+bool tltChannelTransmit(CMTHANDLE handle, int timeout){
+    if (unlikely(bad_write_ptr(handle,sizeof(CMTSTRUCT)))) return false;
+
+    // Send CMP message to content management trustlet.
+
+    handle->lasterror = mcNotify(&handle->session);
+
+    if (unlikely( MC_DRV_OK!=handle->lasterror ))
+    {
+        LOGE("tltChannelTransmit: mcNotify failed, error: %d",handle->lasterror);
+        return false;
+    }
+
+  // Wait for trustlet response.
+
+    handle->lasterror = mcWaitNotification(&handle->session, timeout);
+
+    if (unlikely( MC_DRV_OK!=handle->lasterror ))
+    {
+        LOGE("tltChannelTransmit: Wait for response notification failed, error: %d", handle->lasterror);
+        return false;
+    }
+    return true;
+}
diff --git a/mobicore/rootpa/Code/Common/trustletchannel.h b/mobicore/rootpa/Code/Common/trustletchannel.h
new file mode 100644 (file)
index 0000000..e1c5333
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TRUSTLETCHANNEL_H
+#define TRUSTLETCHANNEL_H
+
+#include<wrapper.h>
+
+#include<MobiCoreDriverApi.h>
+
+typedef struct cmtstruct CMTSTRUCT;
+struct cmtstruct
+{
+  uint8_t*              wsmP;         ///< World Shared Memory (WSM) to the TCI buffer
+  uint8_t*              mappedP;      ///< pointer to the buffer that is mapped to be used with SWd. Nwd uses this.
+  uint32_t              mappedSize;   ///< size of the buffer pointed by mappedP. Nwd uses this.
+  mcBulkMap_t           mapInfo;      ///< information on mapped memory
+  mcSessionHandle_t     session;      ///< session handle
+  uint32_t              lasterror;    ///< last MC driver (MobiCoreDriverAPI.h 0x00000000... MC_DRV_OK(0)) error
+                                      ///< or CMTL ( tlCmError.h 0xE0000000...(SUCCESSFUL(0))) error
+};
+
+typedef CMTSTRUCT* CMTHANDLE;
+
+/**
+Open session to content management trustlet and allocate enough memory for communication
+*/
+CMTHANDLE tltChannelOpen(int sizeOfWsmBuffer, mcResult_t* result);
+
+/**
+Open session to TA and allocate enough memory for communication. There are two way to do this, give TA uuid or TA binary, binary length and spid.
+The former works with system TA's the latter with SP TA's.
+*/
+CMTHANDLE taChannelOpen(int sizeOfWsmBuffer,  mcResult_t* result, const mcUuid_t* uuidP, uint8_t* taBinaryP, uint32_t taLength, mcSpid_t spid);
+/**
+*/
+void tltChannelClose(CMTHANDLE handle);
+/**
+*/
+bool tltChannelTransmit(CMTHANDLE handle, int timeout);
+
+#endif // TRUSTLETCHANNEL_H
diff --git a/mobicore/rootpa/Code/Common/xmlmessagehandler.c b/mobicore/rootpa/Code/Common/xmlmessagehandler.c
new file mode 100644 (file)
index 0000000..b74cb0b
--- /dev/null
@@ -0,0 +1,1128 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <wrapper.h>
+#include <stdint.h>
+#ifdef TIZEN
+#include <stdarg.h>
+extern int asprintf (char **result, const char *format, ...)
+       __attribute__ ((__format__ (__printf__, 2, 3)));
+extern int vasprintf (char **result, const char *format, va_list args)
+       __attribute__ ((__format__ (__printf__, 2, 0)));
+#endif
+
+#include <libxml/parser.h>
+#include <libxml/valid.h>
+#include <libxml/xmlschemas.h>
+
+#include <mcVersionInfo.h>
+
+#include "logging.h"
+#include "enrollmentservicexmlschema.h"
+#include "xmlmessagehandler.h"
+#include "contentmanager.h"
+#include "provisioningengine.h"
+#include "base64.h"
+
+#define ENROLLMENT_SERVICE_NS_PREFIX 0 // "mces"
+#define ENROLLMENT_SERVICE_NAMESPACE "http://www.mcore.gi-de.com/2012/04/schema/EnrollmentService"
+
+#define PLATFORM_TYPES_NS_PREFIX "mcpt"
+#define PLATFORM_TYPES_NAMESPACE "http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes"
+
+#define XSD_PATH_MAX_LEN 1024
+#define INT_BUFFER_LENGTH 11
+#define UNKNOWN_ID 0xFFFFFFFF
+
+#define EXTERNAL_MEMORY 2
+#define DEFAULT_MEMORY_TYPE EXTERNAL_MEMORY
+#define DEFAULT_NUMBER_OF_INSTANCES 1
+#define DEFAULT_FLAGS 0
+
+typedef enum
+{
+    CMP,
+    SO_UPLOAD,
+       TLT_UPLOAD,
+    UNKNOWN_TYPE=0xFFFFFFFF
+} commandtype_t;
+
+static char enrollmentServiceFullPath_[XSD_PATH_MAX_LEN];
+static char platformTypesFullPath_[XSD_PATH_MAX_LEN];
+static xmlNsPtr nameSpace_=NULL;
+static xmlNsPtr typesNameSpace_=NULL;
+// file internal functions
+
+xmlDocPtr createXmlResponse()
+{
+    xmlDocPtr docP = NULL;
+    xmlNodePtr root_node = NULL;
+
+    docP = xmlNewDoc(BAD_CAST "1.0");
+    root_node = xmlNewNode(nameSpace_, BAD_CAST "ContentManagementResponse");
+    nameSpace_=xmlNewNs(root_node, (const xmlChar*) ENROLLMENT_SERVICE_NAMESPACE, (const xmlChar*) ENROLLMENT_SERVICE_NS_PREFIX );
+    typesNameSpace_=xmlNewNs(root_node, (const xmlChar*) PLATFORM_TYPES_NAMESPACE, (const xmlChar*) PLATFORM_TYPES_NS_PREFIX );
+    xmlSetNs(root_node, nameSpace_);
+    xmlDocSetRootElement(docP, root_node);
+    docP->standalone=1;
+    return docP;
+}
+
+
+bool addTrustletData(xmlNodePtr rootNode, bool tltBin, char* contentP)
+{
+    char* element;
+    xmlNodePtr trustletDataNode=xmlNewChild(rootNode, nameSpace_, BAD_CAST "trustletData", NULL);
+    if(NULL==trustletDataNode) return false;
+    element ="encryptedKey";
+    if(tltBin)
+    {
+        element="tltBin";
+    }
+
+    if(xmlNewChild(trustletDataNode, nameSpace_, BAD_CAST element, BAD_CAST contentP)==NULL ) return false;
+    return true;
+}
+
+
+char* errorCodeToString(rootpaerror_t errorCode)
+{
+    char* returnErrorCode = STRING_ROOTPA_ERROR_INTERNAL;
+       
+    switch(errorCode)
+    {
+        case ROOTPA_COMMAND_NOT_SUPPORTED:
+               returnErrorCode = STRING_ROOTPA_COMMAND_NOT_SUPPORTED;
+            break;
+
+        case ROOTPA_ERROR_LOCK:
+               returnErrorCode =  STRING_ROOTPA_ERROR_LOCK;
+               break;
+
+//
+// this is not currently understood by SE
+//
+//        case ROOTPA_ERROR_COMMAND_EXECUTION:
+//            returnErrorCode =   STRING_ROOTPA_ERROR_COMMAND_EXECUTION;
+//             break;
+
+        case ROOTPA_ERROR_REGISTRY:
+               returnErrorCode =  STRING_ROOTPA_ERROR_REGISTRY;
+               break;
+
+        case ROOTPA_ERROR_MOBICORE_CONNECTION:
+               returnErrorCode =  STRING_ROOTPA_ERROR_MOBICORE_CONNECTION;
+               break;
+
+        case ROOTPA_ERROR_OUT_OF_MEMORY:
+               returnErrorCode =  STRING_ROOTPA_ERROR_OUT_OF_MEMORY;
+               break;
+
+        case ROOTPA_ERROR_INTERNAL:
+               returnErrorCode =  STRING_ROOTPA_ERROR_INTERNAL;
+               break;
+
+        case ROOTPA_ERROR_XML:
+               returnErrorCode =  STRING_ROOTPA_ERROR_XML;
+               break;
+
+        case ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE:
+               returnErrorCode =  STRING_ROOTPA_ERROR_REGISTRY_OBJECT_NOT_AVAILABLE;
+               break;
+    }
+    LOGD("errorCodeToString: unknown error code %d", errorCode);
+    
+    return returnErrorCode;
+}
+
+bool addCommandResultData(xmlNodePtr resultListNode, int id,  char* commandResultP, rootpaerror_t errorCode, uint32_t errorDetail )
+{
+    bool retValue;
+    char intBuffer[INT_BUFFER_LENGTH];
+
+    xmlNodePtr commandResultNode=xmlNewChild(resultListNode, nameSpace_, BAD_CAST "commandResult", NULL);
+    if(NULL==commandResultNode) return false;
+
+    retValue=true;
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",(uint32_t) id);
+    if(xmlNewProp(commandResultNode, BAD_CAST "id", BAD_CAST intBuffer)==NULL) return false;
+
+    if(commandResultP==NULL)
+    {
+        xmlNodePtr errorNode=xmlNewChild(commandResultNode, nameSpace_, BAD_CAST "resultError", NULL);
+        if( NULL==errorNode ) return false;    // CommandExecutionError
+
+        if(xmlNewProp(errorNode, BAD_CAST "errorCode", BAD_CAST errorCodeToString(errorCode))==NULL)
+        {
+            retValue=false;
+        }
+        else if(errorDetail!=0)
+        {
+            snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",errorDetail);
+            if(xmlNewProp(errorNode, BAD_CAST "errorDetail", BAD_CAST intBuffer)==NULL)
+            {
+                retValue=false;
+            }
+        }
+    }
+    else
+    {
+        if(xmlNewChild(commandResultNode, nameSpace_, BAD_CAST "resultValue", BAD_CAST commandResultP)==NULL )
+        {
+            retValue=false;
+        }
+    }
+
+    return retValue;
+}
+
+xmlNodePtr findFirstCommandNode(xmlDocPtr xmlDocP)
+{
+    xmlNodePtr commandsNodeP;
+    xmlNodePtr rootElementP;
+
+    rootElementP = xmlDocGetRootElement(xmlDocP);
+    if(NULL==rootElementP) return NULL;
+
+    commandsNodeP=rootElementP->children;
+    for (; commandsNodeP; commandsNodeP = commandsNodeP->next)
+    {
+        if (commandsNodeP->type == XML_ELEMENT_NODE && strcmp((char*)commandsNodeP->name, "commands")==0)
+        {
+            break;
+        }
+    }
+    if(NULL==commandsNodeP) return NULL;
+    return commandsNodeP->children;
+}
+
+xmlNodePtr getNextCommand(xmlDocPtr xmlDocP, xmlNodePtr prevNode)
+{
+    xmlNodePtr firstNode;
+    xmlNodePtr commandNode;
+    LOGD(">> getNextCommand %ld %ld", (long int) xmlDocP, (long int) prevNode);
+    if(NULL==prevNode)
+    {
+        firstNode=findFirstCommandNode(xmlDocP);
+    }
+    else
+    {
+        firstNode=prevNode->next;
+    }
+
+    for (commandNode = firstNode; commandNode; commandNode = commandNode->next)
+    {
+        if (commandNode->type == XML_ELEMENT_NODE && strcmp((char*)commandNode->name, "command")==0)
+        {
+            break;
+        }
+    }
+    LOGD("<< getNextCommand %ld", (long int) commandNode);
+    return commandNode;
+}
+
+
+int getCommandId(xmlNodePtr commandNode)
+{
+    int id;
+    xmlChar* idP;
+    idP=xmlGetProp(commandNode, BAD_CAST "id");
+    if(NULL==idP)
+    {
+        return UNKNOWN_ID;
+    }
+    id=atoi((char*)idP);
+    xmlFree(idP);
+    return id;
+}
+
+commandtype_t getCommandType(xmlNodePtr commandNode)
+{
+    xmlChar* typeP;
+    commandtype_t type;
+    if(NULL==commandNode) return UNKNOWN_TYPE;
+    typeP=xmlGetProp(commandNode, BAD_CAST "type");
+    type=UNKNOWN_TYPE;
+    if(typeP!=NULL)
+    {
+        if(strcmp((char*)typeP,"CMP")==0) type=CMP;
+        else if(strcmp((char*)typeP,"SO_UPLOAD")==0) type=SO_UPLOAD;
+        else if(strcmp((char*)typeP,"TLT_UPLOAD")==0) type=TLT_UPLOAD;
+        xmlFree(typeP);
+    }
+    else
+    {
+        LOGE("type property does not exist");
+    }
+    return type;
+}
+
+/**
+Note, the caller has to release the memory with xmlFree
+*/
+char* getCommandValue(xmlNodePtr commandNode)
+{
+    xmlNodePtr commandValueNodeP=commandNode->children;
+
+    for (; commandValueNodeP; commandValueNodeP = commandValueNodeP->next)
+    {
+        if (commandValueNodeP->type == XML_ELEMENT_NODE && strcmp((char*)commandValueNodeP->name, "commandValue")==0)
+        {
+            break;
+        }
+    }
+    if(NULL==commandValueNodeP) return NULL;
+
+    return (char*) xmlNodeGetContent(commandValueNodeP);
+}
+
+
+bool getCommandIgnoreError(xmlNodePtr commandNode)
+{
+    xmlChar* attribute=xmlGetProp(commandNode, BAD_CAST "ignoreError");
+    bool ignoreError=false; // default value is false
+    if(NULL!=attribute)
+    {
+        if(strcmp((char*)attribute, "true")==0)
+        {
+            ignoreError=true;
+        }
+        xmlFree(attribute);
+    }
+
+    return ignoreError;
+}
+
+void getValues(xmlNodePtr commandNodeP, commandtype_t* commandTypeP, uint32_t* idP, char** commandValueP, bool* ignoreErrorP)
+{
+    *commandTypeP=getCommandType(commandNodeP);
+    *idP=getCommandId(commandNodeP);
+    *commandValueP=(char*) getCommandValue(commandNodeP);
+    *ignoreErrorP=getCommandIgnoreError(commandNodeP);
+}
+
+uint32_t extractCmpCommand(CmpMessage** cmpCommandsP, uint32_t numberOfCmpCommands, uint32_t id, char* commandValueP, bool ignoreError)
+{
+    CmpMessage* localCommandsP=*cmpCommandsP; // localCommandsP is just to make the code a bit more readable
+    CmpMessage* tmpCommandsP=(CmpMessage*)realloc(localCommandsP, sizeof(CmpMessage)*(numberOfCmpCommands+1));
+
+    if(tmpCommandsP!=NULL)
+    {
+        localCommandsP=tmpCommandsP;
+        *cmpCommandsP=localCommandsP;
+
+        memset(&(localCommandsP[numberOfCmpCommands]), 0,sizeof(CmpMessage));
+        if(commandValueP)
+        {
+            localCommandsP[numberOfCmpCommands].length= base64DecodeStringRemoveEndZero(commandValueP,
+                                                                     (char**) &(localCommandsP[numberOfCmpCommands].contentP));
+            if(0==localCommandsP[numberOfCmpCommands].length)
+            {
+                LOGE("handleCmpCommand: base64 decoding failed");
+            }
+            localCommandsP[numberOfCmpCommands].hdr.id=id;
+            localCommandsP[numberOfCmpCommands].hdr.ignoreError=ignoreError;
+            numberOfCmpCommands++;
+        }
+        else
+        {
+            localCommandsP[numberOfCmpCommands].hdr.ret=ROOTPA_ERROR_XML;
+        }
+    }
+    else
+    {
+        LOGE("handleCmpCommand: was not able to realloc");
+        // In this case we can not return an error to SE unless we set some of the earlier errors.
+        if(!ignoreError)
+        {
+            free(*cmpCommandsP);
+            *cmpCommandsP=NULL;
+            numberOfCmpCommands=0;
+        }
+    }
+    return numberOfCmpCommands;
+}
+
+rootpaerror_t handleCmpResponses(uint32_t maxNumberOfCmpResponses, CmpMessage* cmpResponsesP, xmlNodePtr rspResultElementP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    uint32_t i;
+    LOGD(">>handleCmpResponses %d", maxNumberOfCmpResponses);
+
+       if(cmpResponsesP == NULL)
+    {
+        if(maxNumberOfCmpResponses>0)
+        {
+            LOGE("maxNumberOfCmpResponses %d while pointer is NULL", maxNumberOfCmpResponses);
+            return ROOTPA_ERROR_INTERNAL;
+        }
+        return ROOTPA_OK;
+    }
+
+    for(i=0; (i<maxNumberOfCmpResponses) && (ROOTPA_OK==ret); i++)
+    {
+        char* encodedResponseP=NULL;
+        if((ROOTPA_ERROR_COMMAND_EXECUTION==cmpResponsesP[i].hdr.ret ||
+            ROOTPA_OK==cmpResponsesP[i].hdr.ret) && cmpResponsesP[i].contentP!=NULL)
+        {
+            encodedResponseP=base64EncodeAddEndZero((char*) cmpResponsesP[i].contentP, cmpResponsesP[i].length);
+            if(NULL==encodedResponseP)
+            {
+                LOGE("handleCmpResponses: base64 encoding failed %d", i);
+                cmpResponsesP[i].hdr.ret=ROOTPA_ERROR_INTERNAL;
+                if(cmpResponsesP[i].hdr.ignoreError==false) ret=ROOTPA_ERROR_INTERNAL;
+            }
+        }
+
+        if( addCommandResultData(rspResultElementP, cmpResponsesP[i].hdr.id, encodedResponseP, cmpResponsesP[i].hdr.ret, cmpResponsesP[i].hdr.intRet )==false )
+        {
+            ret=ROOTPA_ERROR_XML;
+        }
+        free(encodedResponseP);
+
+        if(cmpResponsesP[i].hdr.ret != ROOTPA_OK && false == cmpResponsesP[i].hdr.ignoreError)
+        {
+            LOGD("handleCmpResponses, stopping since the current message (%d) has error %d and ignoreError false", i, cmpResponsesP[i].hdr.ret);
+            break;
+        }
+    }
+    LOGD("<<handleCmpResponses %d", ret);
+    return ret;
+}
+
+uint32_t handleUploadCommand(commandtype_t commandType,
+                             CommonMessage** uploadCommandsP,
+                             uint32_t numberOfUploadCommands,
+                             uint32_t id,
+                             char* commandValueP,
+                             bool ignoreError)
+{
+    uint8_t* containerDataP = NULL;
+    int containerLength;
+    CommonMessage* localCommandsP=*uploadCommandsP; // localCommandsP is just to make the code a bit more readable
+    CommonMessage* tmpCommandsP=(CommonMessage*)realloc(localCommandsP, sizeof(CommonMessage)*(numberOfUploadCommands+1));
+    LOGD(">>handleUploadCommand %d %lx %lx", commandType, (long int) uploadCommandsP, (long int) *uploadCommandsP);
+    if(NULL == tmpCommandsP)
+    {
+        LOGE("handleUploadCommand: was not able to realloc, returning %d", ignoreError);
+        if(!ignoreError)
+        {
+            free(*uploadCommandsP);
+            *uploadCommandsP=NULL;
+            numberOfUploadCommands=0;
+        }
+        return numberOfUploadCommands;
+        // In this case we can not return an error to SE unless we set some of the earlier errors.
+    }
+
+    localCommandsP=tmpCommandsP;
+    *uploadCommandsP=localCommandsP;
+    memset(&(localCommandsP[numberOfUploadCommands]), 0,sizeof(CommonMessage));
+
+    if(NULL == commandValueP)
+    {
+        localCommandsP[numberOfUploadCommands++].ret=ROOTPA_ERROR_XML;
+        return numberOfUploadCommands;
+    }
+
+    localCommandsP[numberOfUploadCommands].ret=ROOTPA_OK;
+
+    containerLength= base64DecodeStringRemoveEndZero(commandValueP, (char**) &(containerDataP));
+
+    if(0 == containerLength)
+    {
+        LOGE("handleUploadCommand: base64 decoding failed");
+        localCommandsP[numberOfUploadCommands].ret=ROOTPA_ERROR_INTERNAL;
+    }
+
+    if(TLT_UPLOAD == commandType)
+    {
+        localCommandsP[numberOfUploadCommands].ret = uploadTrustlet(containerDataP, containerLength);
+    }
+    else if (SO_UPLOAD == commandType)
+    {
+        localCommandsP[numberOfUploadCommands].ret = uploadSo(containerDataP,
+                                                              containerLength,
+                                                              &localCommandsP[numberOfUploadCommands].intRet);
+    }
+    else
+    {
+        LOGE("handleUploadCommand: unknown command type %d this should not have happened", commandType);
+        localCommandsP[numberOfUploadCommands].ret=ROOTPA_ERROR_INTERNAL;
+    }
+    free(containerDataP);
+    localCommandsP[numberOfUploadCommands].id=id;
+    localCommandsP[numberOfUploadCommands].ignoreError=ignoreError;
+    numberOfUploadCommands++;
+
+    LOGD("<<handleUploadCommand %d %lx %lx", numberOfUploadCommands, (long int) uploadCommandsP, (long int) *uploadCommandsP);
+    return numberOfUploadCommands;
+}
+
+rootpaerror_t handleUploadResponses(uint32_t numberOfUploadResponses, CommonMessage* uploadResponsesP, xmlNodePtr rspResultElementP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    char zero=0;
+    uint32_t i;
+    LOGD(">>handleUploadResponses %d", numberOfUploadResponses);
+
+       if(uploadResponsesP == NULL)
+    {
+        if(numberOfUploadResponses>0)
+        {
+            LOGE("numberOfUploadResponses %d while pointer is NULL", numberOfUploadResponses);
+            return ROOTPA_ERROR_INTERNAL;
+        }
+        return ROOTPA_OK;
+    }
+
+    for(i=0; (i < numberOfUploadResponses) && (ROOTPA_OK==ret); i++)
+    {
+        char* encodedResponseP=NULL;
+        if(ROOTPA_OK == uploadResponsesP[i].ret)
+        {
+            // in success case TLT_UPLOAD and SO_UPLOAD return "0" (encoded) in the resultValue
+            // field (discussed and agreed with Dimi Jan 10, 2013)
+            encodedResponseP=base64EncodeAddEndZero(&zero, 1);
+        }
+
+        if( addCommandResultData(rspResultElementP, uploadResponsesP[i].id, encodedResponseP,  uploadResponsesP[i].ret, uploadResponsesP[i].intRet )==false)
+        {
+            ret=ROOTPA_ERROR_XML;
+        }
+        free(encodedResponseP);
+
+        LOGD("handleUploadResponses, in loop idx %d ret %d ignore %d", i, uploadResponsesP[i].ret , uploadResponsesP[i].ignoreError);
+        if(uploadResponsesP[i].ret != ROOTPA_OK && false == uploadResponsesP[i].ignoreError)
+        {
+            LOGD("handleUploadResponses, stopping since the current message has error and ignoreError false %d", i);
+            break;
+        }
+    }
+    LOGD("<<handleUploadResponses");
+    return ret;
+}
+
+rootpaerror_t handleCommandAndFillResponse(xmlDocPtr xmlCommandP, xmlDocPtr xmlResponseP)
+{
+    rootpaerror_t ret=ROOTPA_OK;
+    rootpaerror_t tmpRet=ROOTPA_OK;
+    xmlNodePtr rspRootElementP;
+
+    CmpMessage* cmpCommandsP=NULL;
+    CommonMessage* uploadCommandsP=NULL;
+
+    int numberOfCmpCommands=0;
+    int numberOfUploadCommands=0;
+
+    commandtype_t commandType=UNKNOWN_TYPE;
+    uint32_t id=0;
+    char* commandValueP=NULL;
+    CmpMessage* cmpResponsesP=NULL;
+    bool ignoreError=0;
+    xmlNodePtr commandNode=NULL;
+    int i;
+
+    LOGD(">>handleCommandAndFillResponse");
+
+    rspRootElementP = xmlDocGetRootElement(xmlResponseP);
+    if(NULL==rspRootElementP) return ROOTPA_ERROR_XML;
+
+    // parse command data out of xml, upload commands will also be executed
+
+    while((commandNode=getNextCommand(xmlCommandP, commandNode))!=NULL)
+    {
+        getValues(commandNode, &commandType, &id, &commandValueP, &ignoreError);
+        switch(commandType)
+        {
+            case CMP:
+            {
+                numberOfCmpCommands=extractCmpCommand(&cmpCommandsP, numberOfCmpCommands, id, commandValueP, ignoreError);
+                if(0==numberOfCmpCommands)
+                {
+                    ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+                }
+                break;
+            }
+            case SO_UPLOAD:
+            // intentional fallthrough
+            case TLT_UPLOAD:
+                numberOfUploadCommands=handleUploadCommand(commandType, &uploadCommandsP, numberOfUploadCommands, id, commandValueP, ignoreError);
+                if(0==numberOfUploadCommands)
+                {
+                    ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+                }
+                break;
+            default:
+                LOGE("handleCommandAndFillResponse: received unknown command");
+                // we will still work with the other commands in case there are any
+                break;
+        }
+        xmlFree(commandValueP);
+
+        if(ROOTPA_ERROR_OUT_OF_MEMORY == ret) break;
+
+        if(commandType != CMP &&
+          false == ignoreError &&
+          uploadCommandsP &&
+          uploadCommandsP[numberOfUploadCommands-1].ret != ROOTPA_OK) break; // since upload commands are already executed in this loop
+    }
+
+    // execute the actual content management protocol commands, if there are any
+    if(cmpCommandsP)
+    {
+        uint32_t internalError;
+        cmpResponsesP=(CmpMessage *)malloc(sizeof(CmpMessage)*numberOfCmpCommands);
+
+        if(NULL==cmpResponsesP)
+        {
+            ret=ROOTPA_ERROR_OUT_OF_MEMORY;
+        }
+        else
+        {
+            memset(cmpResponsesP, 0, sizeof(CmpMessage)*numberOfCmpCommands);
+            tmpRet=executeContentManagementCommands(numberOfCmpCommands, cmpCommandsP, cmpResponsesP, &internalError);
+            if(ROOTPA_OK!=tmpRet)
+            {
+                LOGE("call to executeContentManagementCommands failed with %d, continuing anyway", tmpRet);
+                // return code from executeContentManagementCommands is here more informative than anything else
+                // even in an error case we need to return response to SE, the errors are also included in the
+                // actual CMP messages.
+                ret=tmpRet;
+            }
+        }
+    }
+
+    // fill response
+    if (ret!=ROOTPA_ERROR_OUT_OF_MEMORY)
+    {
+        xmlNodePtr resultListNodeP=xmlNewChild(rspRootElementP, nameSpace_, BAD_CAST "commandResultList", NULL);
+        tmpRet=handleCmpResponses(numberOfCmpCommands, cmpResponsesP, resultListNodeP);
+        if(ROOTPA_OK!=tmpRet)
+        {
+            LOGE("handleCommandAndFillResponse: not able to handle all Cmp responses, still continuing with UploadResponses %d", tmpRet);
+            ret=tmpRet;
+        }
+        tmpRet=handleUploadResponses(numberOfUploadCommands, uploadCommandsP, resultListNodeP);
+        if(ROOTPA_OK!=tmpRet)
+        {
+            LOGE("handleCommandAndFillResponse: not able to handle all Upload responses %d", tmpRet);
+            ret=tmpRet;
+        }
+    }
+    // cleanup what has not yet been cleaned
+
+    for(i=0; i<numberOfCmpCommands; i++)
+    {
+        if(cmpCommandsP) free(cmpCommandsP[i].contentP);
+        if(cmpResponsesP) free(cmpResponsesP[i].contentP);
+    }
+    free(cmpCommandsP);
+    free(cmpResponsesP);
+    free(uploadCommandsP);
+
+    LOGD("<<handleCommandAndFillResponse %d", ret);
+    return ret;
+}
+
+void handleError(void* ctx, const char *format, ...)
+{
+       (void) ctx;
+#ifdef WIN32
+       #define ERROR_LOG_LENGTH 256
+    char errMsg[ERROR_LOG_LENGTH];
+
+       va_list args;
+    va_start(args, format);
+    vsnprintf(errMsg, ERROR_LOG_LENGTH, format, args);
+    va_end(args);
+
+       LOGW("From libxml2: %s", errMsg);
+#else
+    char *errMsg;
+
+       va_list args;
+    va_start(args, format);
+    vasprintf(&errMsg, format, args);
+    va_end(args);
+
+       LOGW("From libxml2: %s", errMsg);
+    free(errMsg);
+#endif
+}
+
+/*
+This is for saving the required xml schema files so that the libxml2 code can read it,
+to be called only if the files do not exist of can not be parsed
+*/
+
+void saveFile(char* filePath, char* fileContent)
+{
+
+    FILE* fh;
+    LOGD(">>saveFile %s", filePath);
+    if ((fh = fopen(filePath, "w")) != NULL)
+       {
+        fprintf(fh, "%s", fileContent);
+        fclose(fh);
+       }
+    else
+    {
+        LOGE("saveFiles no handle %s", filePath);
+    }
+    LOGD("<<saveFile");
+}
+
+
+bool validXmlMessage(xmlDocPtr xmlDocP)
+{
+
+    int result=-2;
+
+#ifdef LIBXML_SCHEMAS_ENABLED
+
+    xmlSchemaParserCtxtPtr parserCtxtP = NULL;
+    xmlSchemaPtr schemaP = NULL;
+    xmlSchemaValidCtxtPtr validCtxtP = NULL;
+    LOGD(">>validXmlMessage %s", enrollmentServiceFullPath_);
+//    Here we store the schemas if they are not already on "disk". It seems
+//    xmlSchemaNewParserCtxt succeeds even if the file does not exists and it is
+//    xmlSchemaParse that requires the file to exists. That is why the files are
+//    created if schemaP==NULL. Since we are using static library, this can be
+//    easily controlled even if there are changes in the behavior
+
+    parserCtxtP = xmlSchemaNewParserCtxt(enrollmentServiceFullPath_);
+    schemaP = xmlSchemaParse(parserCtxtP);
+    if (!schemaP)
+    {
+        LOGW("validXmlMessage, no schema ctxt, attempting to save xsd files");
+        saveFile(platformTypesFullPath_, PLATFORM_TYPES_XSD);
+        saveFile(enrollmentServiceFullPath_, ENROLLMENT_SERVICE_XSD);
+        schemaP = xmlSchemaParse(parserCtxtP);
+        if (!schemaP){
+            LOGE("validXmlMessage, was not able to save xsd files");
+            goto cleanup;
+        }
+    }
+
+    validCtxtP = xmlSchemaNewValidCtxt(schemaP);
+    if (!validCtxtP){
+        LOGE("validXmlMessage, no validCtxtP");
+        goto cleanup;
+    }
+
+    result=xmlSchemaValidateDoc(validCtxtP, xmlDocP);
+
+cleanup:
+
+    if (parserCtxtP) xmlSchemaFreeParserCtxt(parserCtxtP);
+    if (schemaP) xmlSchemaFree(schemaP);
+    if (validCtxtP) xmlSchemaFreeValidCtxt(validCtxtP);
+
+    LOGD("<<validXmlMessage %d", result);
+    return ((0==result)?true:false);
+
+ #else // !LIBXML_SCHEMAS_ENABLED
+    LOGD("<<validXmlMessage");
+    return true;
+ #endif // LIBXML_SCHEMAS_ENABLED
+}
+
+uint8_t* validateDumpAndFree(xmlDocPtr xmlResponseP)
+{
+    uint8_t*  dumpedP=NULL;
+    int size=0;
+    xmlChar* dumpP;
+    if(!validXmlMessage(xmlResponseP))
+    {
+        LOGE("validateDumpAndFree, invalid response");
+    }
+
+       xmlDocDumpMemoryEnc(xmlResponseP, &dumpP, &size, "UTF-8");
+    if(dumpP!=NULL)
+    {
+        // doing this copy only because libxml2 documentation tells to
+        // release the memory with xmlFree, not free and we want to keep
+        // libxml use strictly in this file. It is likely that xmlFree is
+        // compatible with free but since I have not verified it, this is to
+        // be on the safe side
+
+        dumpedP=(uint8_t*)malloc(size+1);
+        if(dumpedP!=NULL)
+        {
+            strncpy((char*) dumpedP, (char*) dumpP, size+1);
+        }
+        xmlFree(dumpP);
+    }
+    xmlFreeDoc(xmlResponseP);
+
+    return dumpedP;
+}
+
+// functions used from outside of this file
+
+/**
+    in case an error is returned *responseP is set to NULL
+*/
+rootpaerror_t handleXmlMessage(const char* messageP, const char** responseP)
+{
+
+    rootpaerror_t ret=ROOTPA_OK;
+    rootpaerror_t tmpRet=ROOTPA_OK;
+    xmlDocPtr xmlDocP;
+    xmlDocPtr xmlResponseP;
+
+    *responseP=NULL;
+    LOGD(">>handleXmlMessage");
+
+    if (NULL==messageP)
+    {
+        LOGE("handleXmlMessage, no messageP");
+        return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+    }
+
+    xmlSetStructuredErrorFunc(NULL, NULL);
+    xmlSetGenericErrorFunc(NULL, handleError);
+    xmlThrDefSetStructuredErrorFunc(NULL, NULL);
+    xmlThrDefSetGenericErrorFunc(NULL, handleError);
+
+    xmlDocP= xmlParseMemory(messageP, strlen(messageP));
+    if(NULL==xmlDocP)
+    {
+        LOGE("handleXmlMessage, can not parse xmlMessageP %s", messageP);
+        return ROOTPA_ERROR_XML;
+    }
+
+    if(!validXmlMessage(xmlDocP))
+    {
+        LOGE("handleXmlMessage, invalid message %s", messageP);
+        ret=ROOTPA_ERROR_XML;
+        // attempting to parse the message anyway.
+    }
+
+   xmlResponseP=createXmlResponse();
+
+// parse received command
+
+    if(xmlResponseP)
+    {
+        tmpRet=handleCommandAndFillResponse(xmlDocP, xmlResponseP);
+        if(tmpRet!=ROOTPA_OK) ret=tmpRet;
+    }
+    else
+    {
+        ret=ROOTPA_ERROR_XML;
+    }
+
+    if(xmlResponseP && xmlResponseP->children) // if there is something to return to SE, return it.
+    {
+        *responseP = (char*)validateDumpAndFree(xmlResponseP);
+    }
+    else
+    {
+        if(xmlResponseP) xmlFreeDoc(xmlResponseP);
+    }
+
+    if(xmlDocP) xmlFreeDoc(xmlDocP);
+    xmlCleanupParser();
+
+    LOGD("<<handleXmlMessage %d %s", ret, ((NULL==*responseP)?"no *responseP":*responseP));
+    return ret;
+}
+
+rootpaerror_t fillSystemInfo(xmlNodePtr systemInfoNode, const osInfo_t* osSpecificInfoP)
+{
+    LOGD(">>fillSystemInfo %ld", (long int) osSpecificInfoP);
+    if(osSpecificInfoP->imeiEsnP)
+    {
+        LOGD("imei %s", osSpecificInfoP->imeiEsnP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "imei", BAD_CAST osSpecificInfoP->imeiEsnP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    if(osSpecificInfoP->mnoP)
+    {
+        LOGD("mno %s", osSpecificInfoP->mnoP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "mno", BAD_CAST osSpecificInfoP->mnoP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    if(osSpecificInfoP->brandP)
+    {
+        LOGD("brand %s", osSpecificInfoP->brandP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "brand", BAD_CAST osSpecificInfoP->brandP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    if(osSpecificInfoP->manufacturerP)
+    {
+        LOGD("manufacturer %s", osSpecificInfoP->manufacturerP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "manufacturer", BAD_CAST osSpecificInfoP->manufacturerP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    if(osSpecificInfoP->hardwareP)
+    {
+        LOGD("hardware %s", osSpecificInfoP->hardwareP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "hardware", BAD_CAST osSpecificInfoP->hardwareP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    if(osSpecificInfoP->modelP)
+    {
+        LOGD("model %s", osSpecificInfoP->modelP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "model", BAD_CAST osSpecificInfoP->modelP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    if(osSpecificInfoP->versionP)
+    {
+        LOGD("version %s", osSpecificInfoP->versionP);
+        if(xmlNewProp(systemInfoNode, BAD_CAST "version", BAD_CAST osSpecificInfoP->versionP)==NULL) return ROOTPA_ERROR_XML;
+    }
+
+    LOGD("<<fillSystemInfo");
+    return ROOTPA_OK;
+}
+
+rootpaerror_t fillMcVersion(xmlNodePtr mcVersionNode, int mcVersionTag, const mcVersionInfo_t* mcVersionP)
+{
+       (void) mcVersionTag;
+    char intBuffer[INT_BUFFER_LENGTH];
+    LOGD(">>fillMcVersion");
+    xmlSetStructuredErrorFunc(NULL, NULL);
+    xmlSetGenericErrorFunc(NULL, handleError);
+    xmlThrDefSetStructuredErrorFunc(NULL, NULL);
+    xmlThrDefSetGenericErrorFunc(NULL, handleError);
+
+    if(xmlNewProp(mcVersionNode, BAD_CAST "productId", BAD_CAST mcVersionP->productId)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionMci);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionMci", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionSo);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionSo", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionMclf);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionMclf", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionContainer);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionContainer", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionMcConfig);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionMcConfig", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionTlApi);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionTlApi", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionDrApi);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionDrApi", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%u",mcVersionP->versionCmp);
+    if(xmlNewProp(mcVersionNode, BAD_CAST "versionCmp", BAD_CAST intBuffer)==NULL) return ROOTPA_ERROR_XML;
+
+    LOGD("<<fillMcVersion");
+    return ROOTPA_OK;
+}
+
+rootpaerror_t buildXmlTrustletInstallationRequest(const char** responseP, trustletInstallationData_t data )
+{
+    char intBuffer[INT_BUFFER_LENGTH];
+    rootpaerror_t ret=ROOTPA_OK;
+    xmlDocPtr xmlResponseDocP;
+    xmlNodePtr rspRootElementP;
+    xmlNodePtr systemInfoNode;
+    xmlNodePtr mcDataNode=NULL;
+    char* encodedDataP;
+    char* pukHashStringP;
+    LOGD(">>buildXmlTrustletInstallationRequest %ld (%ld %d %d)", (long int) responseP, (long int) data.dataP, data.dataLength, data.dataType);
+    if(NULL ==  responseP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT; // data content checked earlier in commandhandler.c
+
+    xmlResponseDocP=createXmlResponse();
+    rspRootElementP = xmlDocGetRootElement(xmlResponseDocP);
+    if(NULL==rspRootElementP) return ROOTPA_ERROR_XML;
+
+    systemInfoNode=xmlNewChild(rspRootElementP, nameSpace_, BAD_CAST "tltInstallationRequest", NULL);
+    if(NULL==systemInfoNode) return ROOTPA_ERROR_XML;
+
+    encodedDataP=base64EncodeAddEndZero((char*) data.dataP, data.dataLength);
+    if(NULL==encodedDataP)
+    {
+        LOGE("buildXmlTrustletInstallationRequest: base64 encoding of data failed");
+        return ROOTPA_ERROR_INTERNAL;
+    }
+
+    if(data.dataType == REQUEST_DATA_TLT)
+    {
+        mcDataNode = xmlNewChild(systemInfoNode, nameSpace_, BAD_CAST "trustletAxf", BAD_CAST encodedDataP);
+        if(data.memoryType != DEFAULT_MEMORY_TYPE)
+        {
+            snprintf(intBuffer,INT_BUFFER_LENGTH,"%d",data.memoryType);
+            if(xmlNewProp(mcDataNode, BAD_CAST "memoryType", BAD_CAST intBuffer)==NULL)
+            {
+                free(encodedDataP);
+                return ROOTPA_ERROR_XML;
+            }
+        }
+
+        if(data.numberOfInstances != DEFAULT_NUMBER_OF_INSTANCES)
+        {
+            snprintf(intBuffer,INT_BUFFER_LENGTH,"%d",data.numberOfInstances);
+            if(xmlNewProp(mcDataNode, BAD_CAST "numberOfInstances", BAD_CAST intBuffer)==NULL)
+            {
+                free(encodedDataP);
+                return ROOTPA_ERROR_XML;
+            }
+        }
+
+        if(data.flags != DEFAULT_FLAGS)
+        {
+            snprintf(intBuffer,INT_BUFFER_LENGTH,"%d",data.flags);
+            if(xmlNewProp(mcDataNode, BAD_CAST "flags", BAD_CAST intBuffer)==NULL)
+            {
+                free(encodedDataP);
+                return ROOTPA_ERROR_XML;
+            }
+        }
+    }
+    else
+    {
+        mcDataNode = xmlNewChild(systemInfoNode, nameSpace_, BAD_CAST "trustletEncryptionKey", BAD_CAST encodedDataP);
+    }
+
+    snprintf(intBuffer,INT_BUFFER_LENGTH,"%d",data.minTltVersion);
+    if(xmlNewProp(mcDataNode, BAD_CAST "minTltVersion", BAD_CAST intBuffer)==NULL)
+    {
+        free(encodedDataP);
+        return ROOTPA_ERROR_XML;
+    }
+
+    pukHashStringP=base64EncodeAddEndZero((char*) data.tltPukHashP, data.tltPukHashLength);
+    if(NULL==pukHashStringP)
+    {
+        LOGE("buildXmlTrustletInstallationRequest: base64 encoding of PukHash failed");
+        free(encodedDataP);
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    if(xmlNewProp(mcDataNode, BAD_CAST "tltPukHash", BAD_CAST pukHashStringP)==NULL)
+    {
+        LOGE("buildXmlTrustletInstallationRequest: xmlNewProp failed");
+        free(pukHashStringP);
+        free(encodedDataP);
+        return ROOTPA_ERROR_XML;
+    }
+
+    free(pukHashStringP);
+    free(encodedDataP);
+    if(NULL==mcDataNode) return ROOTPA_ERROR_XML;
+
+    if(ROOTPA_OK==ret)
+    {
+        *responseP=(char*)validateDumpAndFree(xmlResponseDocP);
+    }
+
+    xmlCleanupParser();
+    return ret;
+    LOGD("<<buildXmlTrustletInstallationRequest");
+}
+
+/**
+in case an error is returned *responseP is set to NULL
+*/
+rootpaerror_t buildXmlSystemInfo(const char** responseP, int mcVersionTag, const mcVersionInfo_t* mcVersionP, const osInfo_t* osSpecificInfoP)
+{
+
+    rootpaerror_t ret=ROOTPA_OK;
+    xmlDocPtr xmlResponseDocP;
+    xmlNodePtr rspRootElementP;
+    xmlNodePtr systemInfoNode;
+    xmlNodePtr mcVersionNode;
+    if(NULL == responseP || NULL == mcVersionP || NULL == osSpecificInfoP) return ROOTPA_ERROR_INTERNAL;
+    LOGD(">>buildXmlSystemInfo %ld %ld %ld", ( long int ) responseP, ( long int ) mcVersionP, ( long int ) osSpecificInfoP);
+
+    xmlSetStructuredErrorFunc(NULL, NULL);
+    xmlSetGenericErrorFunc(NULL, handleError);
+    xmlThrDefSetStructuredErrorFunc(NULL, NULL);
+    xmlThrDefSetGenericErrorFunc(NULL, handleError);
+
+    xmlResponseDocP=createXmlResponse();
+    rspRootElementP= xmlDocGetRootElement(xmlResponseDocP);
+    if(NULL==rspRootElementP) return ROOTPA_ERROR_XML;
+
+    systemInfoNode=xmlNewChild(rspRootElementP, nameSpace_, BAD_CAST "systemInformation", NULL);
+    if(NULL==systemInfoNode) return ROOTPA_ERROR_XML;
+
+    mcVersionNode=xmlNewChild(systemInfoNode, typesNameSpace_, BAD_CAST "mcVersion", NULL);
+    if(NULL==mcVersionNode) return ROOTPA_ERROR_XML;
+
+    ret=fillSystemInfo(systemInfoNode, osSpecificInfoP);
+    if(ROOTPA_OK!=ret)
+    {
+        LOGE("buildXmlSystemInfo: could not fill system info %d, continuing anyway", ret);
+    }
+
+    ret=fillMcVersion(mcVersionNode, mcVersionTag, mcVersionP);
+    if(ROOTPA_OK!=ret)
+    {
+        LOGE("buildXmlSystemInfo: could not fill Mc version %d, continuing anyway", ret);
+    }
+
+
+    if(ROOTPA_OK==ret)
+    {
+        *responseP=(char*)validateDumpAndFree(xmlResponseDocP);
+    }
+
+    xmlCleanupParser();
+    return ret;
+    LOGD("<<buildXmlSystemInfo");
+}
+
+/**
+set the path where to look for and store the xsd files
+*/
+void setXsdPaths(const char* xsdpathP)
+{
+    memset(enrollmentServiceFullPath_, 0, XSD_PATH_MAX_LEN);
+    memset(platformTypesFullPath_, 0, XSD_PATH_MAX_LEN);
+
+    if (xsdpathP!=NULL && strlen(xsdpathP)+1+sizeof(ENROLLMENT_SERVICE_XSD_NAME)<XSD_PATH_MAX_LEN) // ENROLLMENT_SERVICE_XSD_NAME is the longer of the two
+    {
+/* Fix coverity */
+//        strncpy(enrollmentServiceFullPath_, xsdpathP, XSD_PATH_MAX_LEN);
+//        strncpy(platformTypesFullPath_, xsdpathP, XSD_PATH_MAX_LEN);
+        strncpy(enrollmentServiceFullPath_, xsdpathP, XSD_PATH_MAX_LEN-1);
+        strncpy(platformTypesFullPath_, xsdpathP, XSD_PATH_MAX_LEN-1);
+
+        strncat(enrollmentServiceFullPath_, "/", XSD_PATH_MAX_LEN-strlen(xsdpathP));
+        strncat(platformTypesFullPath_, "/", XSD_PATH_MAX_LEN-strlen(xsdpathP));
+    }
+
+    strncat(enrollmentServiceFullPath_, ENROLLMENT_SERVICE_XSD_NAME, XSD_PATH_MAX_LEN-strlen(enrollmentServiceFullPath_));
+    strncat(platformTypesFullPath_, PLATFORM_TYPES_XSD_NAME, XSD_PATH_MAX_LEN-strlen(platformTypesFullPath_));
+}
diff --git a/mobicore/rootpa/Code/Common/xmlmessagehandler.h b/mobicore/rootpa/Code/Common/xmlmessagehandler.h
new file mode 100644 (file)
index 0000000..aac5806
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef XMLMESSAGEHANDLER_H
+#define XMLMESSAGEHANDLER_H
+#include "rootpaErrors.h"
+#include "rootpa.h"
+
+/**
+    @param xmlMessageP received xml message to be handled
+    @param xmlResponseP response to the received message in xml format. The caller is
+           responsible on freeing the memory the pointer points to.
+    @return ROOTPA_OK on success, ROOTPA_ERROR_ILLEGAL_ARGUMENT if
+            xmlMessageP is NULL or if the message is not valid xml
+            If error is returned, the error is also included in xmlResponse
+            (unless there is problem in allocating memory) and the response
+            should still be returned to SE.
+
+*/
+rootpaerror_t handleXmlMessage(const char* xmlMessageP, const char** xmlResponseP);
+
+/**
+From the given system info creates a xml string that can be returned to SE.
+
+@param responseP pointer to a char pointer where the response to the received message in xml
+       format is to be copied. The caller is responsible on freeing the memory the pointer points to.
+
+@param mcVersionTag version of Mobicore version info
+@param mcVersionP pointer to the mobicore version struct
+@param osSpecificInfoP pointer to struct containing operating system specific information
+
+@return ROOTPA_OK on success, ROOTPA_ERROR_INTERNAL if
+            xmlMessageP is NULL or if the message is not valid xml
+            If error is returned, the error is also included in xmlResponse
+            (unless there is problem in allocating memory) and the response
+            should still be returned to SE.
+
+*/
+rootpaerror_t buildXmlSystemInfo(const char** responseP, int mcVersionTag, const mcVersionInfo_t* mcVersionP, const osInfo_t* osSpecificInfoP);
+
+/**
+Builds request for trustlet installation
+
+@param responseP pointer to a char pointer where the response to the received message in xml
+       format is to be copied. The caller is responsible on freeing the memory the pointer points to.
+
+@param data, information needed for trustlet installation
+
+
+@return ROOTPA_OK on success, ROOTPA_ERROR_ILLEGAL_ARGUMENT if data.dataP is NULL, responseP is NULL or if data.dataType
+        has something else than the values in the type.
+
+*/
+rootpaerror_t buildXmlTrustletInstallationRequest(const char** responseP, trustletInstallationData_t data );
+
+/**
+Stores the operating system specific location of xsd files.
+
+@param xsdpathP location of the xsd files, or place when they can be dtored if they do not yet exists
+*/
+void setXsdPaths(const char* xsdpathP);
+
+#endif // XMLMESSAGEHANDLER_H
diff --git a/mobicore/tlcm/Android.mk b/mobicore/tlcm/Android.mk
new file mode 100644 (file)
index 0000000..8394b32
--- /dev/null
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := MobiCoreTlcm
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_EXPORT_C_INCLUDES)
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/mobicore/tlcm/NOTICE b/mobicore/tlcm/NOTICE
new file mode 100644 (file)
index 0000000..627167a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013-2014 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/mobicore/tlcm/TlCm/2.0/cmp.h b/mobicore/tlcm/TlCm/2.0/cmp.h
new file mode 100644 (file)
index 0000000..45bcb7a
--- /dev/null
@@ -0,0 +1,2002 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_2_0
+ * Content Management Protocol 2.0 Definitions.
+ *
+ * The content management protocol (CMP) is based on the trustlet control
+ * interface (TCI) and defines commands/responses with the content management
+ * trustlet (TlCm).
+ *
+ * @{
+ *
+ * @file
+ * CMP 2.0 global definitions.
+ * Various components need access to (sub-)structures defined and used by CMP
+ * 2.0. These common definitions are made available through this header file.
+ */
+
+#ifndef CMP_H_
+#define CMP_H_
+
+#include "TlCm/cmpCommon.h"
+
+/** Key size of encryption algorithm used for secure messaging. */
+#define CMP_MSG_KEY_SIZE 32
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_SOC_AUTHENTICATION \
+  MC_CMP_2_0_CMD_BEGIN_SOC_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_SOC_AUTHENTICATION_CMD Command_2_0
+ * @{ */
+
+/** BeginSocAuthentication non signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpBeginSocAuthenticationCmd_t;
+
+/** BeginSocAuthentication command. */
+typedef struct {
+    /** Command. */
+    cmpBeginSocAuthenticationCmd_t cmd;
+    /** AuthToken container secure object. */
+    mcSoAuthTokenCont_t soAuthTokenCont;
+} cmpCmdBeginSocAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_SOC_AUTHENTICATION_RSP Response_2_0
+ * @{ */
+
+/** BeginSocAuthentication signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+} cmpBeginSocAuthenticationRspSdata_t;
+
+/** BeginSocAuthentication signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpBeginSocAuthenticationRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpBeginSocAuthenticationRsp_t;
+
+/** BeginSocAuthentication response. */
+typedef struct {
+    /** Response. */
+    cmpBeginSocAuthenticationRsp_t rsp;
+} cmpRspBeginSocAuthentication_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_ROOT_AUTHENTICATION \
+  MC_CMP_2_0_CMD_BEGIN_ROOT_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_ROOT_AUTHENTICATION_CMD Command_2_0
+ * @{ */
+
+/** BeginRootAuthentication non signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpBeginRootAuthenticationCmd_t;
+
+/** BeginRootAuthentication command. */
+typedef struct {
+    /** Command. */
+    cmpBeginRootAuthenticationCmd_t cmd;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpCmdBeginRootAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_ROOT_AUTHENTICATION_RSP Response_2_0
+ * @{ */
+
+/** BeginRootAuthentication signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+} cmpBeginRootAuthenticationRspSdata_t;
+
+/** BeginRootAuthentication signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpBeginRootAuthenticationRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpBeginRootAuthenticationRsp_t;
+
+/** BeginRootAuthentication response. */
+typedef struct {
+    /** Response. */
+    cmpBeginRootAuthenticationRsp_t rsp;
+} cmpRspBeginRootAuthentication_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_SP_AUTHENTICATION \
+  MC_CMP_2_0_CMD_BEGIN_SP_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_SP_AUTHENTICATION_CMD Command_2_0
+ * @{ */
+
+/** BeginSpAuthentication non signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpBeginSpAuthenticationCmdSdata_t;
+
+/** BeginSpAuthentication non signed command and no signature. */
+typedef struct {
+    /** Non signed command. */
+    cmpBeginSpAuthenticationCmdSdata_t sdata;
+} cmpBeginSpAuthenticationCmd_t;
+
+/** BeginSpAuthentication command. */
+typedef struct {
+    /** Command. */
+    cmpBeginSpAuthenticationCmd_t cmd;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpCmdBeginSpAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_BEGIN_SP_AUTHENTICATION_RSP Response_2_0
+ * @{ */
+
+/** BeginSpAuthentication signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** Spid. */
+    mcSpid_t spid;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+} cmpBeginSpAuthenticationRspSdata_t;
+
+/** BeginSpAuthentication signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpBeginSpAuthenticationRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpBeginSpAuthenticationRsp_t;
+
+/** BeginSpAuthentication response. */
+typedef struct {
+    /** Response. */
+    cmpBeginSpAuthenticationRsp_t rsp;
+} cmpRspBeginSpAuthentication_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_AUTHENTICATE MC_CMP_2_0_CMD_AUTHENTICATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_AUTHENTICATE_CMD Command_2_0
+ * @{ */
+
+/** Authenticate encrypted data command. */
+typedef struct {
+    /** Suid. */
+    mcSuid_t suid;
+    /** EntityId. */
+    uint32_t entityId;
+    /** NWd authentication random number. */
+    cmpRnd8_t rnd2;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+    /** NWd authentication random seed. */
+    cmpRnd32_t k2;
+} cmpAuthMsgEdata_t;
+
+/** Authenticate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpAuthMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthMsgEdata_t))];
+} cmpAuthCmdEd_t;
+
+/** Authenticate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Encrypted and padded data. */
+    cmpAuthCmdEd_t ed;
+} cmpAuthCmdSdata_t;
+
+/** Authenticate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpAuthCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAuthenticateCmd_t;
+
+/** Authenticate command. */
+typedef struct {
+    /** Command. */
+    cmpAuthenticateCmd_t cmd;
+} cmpCmdAuthenticate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_AUTHENTICATE_RSP Response_2_0
+ * @{ */
+
+/** Authenticate encrypted data response. */
+typedef struct {
+    /** Suid. */
+    mcSuid_t suid;
+    /** EntityId. */
+    uint32_t entityId;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+    /** NWd authentication random number. */
+    cmpRnd8_t rnd2;
+    /** SWd authentication random seed. */
+    cmpRnd32_t k1;
+} cmpAuthRspEdata_t;
+
+/** Authenticate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpAuthRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthRspEdata_t))];
+} cmpAuthRspEd_t;
+
+/** Authenticate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpAuthRspEd_t ed;
+} cmpAuthRspSdata_t;
+
+/** Authenticate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpAuthRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAuthenticateRsp_t;
+
+/** Authenticate response. */
+typedef struct {
+    /** Response. */
+    cmpAuthenticateRsp_t rsp;
+} cmpRspAuthenticate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_AUTHENTICATE_TERMINATE \
+  MC_CMP_2_0_CMD_AUTHENTICATE_TERMINATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_AUTHENTICATE_TERMINATE_CMD Command_2_0
+ * @{ */
+
+/** AuthenticateTerminate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpAuthenticateTerminateCmdSdata_t;
+
+/** AuthenticateTerminate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpAuthenticateTerminateCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAuthenticateTerminateCmd_t;
+
+/** AuthenticateTerminate command. */
+typedef struct {
+    /** Command. */
+    cmpAuthenticateTerminateCmd_t cmd;
+} cmpCmdAuthenticateTerminate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_AUTHENTICATE_TERMINATE_RSP Response_2_0
+ * @{ */
+
+/** AuthenticateTerminate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+} cmpAuthenticateTerminateRspSdata_t;
+
+/** AuthenticateTerminate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpAuthenticateTerminateRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTerminateAutenticateRsp_t;
+
+/** AuthenticateTerminate response. */
+typedef struct {
+    /** Response. */
+    cmpTerminateAutenticateRsp_t rsp;
+} cmpRspAuthenticateTerminate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_REGISTER_ACTIVATE \
+  MC_CMP_2_0_CMD_ROOT_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_REGISTER_ACTIVATE_CMD Command_2_0
+ * @{ */
+
+/** RootContRegisterActivate encrypted data command. */
+typedef struct {
+    /** Root authentication key. */
+    mcSymmetricKey_t kRootAuth;
+} cmpRootRegActMsgEdata_t;
+
+/** RootContRegisterActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootRegActMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActMsgEdata_t))];
+} cmpRootRegActCmdEd_t;
+
+/** RootContRegisterActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Rootid. */
+    mcRootid_t rootid;
+    /** Encrypted and padded data. */
+    cmpRootRegActCmdEd_t ed;
+} cmpRootRegActCmdSdata_t;
+
+/** RootContRegisterActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootRegActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContRegisterActivateCmd_t;
+
+/** RootContRegisterActivate command. */
+typedef struct {
+    /** Command. */
+    cmpRootContRegisterActivateCmd_t cmd;
+} cmpCmdRootContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_REGISTER_ACTIVATE_RSP Response_2_0
+ * @{ */
+
+/** RootContRegisterActivate encrypted data response. */
+typedef struct {
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRootRegActRspEdata_t;
+
+/** RootContRegisterActivate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootRegActRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActRspEdata_t))];
+} cmpRootRegActRspEd_t;
+
+/** RootContRegisterActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpRootRegActRspEd_t ed;
+} cmpRootRegActRspSdata_t;
+
+/** RootContRegisterActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootRegActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContRegisterActivateRsp_t;
+
+/** RooContRegisterActivate response. */
+typedef struct {
+    /** Response. */
+    cmpRootContRegisterActivateRsp_t rsp;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRspRootContRegisterActivate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_UNREGISTER \
+  MC_CMP_2_0_CMD_ROOT_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_UNREGISTER_CMD Command_2_0
+ * @{ */
+
+/** RootContUnregister encrypted data command. */
+typedef struct {
+    /** Suid. */
+    mcSuid_t suid;
+    /** AuthToken container secure object. */
+    mcSoAuthTokenCont_t soAuthTokenCont;
+} cmpRootUnregMsgEdata_t;
+
+/** RootContUnregister encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootUnregMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregMsgEdata_t))];
+} cmpRootUnregCmdEd_t;
+
+/** RootContUnregister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Encrypted and padded data. */
+    cmpRootUnregCmdEd_t ed;
+} cmpRootUnregCmdSdata_t;
+
+/** RootContUnregister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootUnregCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnregisterCmd_t;
+
+/** RootContUnregister command. */
+typedef struct {
+    /** Command. */
+    cmpRootContUnregisterCmd_t cmd;
+} cmpCmdRootContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_UNREGISTER_RSP Response_2_0
+ * @{ */
+
+/** RootContUnregister encrypted data response. */
+typedef struct {
+    /** Suid. */
+    mcSuid_t suid;
+} cmpRootUnregRspEdata_t;
+
+/** RootContUnregister encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootUnregRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregRspEdata_t))];
+} cmpRootUnregRspEd_t;
+
+/** RootContUnregister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpRootUnregRspEd_t ed;
+} cmpRootUnregRspSdata_t;
+
+/** RootContUnregister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootUnregRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnregisterRsp_t;
+
+/** RootContUnregister response. */
+typedef struct {
+    /** Response. */
+    cmpRootContUnregisterRsp_t rsp;
+    /** AuthToken container secure object. */
+    mcSoAuthTokenCont_t soAuthTokenCont;
+} cmpRspRootContUnregister_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_LOCK_BY_ROOT \
+  MC_CMP_2_0_CMD_ROOT_CONT_LOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_LOCK_BY_ROOT_CMD Command_2_0
+ * @{ */
+
+/** RootContLockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpRootLockByRootCmdSdata_t;
+
+/** RootContLockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootLockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContLockByRootCmd_t;
+
+/** RootContLockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpRootContLockByRootCmd_t cmd;
+} cmpCmdRootContLockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_LOCK_BY_ROOT_RSP Response_2_0
+ * @{ */
+
+/** RootContLockByRoot encrypted data response. */
+typedef struct {
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRootLockByRootRspEdata_t;
+
+/** RootContLockByRoot encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootLockByRootRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootLockByRootRspEdata_t))];
+} cmpRootLockByRootRspEd_t;
+
+/** RootContLockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpRootLockByRootRspEd_t ed;
+} cmpRootLockByRootRspSdata_t;
+
+/** RootContLockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootLockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContLockByRootRsp_t;
+
+/** RootContLockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpRootContLockByRootRsp_t rsp;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRspRootContLockByRoot_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_UNLOCK_BY_ROOT \
+  MC_CMP_2_0_CMD_ROOT_CONT_UNLOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_UNLOCK_BY_ROOT_CMD Command_2_0
+ * @{ */
+
+/** RootContUnlockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpRootUnlockByRootCmdSdata_t;
+
+/** RootContUnlockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootUnlockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnlockByRootCmd_t;
+
+/** RootContUnlockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpRootContUnlockByRootCmd_t cmd;
+} cmpCmdRootContUnlockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_ROOT_CONT_UNLOCK_BY_ROOT_RSP Response_2_0
+ * @{ */
+
+/** RootContUnlockByRoot encrypted data response. */
+typedef struct {
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRootUnlockByRootRspEdata_t;
+
+/** RootContUnlockByRoot encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootUnlockByRootRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnlockByRootRspEdata_t))];
+} cmpRootUnlockByRootRspEd_t;
+
+/** RootContUnlockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpRootUnlockByRootRspEd_t ed;
+} cmpRootUnlockByRootRspSdata_t;
+
+/** RootContUnlockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootUnlockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnlockByRootRsp_t;
+
+/** RootContUnlockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpRootContUnlockByRootRsp_t rsp;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRspRootContUnlockByRoot_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_REGISTER_ACTIVATE \
+  MC_CMP_2_0_CMD_SP_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_REGISTER_ACTIVATE_CMD Command_2_0
+ * @{ */
+
+/** SpContRegisterActivate encrypted data command. */
+typedef struct {
+    /** Sp authentication key. */
+    mcSymmetricKey_t kSpAuth;
+} cmpSpRegActMsgEdata_t;
+
+/** SpContRegisterActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpRegActMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActMsgEdata_t))];
+} cmpSpRegActCmdEd_t;
+
+/** SpContRegisterActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    /** Encrypted and padded data. */
+    cmpSpRegActCmdEd_t ed;
+} cmpSpRegActCmdSdata_t;
+
+/** SpContRegisterActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpRegActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterActivateCmd_t;
+
+/** SpContRegisterActivate command. */
+typedef struct {
+    /** Command. */
+    cmpSpContRegisterActivateCmd_t cmd;
+} cmpCmdSpContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_REGISTER_ACTIVATE_RSP Response_2_0
+ * @{ */
+
+/** SpContRegisterActivate encrypted data response. */
+typedef struct {
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpRegActRspEdata_t;
+
+/** SpContRegisterActivate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpRegActRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActRspEdata_t))];
+} cmpSpRegActRspEd_t;
+
+/** SpContRegisterActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpRegActRspEd_t ed;
+} cmpSpRegActRspSdata_t;
+
+/** SpContRegisterActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpRegActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterActivateRsp_t;
+
+/** SpContRegisterActivate response. */
+typedef struct {
+    /** Response. */
+    cmpSpContRegisterActivateRsp_t rsp;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContRegisterActivate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNREGISTER \
+ MC_CMP_2_0_CMD_SP_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNREGISTER_CMD Command_2_0
+ * @{ */
+
+/** SpContUnregister signed response. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpContUnregCmdSdata_t;
+
+/** SpContUnregister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpContUnregCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnregisterCmd_t;
+
+/** SpContUnregister command. */
+typedef struct {
+    /** Command. */
+    cmpSpContUnregisterCmd_t cmd;
+} cmpCmdSpContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNREGISTER_RSP Response_2_0
+ * @{ */
+
+/** SpContUnregister encrypted data response. */
+typedef struct {
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpSpUnregRspEdata_t;
+
+/** SpContUnregister encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpUnregRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnregRspEdata_t))];
+} cmpSpUnregRspEd_t;
+
+/** SpContUnregister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpUnregRspEd_t ed;
+} cmpSpContUnregRspSdata_t;
+
+/** SpContUnregister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpContUnregRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnregisterRsp_t;
+
+/** SpContUnregister response. */
+typedef struct {
+    /** Response. */
+    cmpSpContUnregisterRsp_t rsp;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRspSpContUnregister_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_REGISTER \
+  MC_CMP_2_0_CMD_SP_CONT_REGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_REGISTER_CMD Command_2_0
+ * @{ */
+
+/** SpContRegister encrypted data command. */
+typedef struct {
+    /** Sp authentication key. */
+    mcSymmetricKey_t kSpAuth;
+} cmpSpRegisterMsgEdata_t;
+
+/** SpContRegister encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpRegisterMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterMsgEdata_t))];
+} cmpSpRegisterCmdEd_t;
+
+/** SpContRegister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Encrypted and padded data. */
+    cmpSpRegisterCmdEd_t ed;
+} cmpSpRegisterCmdSdata_t;
+
+/** SpContRegister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpRegisterCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterCmd_t;
+
+/** SpContRegister command. */
+typedef struct {
+    /** Command. */
+    cmpSpContRegisterCmd_t cmd;
+} cmpCmdSpContRegister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_REGISTER_RSP Response_2_0
+ * @{ */
+
+/** SpContRegister encrypted data response. */
+typedef struct {
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpRegisterRspEdata_t;
+
+/** SpContRegister encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpRegisterRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterRspEdata_t))];
+} cmpSpRegisterRspEd_t;
+
+/** SpContRegister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpRegisterRspEd_t ed;
+} cmpSpRegisterRspSdata_t;
+
+/** SpContRegister signed response and signature. */
+typedef struct {
+    cmpSpRegisterRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterRsp_t;
+
+/** SpContRegister response. */
+typedef struct {
+    /** Response. */
+    cmpSpContRegisterRsp_t rsp;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContRegister_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_ROOT \
+  MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_ROOT_CMD Command_2_0
+ * @{ */
+
+/** SpContLockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpLockByRootCmdSdata_t;
+
+/** SpContLockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpLockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockByRootCmd_t;
+
+/** SpContLockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpSpContLockByRootCmd_t cmd;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpCmdSpContLockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_ROOT_RSP Response_2_0
+ * @{ */
+
+/** SpContLockByRoot encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpLockByRootRspEdata_t;
+
+/** SpContLockByRoot encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpLockByRootRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpLockByRootRspEdata_t))];
+} cmpSpLockByRootRspEd_t;
+
+/** SpContLockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpLockByRootRspEd_t ed;
+} cmpSpLockByRootRspSdata_t;
+
+/** SpContLockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpLockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockByRootRsp_t;
+
+/** SpContLockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpSpContLockByRootRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContLockByRoot_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_ROOT \
+  MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_ROOT_CMD Command_2_0
+ * @{ */
+
+/** SpContUnlockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpUnlockByRootCmdSdata_t;
+
+/** SpContUnlockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpUnlockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockByRootCmd_t;
+
+/** SpContUnlockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpSpContUnlockByRootCmd_t cmd;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpCmdSpContUnlockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_ROOT_RSP Response_2_0
+ * @{ */
+
+/** SpContUnlockByRoot encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpUnlockByRootRspEdata_t;
+
+/** SpContUnlockByRoot encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpUnlockByRootRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnlockByRootRspEdata_t))];
+} cmpSpUnlockByRootRspEd_t;
+
+/** SpContUnlockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpUnlockByRootRspEd_t ed;
+} cmpSpUnlockByRootRspSdata_t;
+
+/** SpContUnlockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpUnlockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockByRootRsp_t;
+
+/** SpContUnlockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpSpContUnlockByRootRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContUnlockByRoot_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_ACTIVATE \
+  MC_CMP_2_0_CMD_SP_CONT_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_ACTIVATE_CMD Command_2_0
+ * @{ */
+
+/** SpContActivate encrypted data command. */
+typedef struct {
+    /** Sp authentication key. */
+    mcSymmetricKey_t kSpAuth;
+} cmpSpActivateMsgEdata_t;
+
+/** SpContActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpActivateMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateMsgEdata_t))];
+} cmpSpActivateCmdEd_t;
+
+/** SpContActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Encrypted and padded data. */
+    cmpSpActivateCmdEd_t ed;
+} cmpSpActivateCmdSdata_t;
+
+/** SpContActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpActivateCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContActivateCmd_t;
+
+/** SpContActivate command. */
+typedef struct {
+    /** Command. */
+    cmpSpContActivateCmd_t cmd;
+} cmpCmdSpContActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_ACTIVATE_RSP Response_2_0
+ * @{ */
+
+/** SpContActivate encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpActivateRspEdata_t;
+
+/** SpContActivate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpActivateRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateRspEdata_t))];
+} cmpSpActivateRspEd_t;
+
+/** SpContActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpActivateRspEd_t ed;
+} cmpSpActivateRspSdata_t;
+
+/** SpContActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpActivateRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContActivateRsp_t;
+
+/** SpContActivate response. */
+typedef struct {
+    /** Response. */
+    cmpSpContActivateRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContActivate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_SP \
+  MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_SP_CMD Command_2_0
+ * @{ */
+
+/** SpContLockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpLockBySpCmdSdata_t;
+
+/** SpContLockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpLockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockBySpCmd_t;
+
+/** SpContLockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpSpContLockBySpCmd_t cmd;
+} cmpCmdSpContLockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_LOCK_BY_SP_RSP Response_2_0
+ * @{ */
+
+/** SpContLockBySp encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpLockBySpRspEdata_t;
+
+/** SpContLockBySp encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpLockBySpRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpLockBySpRspEdata_t))];
+} cmpSpLockBySpRspEd_t;
+
+/** SpContLockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpLockBySpRspEd_t ed;
+} cmpSpLockBySpRspSdata_t;
+
+/** SpContLockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpLockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockBySpRsp_t;
+
+/** SpContLockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpSpContLockBySpRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContLockBySp_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_SP \
+  MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_SP_CMD Command_2_0
+ * @{ */
+
+/** SpContUnlockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpUnlockBySpCmdSdata_t;
+
+/** SpContUnlockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpUnlockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockBySpCmd_t;
+
+/** SpContUnlockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpSpContUnlockBySpCmd_t cmd;
+} cmpCmdSpContUnlockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_SP_CONT_UNLOCK_BY_SP_RSP Response_2_0
+ * @{ */
+
+/** SpContUnlockBySp encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpUnlockBySpRspEdata_t;
+
+/** SpContUnlockBySp encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpUnlockBySpRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnlockBySpRspEdata_t))];
+} cmpSpUnlockBySpRspEd_t;
+
+/** SpContUnlockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpSpUnlockBySpRspEd_t ed;
+} cmpSpUnlockBySpRspSdata_t;
+
+/** SpContUnlockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpUnlockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockBySpRsp_t;
+
+/** SpContUnlockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpSpContUnlockBySpRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContUnlockBySp_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_REGISTER_ACTIVATE \
+  MC_CMP_2_0_CMD_TLT_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_REGISTER_ACTIVATE_CMD Command_2_0
+ * @{ */
+
+/** TltContRegisterActivate encrypted data command. */
+typedef struct {
+    /** Tlt authentication key. */
+    mcSymmetricKey_t kSpTltEnc;
+} cmpTltRegActMsgEdata_t;
+
+/** TltContRegisterActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltRegActMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActMsgEdata_t))];
+} cmpTltRegActCmdEd_t;
+
+/** TltContRegisterActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+    /** Encrypted and padded data. */
+    cmpTltRegActCmdEd_t ed;
+} cmpTltRegActCmdSdata_t;
+
+/** TltContRegisterActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltRegActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterActivateCmd_t;
+
+/** TltContRegisterActivate command. */
+typedef struct {
+    /** Command. */
+    cmpTltContRegisterActivateCmd_t cmd;
+} cmpCmdTltContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_REGISTER_ACTIVATE_RSP Response_2_0
+ * @{ */
+
+/** TltContRegisterActivate encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpTltRegActRspEdata_t;
+
+/** TltContRegisterActivate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltRegActRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActRspEdata_t))];
+} cmpTltRegActRspEd_t;
+
+/** TltContRegisterActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpTltRegActRspEd_t ed;
+} cmpTltRegActRspSdata_t;
+
+/** TltContRegisterActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltRegActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterActivateRsp_t;
+
+/** TltContRegisterActivate response. */
+typedef struct {
+    /** Response. */
+    cmpTltContRegisterActivateRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpRspTltContRegisterActivate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_UNREGISTER \
+  MC_CMP_2_0_CMD_TLT_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_UNREGISTER_CMD Command_2_0
+ * @{ */
+
+/** TltContUnregister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltUnregCmdSdata_t;
+
+/** TltContUnregister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltUnregCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnregisterCmd_t;
+
+/** TltContUnregister command. */
+typedef struct {
+    /** Command. */
+    cmpTltContUnregisterCmd_t cmd;
+} cmpCmdTltContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_UNREGISTER_RSP Response_2_0
+ * @{ */
+
+/** TltContUnregister encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpTltUnregRspEdata_t;
+
+/** TltContUnregister encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltUnregRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltUnregRspEdata_t))];
+} cmpTltUnregRspEd_t;
+
+/** TltContUnregister signed command. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpTltUnregRspEd_t ed;
+} cmpTltUnregRspSdata_t;
+
+/** TltContUnregister signed command and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltUnregRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnregisterRsp_t;
+
+/** TltContUnregister response. */
+typedef struct {
+    /** Response. */
+    cmpTltContUnregisterRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpRspTltContUnregister_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_REGISTER \
+  MC_CMP_2_0_CMD_TLT_CONT_REGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_REGISTER_CMD Command_2_0
+ * @{ */
+
+/** TltContRegister encrypted data command. */
+typedef struct {
+    /** Tlt authentication key. */
+    mcSymmetricKey_t kSpTltEnc;
+} cmpTltRegMsgEdata_t;
+
+/** TltContRegister encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltRegMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegMsgEdata_t))];
+} cmpTltRegCmdEd_t;
+
+/** TltContRegister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+    /** Encrypted and padded data. */
+    cmpTltRegCmdEd_t ed;
+} cmpTltRegCmdSdata_t;
+
+/** TltContRegister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltRegCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterCmd_t;
+
+/** TltContRegister command. */
+typedef struct {
+    /** Command. */
+    cmpTltContRegisterCmd_t cmd;
+} cmpCmdTltContRegister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_REGISTER_RSP Response_2_0
+ * @{ */
+
+/** TltContRegister encrypted data response. */
+typedef struct {
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpTltRegRspEdata_t;
+
+/** TltContRegister encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltRegRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegRspEdata_t))];
+} cmpTltRegRspEd_t;
+
+/** TltContRegister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpTltRegRspEd_t ed;
+} cmpTltRegRspSdata_t;
+
+/** TltContRegister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltRegRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterRsp_t;
+
+/** TltContRegister response. */
+typedef struct {
+    /** Response. */
+    cmpTltContRegisterRsp_t rsp;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpRspTltContRegister_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_ACTIVATE \
+  MC_CMP_2_0_CMD_TLT_CONT_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_ACTIVATE_CMD Command_2_0
+ * @{ */
+
+/** TltContActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltActCmdSdata_t;
+
+/** TltContActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContActivateCmd_t;
+
+/** TltContActivate command. */
+typedef struct {
+    /** Command. */
+    cmpTltContActivateCmd_t cmd;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpCmdTltContActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_ACTIVATE_RSP Response_2_0
+ * @{ */
+
+/** TltContActivate encrypted data response. */
+typedef struct {
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpTltActRspEdata_t;
+
+/** TltContActivate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltActRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltActRspEdata_t))];
+} cmpTltActRspEd_t;
+
+/** TltContActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpTltActRspEd_t ed;
+} cmpTltActRspSdata_t;
+
+/** TltContActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContActivateRsp_t;
+
+/** TltContActivate response. */
+typedef struct {
+    /** Response. */
+    cmpTltContActivateRsp_t rsp;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpRspTltContActivate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_LOCK_BY_SP \
+  MC_CMP_2_0_CMD_TLT_CONT_LOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_LOCK_BY_SP_CMD Command_2_0
+ * @{ */
+
+/** TltContLockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltLockBySpCmdSdata_t;
+
+/** TltContLockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltLockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContLockBySpCmd_t;
+
+/** TltContLockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpTltContLockBySpCmd_t cmd;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpCmdTltContLockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_LOCK_BY_SP_RSP Response_2_0
+ * @{ */
+
+/** TltContLockBySp encrypted data response. */
+typedef struct {
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpTltLockBySpRspEdata_t;
+
+/** TltContLockBySp encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltLockBySpRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltLockBySpRspEdata_t))];
+} cmpTltLockBySpRspEd_t;
+
+/** TltContLockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpTltLockBySpRspEd_t ed;
+} cmpTltLockBySpRspSdata_t;
+
+/** TltContLockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltLockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContLockBySpRsp_t;
+
+/** TltContLockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpTltContLockBySpRsp_t rsp;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpRspTltContLockBySp_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_UNLOCK_BY_SP \
+  MC_CMP_2_0_CMD_TLT_CONT_UNLOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_UNLOCK_BY_SP_CMD Command_2_0
+ * @{ */
+
+/** TltContUnlockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltUnlockBySpCmdSdata_t;
+
+/** TltContUnlockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltUnlockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnlockBySpCmd_t;
+
+/** TltContUnlockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpTltContUnlockBySpCmd_t cmd;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpCmdTltContUnlockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_UNLOCK_BY_SP_RSP Response_2_0
+ * @{ */
+
+/** TltContUnlockBySp encrypted data response. */
+typedef struct {
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpTltUnlockBySpRspEdata_t;
+
+/** TltContUnlockBySp encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltUnlockBySpRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltUnlockBySpRspEdata_t))];
+} cmpTltUnlockBySpRspEd_t;
+
+/** TltContUnlockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data. */
+    cmpTltUnlockBySpRspEd_t ed;
+} cmpTltUnlockBySpRspSdata_t;
+
+/** TltContUnlockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltUnlockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnlockBySpRsp_t;
+
+/** TltContUnlockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpTltContUnlockBySpRsp_t rsp;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpRspTltContUnlockBySp_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_PERSONALIZE \
+  MC_CMP_2_0_CMD_TLT_CONT_PERSONALIZE
+ * @{ */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_PERSONALIZE_CMD Command_2_0
+ * @{ */
+
+/** TltContPersonalize encrypted data command. */
+typedef struct {
+    /** Pid. */
+    mcPid_t pid;
+    /** Data. */
+    mcCoDataCont_t persoData;
+} cmpTltContPersonalizeCmdEdata_t;
+
+/** TltContPersonalize encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltContPersonalizeCmdEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeCmdEdata_t))];
+} cmpTltContPersonalizeCmdEd_t;
+
+/** TltContPersonalize signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpTltContPersonalizeCmdEd_t ed;
+} cmpTltContPersonalizeCmdSdata_t;
+
+/** TltContPersonalize signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltContPersonalizeCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContPersonalizeCmd_t;
+
+/** TltContPersonalize command. */
+typedef struct {
+    /** Command. */
+    cmpTltContPersonalizeCmd_t cmd;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_0_t soTltCont;
+} cmpCmdTltContPersonalize_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_2_0_CMD_TLT_CONT_PERSONLIZE_RSP Response_2_0
+ * @{ */
+
+/** TltContPersonalize encrypted data response. */
+typedef struct {
+    /** Data container secure object. */
+    mcSoDataCont_t soDataCont;
+} cmpTltContPersonalizeRspEdata_t;
+
+/** TltContPersonalize encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltContPersonalizeRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeRspEdata_t))];
+} cmpTltContPersonalizeRspEd_t;
+
+/** TltContPersonalize signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpTltContPersonalizeRspEd_t ed;
+} cmpTltContPersonalizeRspSdata_t;
+
+/** TltContPersonalize signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltContPersonalizeRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContPersonalizeRsp_t;
+
+/** TltContPersonalize response. */
+typedef struct {
+    /** Response. */
+    cmpTltContPersonalizeRsp_t rsp;
+    /** Data container secure object. */
+    mcSoDataCont_t soDataCont;
+} cmpRspTltContPersonalize_t;
+
+/** @} */
+
+/** @} */
+
+#endif // CMP_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/2.0/tlCmApi.h b/mobicore/tlcm/TlCm/2.0/tlCmApi.h
new file mode 100644 (file)
index 0000000..df4217d
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_2_0
+ * @{
+ * @file
+ * Interface to content management trustlet (TlCm) definitions.
+ *
+ * The TlCm is responsible for implementing content management protocol (CMP)
+ * 2.0 commands and generating approriate CMP 2.0 responses in the trustlet
+ * control interface (TCI).
+ */
+
+#ifndef TL_CM_API_H_
+#define TL_CM_API_H_
+
+#include "TlCm/tlCmApiCommon.h"
+#include "TlCm/2.0/cmp.h"
+
+/** TCI CMP 2.0 messages. */
+typedef union {
+    /** Command header. */
+    cmpCommandHeader_t commandHeader;
+    /** Response header. */
+    cmpResponseHeader_t responseHeader;
+
+    /** System command GetVersion. */
+    cmpCmdGetVersion_t cmpCmdGetVersion;
+    /** System response GetVersion. */
+    cmpRspGetVersion_t cmpRspGetVersion;
+    /** System command GetSuid. */
+    cmpCmdGetSuid_t cmpCmdGetSuid;
+    /** System response GetSuid. */
+    cmpRspGetSuid_t cmpRspGetSuid;
+    /** System command GenAuthToken. */
+    cmpCmdGenAuthToken_t cmpCmdGenAuthToken;
+    /** System response GenAuthToken. */
+    cmpRspGenAuthToken_t cmpRspGenAuthToken;
+
+    /** Authentication command BeginSocAuthentication. */
+    cmpCmdBeginSocAuthentication_t cmpCmdBeginSocAuthentication;
+    /** Authentication response BeginSocAuthentication. */
+    cmpRspBeginSocAuthentication_t cmpRspBeginSocAuthentication;
+    /** Authentication command BeginRootAuthentication. */
+    cmpCmdBeginRootAuthentication_t cmpCmdBeginRootAuthentication;
+    /** Authentication response BeginRootAuthentication. */
+    cmpRspBeginRootAuthentication_t cmpRspBeginRootAuthentication;
+    /** Authentication command BeginSpAuthentication. */
+    cmpCmdBeginSpAuthentication_t cmpCmdBeginSpAuthentication;
+    /** Authentication response BeginSpAuthentication. */
+    cmpRspBeginSpAuthentication_t cmpRspBeginSpAuthentication;
+    /** Authentication command Authenticate. */
+    cmpCmdAuthenticate_t cmpCmdAuthenticate;
+    /** Authentication response Authenticate. */
+    cmpRspAuthenticate_t cmpRspAuthenticate;
+    /** Authentication command AuthenticateTerminate. */
+    cmpCmdAuthenticateTerminate_t cmpCmdAuthenticateTerminate;
+    /** Authentication response AuthenticateTerminate. */
+    cmpRspAuthenticateTerminate_t cmpRspAuthenticateTerminate;
+
+    /** SoC administrative command RootContRegisterActivate. */
+    cmpCmdRootContRegisterActivate_t cmpCmdRootContRegisterActivate;
+    /** SoC administrative response RootContRegisterActivate. */
+    cmpRspRootContRegisterActivate_t cmpRspRootContRegisterActivate;
+
+    /** Root administrative command RootContUnregister. */
+    cmpCmdRootContUnregister_t cmpCmdRootContUnregister;
+    /** Root administrative response RootContUnregister. */
+    cmpRspRootContUnregister_t cmpRspRootContUnregister;
+    /** Root administrative command RootContLockByRoot. */
+    cmpCmdRootContLockByRoot_t cmpCmdRootContLockByRoot;
+    /** Root administrative response RootContLockByRoot. */
+    cmpRspRootContLockByRoot_t cmpRspRootContLockByRoot;
+    /** Root administrative command RootContUnlockByRoot. */
+    cmpCmdRootContUnlockByRoot_t cmpCmdRootContUnlockByRoot;
+    /** Root administrative command RootContUnlockByRoot. */
+    cmpRspRootContUnlockByRoot_t cmpRspRootContUnlockByRoot;
+    /** Root administrative command SpContRegisterActivate. */
+    cmpCmdSpContRegisterActivate_t cmpCmdSpContRegisterActivate;
+    /** Root administrative response SpContRegisterActivate. */
+    cmpRspSpContRegisterActivate_t cmpRspSpContRegisterActivate;
+    /** Root administrative command SpContUnregister. */
+    cmpCmdSpContUnregister_t cmpCmdSpContUnregister;
+    /** Root administrative response SpContUnregister. */
+    cmpRspSpContUnregister_t cmpRspSpContUnregister;
+    /** Root administrative command SpContRegister. */
+    cmpCmdSpContRegister_t cmpCmdSpContRegister;
+    /** Root administrative response SpContRegister. */
+    cmpRspSpContRegister_t cmpRspSpContRegister;
+    /** Root administrative command SpContLockByRoot. */
+    cmpCmdSpContLockByRoot_t cmpCmdSpContLockByRoot;
+    /** Root administrative response SpContLockByRoot. */
+    cmpRspSpContLockByRoot_t cmpRspSpContLockByRoot;
+    /** Root administrative command SpContUnlockByRoot. */
+    cmpCmdSpContUnlockByRoot_t cmpCmdSpContUnlockByRoot;
+    /** Root administrative response SpContUnlockByRoot. */
+    cmpRspSpContUnlockByRoot_t cmpRspSpContUnlockByRoot;
+
+    /** Sp administrative command SpContActivate. */
+    cmpCmdSpContActivate_t cmpCmdSpContActivate;
+    /** Sp administrative response SpContActivate. */
+    cmpRspSpContActivate_t cmpRspSpContActivate;
+    /** Sp administrative command SpContLockBySp. */
+    cmpCmdSpContLockBySp_t cmpCmdSpContLockBySp;
+    /** Sp administrative response SpContLockBySp. */
+    cmpRspSpContLockBySp_t cmpRspSpContLockBySp;
+    /** Sp administrative command SpContUnlockBySp. */
+    cmpCmdSpContUnlockBySp_t cmpCmdSpContUnlockBySp;
+    /** Sp administrative command SpContUnlockBySp. */
+    cmpRspSpContUnlockBySp_t cmpRspSpContUnlockBySp;
+    /** Sp administrative command TltContRegisterActivate. */
+    cmpCmdTltContRegisterActivate_t cmpCmdTltContRegisterActivate;
+    /** Sp administrative response TltContRegisterActivate. */
+    cmpRspTltContRegisterActivate_t cmpRspTltContRegisterActivate;
+    /** Sp administrative command TltContUnregister. */
+    cmpCmdTltContUnregister_t cmpCmdTltContUnregister;
+    /** Sp administrative response TltContUnregister. */
+    cmpRspTltContUnregister_t cmpRspTltContUnregister;
+    /** Sp administrative command TltContRegister. */
+    cmpCmdTltContRegister_t cmpCmdTltContRegister;
+    /** Sp administrative response TltContRegister. */
+    cmpRspTltContRegister_t cmpRspTltContRegister;
+    /** Sp administrative command TltContActivate. */
+    cmpCmdTltContActivate_t cmpCmdTltContActivate;
+    /** Sp administrative response TltContActivate. */
+    cmpRspTltContActivate_t cmpRspTltContActivate;
+    /** Sp administrative command TltContLockBySp. */
+    cmpCmdTltContLockBySp_t cmpCmdTltContLockBySp;
+    /** Sp administrative response TltContLockBySp. */
+    cmpRspTltContLockBySp_t cmpRspTltContLockBySp;
+    /** Sp administrative command TltContUnlockBySp. */
+    cmpCmdTltContUnlockBySp_t cmpCmdTltContUnlockBySp;
+    /** Sp administrative response TltContUnlockBySp. */
+    cmpRspTltContUnlockBySp_t cmpRspTltContUnlockBySp;
+    /** Sp administrative command TltContPersonalize. */
+    cmpCmdTltContPersonalize_t cmpCmdTltContPersonalize;
+    /** Sp administrative response TltContPersonalize. */
+    cmpRspTltContPersonalize_t cmpRspTltContPersonalize;
+} cmpMessage_t;
+
+/** TCI CMP 2.0. */
+typedef struct {
+    /** TCI CMP 2.0 messages. */
+    cmpMessage_t msg;
+} cmp_t;
+
+#endif // TL_CM_API_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/3.0/cmp.h b/mobicore/tlcm/TlCm/3.0/cmp.h
new file mode 100644 (file)
index 0000000..6abb747
--- /dev/null
@@ -0,0 +1,1004 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP
+ * Content Management Protocol Definitions.
+ *
+ * The content management protocol (CMP) is based on the trustlet control
+ * interface (TCI) and CMP mapped interfaces. It defines commands/responses
+ * with the content management trustlet (TlCm).
+ *
+ * @{
+ *
+ * @file
+ * CMP TCI global definitions.
+ * Various components need access to (sub-)structures defined and used by CMP;
+ * these common definitions are made available through this header file.
+ */
+
+#ifndef CMP_H_
+#define CMP_H_
+
+#include "TlCm/cmpCommon.h"
+
+/** Info of the whole mapped memory with NWd. */
+typedef struct {
+    /** Address of the mapped memory. */
+#if ( __WORDSIZE == 64 )
+    uint32_t addr;         /**< The virtual address of the Bulk buffer regarding the address space of the Trusted Application, already includes a possible offset! */
+#else
+    void* addr;
+#endif
+    /** Size of the mapped memory. */
+    uint32_t len;
+} cmpMapInfo_t;
+
+/** Info of the mapped element from a CMP message with NWd. */
+typedef struct {
+    /** Offset of the mapped element in the mapped memory. */
+    uint32_t offset;
+    /** Size of the mapped element. */
+    uint32_t len;
+} cmpMapOffsetInfo_t;
+
+/** TCI CMP command header. */
+typedef struct {
+    /** CMP version. */
+    cmpVersionId_t version;
+    /** Command id. */
+    cmpCommandId_t commandId;
+    /** Info of the whole mapped memory with NWd. */
+    cmpMapInfo_t mapInfo;
+    /** Info of the mapped CMP command with NWd. */
+    cmpMapOffsetInfo_t cmpCmdMapOffsetInfo;
+} cmpCommandHeaderTci_t;
+
+/** TCI CMP response header. */
+typedef struct {
+    /** CMP version. */
+    cmpVersionId_t version;
+    /** Response id (must be command id | RSP_ID_MASK ). */
+    cmpResponseId_t responseId;
+    /** Required lenght (return 0 if lenght is enough) of the mapped memory
+     * with NWd. */
+    uint32_t len;
+} cmpResponseHeaderTci_t;
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_TCI \
+   MC_CMP_CMD_GET_VERSION_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_TCI_CMD Command
+ * @{ */
+
+/** GetVersion TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdGetVersionTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_TCI_RSP Response
+ * @{ */
+
+/** GetVersion TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspGetVersionTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GET_SUID_TCI \
+  MC_CMP_CMD_GET_SUID_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_TCI_CMD Command
+ * @{ */
+
+/** GetSuid TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdGetSuidTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_TCI_RSP Response
+ * @{ */
+
+/** GetSuid TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspGetSuidTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_TCI \
+ MC_CMP_CMD_GENERATE_AUTH_TOKEN_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_TCI_CMD Command
+ * @{ */
+
+/** GenAuthToken TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdGenAuthTokenTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_TCI_RSP Response
+ * @{ */
+
+/** GenAuthToken TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeaderTci;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped AuthTokenCont with NWd. */
+    cmpMapOffsetInfo_t cmpAuthTokenContMapOffsetInfo;
+} cmpRspGenAuthTokenTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_BINDING_KEY_TCI \
+ MC_CMP_CMD_GENERATE_BINDING_KEY_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_GENERATE_BINDING_KEY_TCI_CMD Command
+ * @{ */
+
+/** GenBindingKey TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdGenBindingKeyTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_BINDING_KEY_TCI_RSP Response
+ * @{ */
+
+/** GenAuthToken TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeaderTci;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped AuthTokenCont with NWd. */
+    cmpMapOffsetInfo_t cmpAuthTokenContMapOffsetInfo;
+} cmpRspGenBindingKeyTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_TCI \
+  MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_TCI_CMD Command
+ * @{ */
+
+/** BeginSocAuthentication TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped AuthTokenCont with NWd. */
+    cmpMapOffsetInfo_t cmpAuthTokenContMapOffsetInfo;
+} cmpCmdBeginSocAuthenticationTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_TCI_RSP Response
+ * @{ */
+
+/** BeginSocAuthentication TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspBeginSocAuthenticationTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_TCI \
+  MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_TCI_CMD Command
+ * @{ */
+
+/** BeginRootAuthentication TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+} cmpCmdBeginRootAuthenticationTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_TCI_RSP Response
+ * @{ */
+
+/** BeginRootAuthentication TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspBeginRootAuthenticationTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_TCI \
+  MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_TCI_CMD Command
+ * @{ */
+
+/** BeginSpAuthentication TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpCmdBeginSpAuthenticationTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_TCI_RSP Response
+ * @{ */
+
+/** BeginSpAuthentication TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspBeginSpAuthenticationTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TCI \
+  MC_CMP_CMD_AUTHENTICATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TCI_CMD Command
+ * @{ */
+
+/** Authenticate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdAuthenticateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TCI_RSP Response
+ * @{ */
+
+/** Authenticate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspAuthenticateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_TCI \
+  MC_CMP_CMD_AUTHENTICATE_TERMINATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_TCI_CMD Command
+ * @{ */
+
+/** AuthenticateTerminate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdAuthenticateTerminateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_TCI_RSP Response
+ * @{ */
+
+/** AuthenticateTerminate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspAuthenticateTerminateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_TCI \
+  MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_TCI_CMD Command
+ * @{ */
+
+/** RootContRegisterActivate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdRootContRegisterActivateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_TCI_RSP Response
+ * @{ */
+
+/** RootContRegisterActivate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+} cmpRspRootContRegisterActivateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_TCI \
+  MC_CMP_CMD_ROOT_CONT_UNREGISTER_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_TCI_CMD Command
+ * @{ */
+
+/** RootContUnregister TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdRootContUnregisterTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_TCI_RSP Response
+ * @{ */
+
+/** RootContUnregister TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+} cmpRspRootContUnregisterTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_TCI \
+  MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_TCI_CMD Command
+ * @{ */
+
+/** RootContLockByRoot TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdRootContLockByRootTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_TCI_RSP Response
+ * @{ */
+
+/** RootContLockByRoot TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+} cmpRspRootContLockByRootTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_TCI \
+  MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_TCI_CMD Command
+ * @{ */
+
+/** RootContUnlockByRoot TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdRootContUnlockByRootTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_TCI_RSP Response
+ * @{ */
+
+/** RootContUnlockByRoot TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+} cmpRspRootContUnlockByRootTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_TCI \
+  MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_TCI_CMD Command
+ * @{ */
+
+/** SpContRegisterActivate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdSpContRegisterActivateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_TCI_RSP Response
+ * @{ */
+
+/** SpContRegisterActivate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContRegisterActivateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_TCI \
+  MC_CMP_CMD_SP_CONT_UNREGISTER_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_TCI_CMD Command
+ * @{ */
+
+/** SpContUnregister TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdSpContUnregisterTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_TCI_RSP Response
+ * @{ */
+
+/** SpContUnregister TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+} cmpRspSpContUnregisterTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_TCI \
+  MC_CMP_CMD_SP_CONT_REGISTER_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_TCI_CMD Command
+ * @{ */
+
+/** SpContRegister TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdSpContRegisterTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_TCI_RSP Response
+ * @{ */
+
+/** SpContRegister TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped RootCont with NWd. */
+    cmpMapOffsetInfo_t cmpRootContMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContRegisterTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_TCI \
+  MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_TCI_CMD Command
+ * @{ */
+
+/** SpContLockByRoot TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpCmdSpContLockByRootTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_TCI_RSP Response
+ * @{ */
+
+/** SpContLockByRoot TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContLockByRootTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_TCI \
+  MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_TCI_CMD Command
+ * @{ */
+
+/** SpContUnlockByRoot TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpCmdSpContUnlockByRootTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_TCI_RSP Response
+ * @{ */
+
+/** SpContUnlockByRoot TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContUnlockByRootTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_TCI \
+  MC_CMP_CMD_SP_CONT_ACTIVATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_TCI_CMD Command
+ * @{ */
+
+/** SpContActivate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdSpContActivateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_TCI_RSP Response
+ * @{ */
+
+/** SpContActivate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContActivateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_TCI \
+  MC_CMP_CMD_SP_CONT_LOCK_BY_SP_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_TCI_CMD Command
+ * @{ */
+
+/** SpContLockBySp TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdSpContLockBySpTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_TCI_RSP Response
+ * @{ */
+
+/** SpContLockBySp TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContLockBySpTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_TCI \
+  MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_TCI_CMD Command
+ * @{ */
+
+/** SpContUnlockBySp TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdSpContUnlockBySpTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_TCI_RSP Response
+ * @{ */
+
+/** SpContUnlockBySp TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspSpContUnlockBySpTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_TCI \
+  MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_TCI_CMD Command
+ * @{ */
+
+/** TltContRegisterActivate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdTltContRegisterActivateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_TCI_RSP Response
+ * @{ */
+
+/** TltContRegisterActivate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpRspTltContRegisterActivateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_TCI \
+  MC_CMP_CMD_TLT_CONT_UNREGISTER_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_TCI_CMD Command
+ * @{ */
+
+/** TltContUnregister TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdTltContUnregisterTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_TCI_RSP Response
+ * @{ */
+
+/** TltContUnregister TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+} cmpRspTltContUnregisterTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_TCI \
+  MC_CMP_CMD_TLT_CONT_REGISTER_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_TCI_CMD Command
+ * @{ */
+
+/** TltContRegister TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+} cmpCmdTltContRegisterTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_TCI_RSP Response
+ * @{ */
+
+/** TltContRegister TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped SpCont with NWd. */
+    cmpMapOffsetInfo_t cmpSpContMapOffsetInfo;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpRspTltContRegisterTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_TCI \
+  MC_CMP_CMD_TLT_CONT_ACTIVATE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_TCI_CMD Command
+ * @{ */
+
+/** TltContActivate TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpCmdTltContActivateTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_TCI_RSP Response
+ * @{ */
+
+/** TltContActivate TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpRspTltContActivateTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_TCI \
+  MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_TCI_CMD Command
+ * @{ */
+
+/** TltContLockBySp TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpCmdTltContLockBySpTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_TCI_RSP Response
+ * @{ */
+
+/** TltContLockBySp TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpRspTltContLockBySpTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_TCI \
+  MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_TCI_CMD Command
+ * @{ */
+
+/** TltContUnlockBySp TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpCmdTltContUnlockBySpTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_TCI_RSP Response
+ * @{ */
+
+/** TltContUnlockBySp TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpRspTltContUnlockBySpTci_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_TCI \
+  MC_CMP_CMD_TLT_CONT_PERSONALIZE_TCI
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_TCI_CMD Command
+ * @{ */
+
+/** TltContPersonalize TCI command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderTci_t cmdHeader;
+    /** Offset of the mapped TltCont with NWd. */
+    cmpMapOffsetInfo_t cmpTltContMapOffsetInfo;
+} cmpCmdTltContPersonalizeTci_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_TCI_RSP Response
+ * @{ */
+
+/** TltContPersonalize TCI response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderTci_t rspHeader;
+    /** Offset of the mapped CMP response with NWd. */
+    cmpMapOffsetInfo_t cmpRspMapOffsetInfo;
+    /** Offset of the mapped PersonalizeData with NWd. */
+    cmpMapOffsetInfo_t cmpTltContPersoMapOffsetInfo;
+} cmpRspTltContPersonalizeTci_t;
+
+/** @} */
+
+/** @} */
+
+#endif // CMP_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/3.0/cmpMap.h b/mobicore/tlcm/TlCm/3.0/cmpMap.h
new file mode 100644 (file)
index 0000000..56d7fff
--- /dev/null
@@ -0,0 +1,2143 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP
+ * Content Management Protocol Definitions.
+ *
+ * The content management protocol (CMP) is based on the trustlet control
+ * interface (TCI) and CMP mapped interfaces. It defines commands/responses with
+ * the content management trustlet (TlCm).
+ *
+ * @{
+ *
+ * @file
+ * CMP mapped global definitions.
+ * Various components need access to (sub-)structures defined and used by CMP;
+ * these common definitions are made available through this header file.
+ */
+
+#ifndef CMP_MAP_H_
+#define CMP_MAP_H_
+
+#include "TlCm/3.0/cmp.h"
+
+/** Map CMP GetVersion message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdGetVersion_t cmpCmdGetVersion;
+    /** Map CMP response. */
+    cmpRspGetVersion_t cmpRspGetVersion;
+} cmpMapGetVersion_t;
+
+/** Map CMP GetSuid message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdGetSuid_t cmpCmdGetSuid;
+    /** Map CMP response. */
+    cmpRspGetSuid_t cmpRspGetSuid;
+} cmpMapGetSuid_t;
+
+/** Map CMP GenAuthToken message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdGenAuthToken_t cmpCmdGenAuthToken;
+    /** Map CMP response. */
+    cmpRspGenAuthToken_t cmpRspGenAuthToken;
+} cmpMapGenAuthToken_t;
+
+/** Map CMP GenBindingKey message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdGenBindingKey_t cmpCmdGenBindingKey;
+    /** Map CMP response. */
+    cmpRspGenBindingKey_t cmpRspGenBindingKey;
+} cmpMapGenBindingKey_t;
+
+/** Map CMP command header. */
+typedef struct {
+    /** Command id. */
+    cmpCommandId_t commandId;
+    /** Size of command. */
+    uint32_t len;
+    /** Reserved. */
+    uint32_t reserved;
+} cmpCommandHeaderMap_t;
+
+/** Map CMP response header. */
+typedef struct {
+    /** Return id. */
+    cmpResponseId_t responseId;
+    /** Return code. */
+    cmpReturnCode_t returnCode;
+    /** Size of response. */
+    uint32_t len;
+    /** Reserved. */
+    uint32_t reserved;
+} cmpResponseHeaderMap_t;
+
+/** Map CMP message header. */
+typedef union {
+    /** Map CMP command. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Map CMP response. */
+    cmpResponseHeaderMap_t rspHeader;
+} cmpMapHeader_t;
+
+/** CMP error signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpErrorRsp_t;
+
+/** Map CMP error response. */
+typedef struct {
+    /** Response. */
+    cmpErrorRsp_t rsp;
+} cmpMapError_t;
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION \
+  MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_CMD Command
+ * @{ */
+
+/** BeginSocAuthentication non signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+} cmpBeginSocAuthenticationCmd_t;
+
+/** BeginSocAuthentication command. */
+typedef struct {
+    /** Command. */
+    cmpBeginSocAuthenticationCmd_t cmd;
+} cmpCmdBeginSocAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_RSP Response
+ * @{ */
+
+/** BeginSocAuthentication signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+} cmpBeginSocAuthenticationRspSdata_t;
+
+/** BeginSocAuthentication signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpBeginSocAuthenticationRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpBeginSocAuthenticationRsp_t;
+
+/** BeginSocAuthentication response. */
+typedef struct {
+    /** Response. */
+    cmpBeginSocAuthenticationRsp_t rsp;
+} cmpRspBeginSocAuthentication_t;
+
+/** @} */
+
+/** Map CMP BeginSocAuthentication message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdBeginSocAuthentication_t cmpCmdBeginSocAuthentication;
+    /** Map CMP response. */
+    cmpRspBeginSocAuthentication_t cmpRspBeginSocAuthentication;
+} cmpMapBeginSocAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION \
+  MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_CMD Command
+ * @{ */
+
+/** BeginRootAuthentication non signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+} cmpBeginRootAuthenticationCmd_t;
+
+/** BeginRootAuthentication command. */
+typedef struct {
+    /** Command. */
+    cmpBeginRootAuthenticationCmd_t cmd;
+} cmpCmdBeginRootAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_RSP Response
+ * @{ */
+
+/** BeginRootAuthentication signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+} cmpBeginRootAuthenticationRspSdata_t;
+
+/** BeginRootAuthentication signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpBeginRootAuthenticationRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpBeginRootAuthenticationRsp_t;
+
+/** BeginRootAuthentication response. */
+typedef struct {
+    /** Response. */
+    cmpBeginRootAuthenticationRsp_t rsp;
+} cmpRspBeginRootAuthentication_t;
+
+/** @} */
+
+/** Map CMP BeginRootAuthentication message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdBeginRootAuthentication_t cmpCmdBeginRootAuthentication;
+    /** Map CMP response. */
+    cmpRspBeginRootAuthentication_t cmpRspBeginRootAuthentication;
+} cmpMapBeginRootAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION \
+  MC_CMP_CMD_BEGIN_SP_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_CMD Command
+ * @{ */
+
+/** BeginSpAuthentication non signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpBeginSpAuthenticationCmd_t;
+
+/** BeginSpAuthentication command. */
+typedef struct {
+    /** Command. */
+    cmpBeginSpAuthenticationCmd_t cmd;
+} cmpCmdBeginSpAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_RSP Response
+ * @{ */
+
+/** BeginSpAuthentication signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** Spid. */
+    mcSpid_t spid;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+} cmpBeginSpAuthenticationRspSdata_t;
+
+/** BeginSpAuthentication signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpBeginSpAuthenticationRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpBeginSpAuthenticationRsp_t;
+
+/** BeginSpAuthentication response. */
+typedef struct {
+    /** Response. */
+    cmpBeginSpAuthenticationRsp_t rsp;
+} cmpRspBeginSpAuthentication_t;
+
+/** @} */
+
+/** Map CMP BeginSpAuthentication message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdBeginSpAuthentication_t cmpCmdBeginSpAuthentication;
+    /** Map CMP response. */
+    cmpRspBeginSpAuthentication_t cmpRspBeginSpAuthentication;
+} cmpMapBeginSpAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE MC_CMP_CMD_AUTHENTICATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_CMD Command
+ * @{ */
+
+/** Authenticate encrypted data command. */
+typedef struct {
+    /** NWd authentication random number. */
+    cmpRnd8_t rnd2;
+    /** Suid. */
+    mcSuid_t suid;
+    /** EntityId. */
+    uint32_t entityId;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+    /** NWd authentication random seed. */
+    cmpRnd32_t k2;
+} cmpAuthMsgEdata_t;
+
+/** Authenticate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpAuthMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthMsgEdata_t))];
+} cmpAuthCmdEd_t;
+
+/** Authenticate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpAuthCmdEd_t ed;
+} cmpAuthCmdSdata_t;
+
+/** Authenticate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpAuthCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAuthenticateCmd_t;
+
+/** Authenticate command. */
+typedef struct {
+    /** Command. */
+    cmpAuthenticateCmd_t cmd;
+} cmpCmdAuthenticate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_RSP Response
+ * @{ */
+
+/** Authenticate encrypted data response. */
+typedef struct {
+    /** NWd authentication random number. */
+    cmpRnd8_t rnd2;
+    /** Suid. */
+    mcSuid_t suid;
+    /** EntityId. */
+    uint32_t entityId;
+    /** SWd authentication random number. */
+    cmpRnd8_t rnd1;
+    /** SWd authentication random seed. */
+    cmpRnd32_t k1;
+} cmpAuthRspEdata_t;
+
+/** Authenticate encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpAuthRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthRspEdata_t))];
+} cmpAuthRspEd_t;
+
+/** Authenticate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpAuthRspEd_t ed;
+} cmpAuthRspSdata_t;
+
+/** Authenticate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpAuthRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAuthenticateRsp_t;
+
+/** Authenticate response. */
+typedef struct {
+    /** Response. */
+    cmpAuthenticateRsp_t rsp;
+} cmpRspAuthenticate_t;
+
+/** @} */
+
+/** Map CMP Authenticate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdAuthenticate_t cmpCmdAuthenticate;
+    /** Map CMP response. */
+    cmpRspAuthenticate_t cmpRspAuthenticate;
+} cmpMapAuthenticate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE \
+  MC_CMP_CMD_AUTHENTICATE_TERMINATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_CMD Command
+ * @{ */
+
+/** AuthenticateTerminate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+} cmpAuthenticateTerminateCmdSdata_t;
+
+/** AuthenticateTerminate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpAuthenticateTerminateCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAuthenticateTerminateCmd_t;
+
+/** AuthenticateTerminate command. */
+typedef struct {
+    /** Command. */
+    cmpAuthenticateTerminateCmd_t cmd;
+} cmpCmdAuthenticateTerminate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_RSP Response
+ * @{ */
+
+/** AuthenticateTerminate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+} cmpAuthenticateTerminateRspSdata_t;
+
+/** AuthenticateTerminate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpAuthenticateTerminateRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpAutenticateTerminateRsp_t;
+
+/** AuthenticateTerminate response. */
+typedef struct {
+    /** Response. */
+    cmpAutenticateTerminateRsp_t rsp;
+} cmpRspAuthenticateTerminate_t;
+
+/** @} */
+
+/** Map CMP AuthenticateTerminate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdAuthenticateTerminate_t cmpCmdAuthenticateTerminate;
+    /** Map CMP response. */
+    cmpRspAuthenticateTerminate_t cmpRspAuthenticateTerminate;
+} cmpMapAuthenticateTerminate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE \
+  MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_CMD Command
+ * @{ */
+
+/** RootContRegisterActivate encrypted data command. */
+typedef struct {
+    /** Root authentication key. */
+    mcSymmetricKey_t kRootAuth;
+} cmpRootRegActMsgEdata_t;
+
+/** RootContRegisterActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootRegActMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActMsgEdata_t))];
+} cmpRootRegActCmdEd_t;
+
+/** RootContRegisterActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Rootid. */
+    mcRootid_t rootid;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpRootRegActCmdEd_t ed;
+} cmpRootRegActCmdSdata_t;
+
+/** RootContRegisterActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootRegActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContRegisterActivateCmd_t;
+
+/** RootContRegisterActivate command. */
+typedef struct {
+    /** Command. */
+    cmpRootContRegisterActivateCmd_t cmd;
+} cmpCmdRootContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_RSP Response
+ * @{ */
+
+/** RootContRegisterActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Root container secure object size. */
+    uint32_t soRootContLen;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRootRegActRspSdata_t;
+
+/** RootContRegisterActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootRegActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContRegisterActivateRsp_t;
+
+/** RooContRegisterActivate response. */
+typedef struct {
+    /** Response. */
+    cmpRootContRegisterActivateRsp_t rsp;
+} cmpRspRootContRegisterActivate_t;
+
+/** @} */
+
+/** Map CMP RootContRegisterActivate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdRootContRegisterActivate_t cmpCmdRootContRegisterActivate;
+    /** Map CMP response. */
+    cmpRspRootContRegisterActivate_t cmpRspRootContRegisterActivate;
+} cmpMapRootContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER \
+  MC_CMP_CMD_ROOT_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_CMD Command
+ * @{ */
+
+/** RootContUnregister encrypted data command. */
+typedef struct {
+    /** Suid. */
+    mcSuid_t suid;
+} cmpRootUnregMsgEdata_t;
+
+/** RootContUnregister encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootUnregMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregMsgEdata_t))];
+} cmpRootUnregCmdEd_t;
+
+/** RootContUnregister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpRootUnregCmdEd_t ed;
+} cmpRootUnregCmdSdata_t;
+
+/** RootContUnregister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootUnregCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnregisterCmd_t;
+
+/** RootContUnregister command. */
+typedef struct {
+    /** Command. */
+    cmpRootContUnregisterCmd_t cmd;
+} cmpCmdRootContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_RSP Response
+ * @{ */
+
+/** RootContUnregister encrypted data response. */
+typedef struct {
+    /** Suid. */
+    mcSuid_t suid;
+} cmpRootUnregRspEdata_t;
+
+/** RootContUnregister encrypted and padded data response. */
+typedef struct {
+    /** Encrypted data. */
+    cmpRootUnregRspEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregRspEdata_t))];
+} cmpRootUnregRspEd_t;
+
+/** RootContUnregister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpRootUnregRspEd_t ed;
+} cmpRootUnregRspSdata_t;
+
+/** RootContUnregister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootUnregRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnregisterRsp_t;
+
+/** RootContUnregister response. */
+typedef struct {
+    /** Response. */
+    cmpRootContUnregisterRsp_t rsp;
+} cmpRspRootContUnregister_t;
+
+/** @} */
+
+/** Map CMP RootContUnregister message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdRootContUnregister_t cmpCmdRootContUnregister;
+    /** Map CMP response. */
+    cmpRspRootContUnregister_t cmpRspRootContUnregister;
+} cmpMapRootContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT \
+  MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_CMD Command
+ * @{ */
+
+/** RootContLockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+} cmpRootLockByRootCmdSdata_t;
+
+/** RootContLockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootLockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContLockByRootCmd_t;
+
+/** RootContLockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpRootContLockByRootCmd_t cmd;
+} cmpCmdRootContLockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_RSP Response
+ * @{ */
+
+/** RootContLockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Root container secure object size. */
+    uint32_t soRootContLen;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRootLockByRootRspSdata_t;
+
+/** RootContLockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootLockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContLockByRootRsp_t;
+
+/** RootContLockByRoot response. */
+typedef struct {
+    cmpRootContLockByRootRsp_t rsp;
+} cmpRspRootContLockByRoot_t;
+
+/** @} */
+
+/** Map CMP RootContLockByRoot message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdRootContLockByRoot_t cmpCmdRootContLockByRoot;
+    /** Map CMP response. */
+    cmpRspRootContLockByRoot_t cmpRspRootContLockByRoot;
+} cmpMapRootContLockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT \
+  MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_CMD Command
+ * @{ */
+
+/** RootContUnlockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+} cmpRootUnlockByRootCmdSdata_t;
+
+/** RootContUnlockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpRootUnlockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnlockByRootCmd_t;
+
+/** RootContUnlockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpRootContUnlockByRootCmd_t cmd;
+} cmpCmdRootContUnlockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_RSP Response
+ * @{ */
+
+/** RootContUnlockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Root container secure object size. */
+    uint32_t soRootContLen;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpRootUnlockByRootRspSdata_t;
+
+/** RootContUnlockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpRootUnlockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpRootContUnlockByRootRsp_t;
+
+/** RootContUnlockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpRootContUnlockByRootRsp_t rsp;
+} cmpRspRootContUnlockByRoot_t;
+
+/** @} */
+
+/** Map CMP RootContUnlockByRoot message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdRootContUnlockByRoot_t cmpCmdRootContUnlockByRoot;
+    /** Map CMP response. */
+    cmpRspRootContUnlockByRoot_t cmpRspRootContUnlockByRoot;
+} cmpMapRootContUnlockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE \
+  MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_CMD Command
+ * @{ */
+
+/** SpContRegisterActivate encrypted data command. */
+typedef struct {
+    /** Sp authentication key. */
+    mcSymmetricKey_t kSpAuth;
+} cmpSpRegActMsgEdata_t;
+
+/** SpContRegisterActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpRegActMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActMsgEdata_t))];
+} cmpSpRegActCmdEd_t;
+
+/** SpContRegisterActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpSpRegActCmdEd_t ed;
+} cmpSpRegActCmdSdata_t;
+
+/** SpContRegisterActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpRegActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterActivateCmd_t;
+
+/** SpContRegisterActivate command. */
+typedef struct {
+    /** Command. */
+    cmpSpContRegisterActivateCmd_t cmd;
+} cmpCmdSpContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_RSP Response
+ * @{ */
+
+/** SpContRegisterActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Root container secure object size. */
+    uint32_t soRootContLen;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpRegActRspSdata_t;
+
+/** SpContRegisterActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpRegActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterActivateRsp_t;
+
+/** SpContRegisterActivate response. */
+typedef struct {
+    /** Response. */
+    cmpSpContRegisterActivateRsp_t rsp;
+} cmpRspSpContRegisterActivate_t;
+
+/** @} */
+
+/** Map CMP SpContRegisterActivate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContRegisterActivate_t cmpCmdSpContRegisterActivate;
+    /** Map CMP response. */
+    cmpRspSpContRegisterActivate_t cmpRspSpContRegisterActivate;
+} cmpMapSpContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER \
+  MC_CMP_CMD_SP_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_CMD Command
+ * @{ */
+
+/** SpContUnregister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpContUnregCmdSdata_t;
+
+/** SpContUnregister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpContUnregCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnregisterCmd_t;
+
+/** SpContUnregister command. */
+typedef struct {
+    /** Command. */
+    cmpSpContUnregisterCmd_t cmd;
+} cmpCmdSpContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_RSP Response
+ * @{ */
+
+/** SpContUnregister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Root container secure object size. */
+    uint32_t soRootContLen;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+} cmpSpContUnregRspSdata_t;
+
+/** SpContUnregister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpContUnregRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnregisterRsp_t;
+
+/** SpContUnregister response. */
+typedef struct {
+    /** Response. */
+    cmpSpContUnregisterRsp_t rsp;
+} cmpRspSpContUnregister_t;
+
+/** @} */
+
+/** Map CMP SpContUnregister message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContUnregister_t cmpCmdSpContUnregister;
+    /** Map CMP response. */
+    cmpRspSpContUnregister_t cmpRspSpContUnregister;
+} cmpMapSpContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER \
+  MC_CMP_CMD_SP_CONT_REGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_CMD Command
+ * @{ */
+
+/** SpContRegister encrypted data command. */
+typedef struct {
+    /** Sp authentication key. */
+    mcSymmetricKey_t kSpAuth;
+} cmpSpRegisterMsgEdata_t;
+
+/** SpContRegister encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpRegisterMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterMsgEdata_t))];
+} cmpSpRegisterCmdEd_t;
+
+/** SpContRegister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpSpRegisterCmdEd_t ed;
+} cmpSpRegisterCmdSdata_t;
+
+/** SpContRegister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpRegisterCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterCmd_t;
+
+/** SpContRegister command. */
+typedef struct {
+    /** Command. */
+    cmpSpContRegisterCmd_t cmd;
+} cmpCmdSpContRegister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_RSP Response
+ * @{ */
+
+/** SpContRegister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Root container secure object size. */
+    uint32_t soRootContLen;
+    /** Root container secure object. */
+    mcSoRootCont_t soRootCont;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpRegisterRspSdata_t;
+
+/** SpContRegister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpRegisterRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContRegisterRsp_t;
+
+/** SpContRegister response. */
+typedef struct {
+    /** Response. */
+    cmpSpContRegisterRsp_t rsp;
+} cmpRspSpContRegister_t;
+
+/** @} */
+
+/** Map CMP SpContRegister message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContRegister_t cmpCmdSpContRegister;
+    /** Map CMP response. */
+    cmpRspSpContRegister_t cmpRspSpContRegister;
+} cmpMapSpContRegister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT \
+  MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_CMD Command
+ * @{ */
+
+/** SpContLockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpLockByRootCmdSdata_t;
+
+/** SpContLockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpLockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockByRootCmd_t;
+
+/** SpContLockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpSpContLockByRootCmd_t cmd;
+} cmpCmdSpContLockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_RSP Response
+ * @{ */
+
+/** SpContLockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpLockByRootRspSdata_t;
+
+/** SpContLockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpLockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockByRootRsp_t;
+
+/** SpContLockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpSpContLockByRootRsp_t rsp;
+} cmpRspSpContLockByRoot_t;
+
+/** @} */
+
+/** Map CMP SpContLockByRoot message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContLockByRoot_t cmpCmdSpContLockByRoot;
+    /** Map CMP response. */
+    cmpRspSpContLockByRoot_t cmpRspSpContLockByRoot;
+} cmpMapSpContLockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT \
+  MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_CMD Command
+ * @{ */
+
+/** SpContUnlockByRoot signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpUnlockByRootCmdSdata_t;
+
+/** SpContUnlockByRoot signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpUnlockByRootCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockByRootCmd_t;
+
+/** SpContUnlockByRoot command. */
+typedef struct {
+    /** Command. */
+    cmpSpContUnlockByRootCmd_t cmd;
+} cmpCmdSpContUnlockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_RSP Response
+ * @{ */
+
+/** SpContUnlockByRoot signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpUnlockByRootRspSdata_t;
+
+/** SpContUnlockByRoot signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpUnlockByRootRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockByRootRsp_t;
+
+/** SpContUnlockByRoot response. */
+typedef struct {
+    /** Response. */
+    cmpSpContUnlockByRootRsp_t rsp;
+} cmpRspSpContUnlockByRoot_t;
+
+/** @} */
+
+/** Map CMP SpContUnlockByRoot message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContUnlockByRoot_t cmpCmdSpContUnlockByRoot;
+    /** Map CMP response. */
+    cmpRspSpContUnlockByRoot_t cmpRspSpContUnlockByRoot;
+} cmpMapSpContUnlockByRoot_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE \
+  MC_CMP_CMD_SP_CONT_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_CMD Command
+ * @{ */
+
+/** SpContActivate encrypted data command. */
+typedef struct {
+    /** Sp authentication key. */
+    mcSymmetricKey_t kSpAuth;
+} cmpSpActivateMsgEdata_t;
+
+/** SpContActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpSpActivateMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateMsgEdata_t))];
+} cmpSpActivateCmdEd_t;
+
+/** SpContActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpSpActivateCmdEd_t ed;
+} cmpSpActivateCmdSdata_t;
+
+/** SpContActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpActivateCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContActivateCmd_t;
+
+/** SpContActivate command. */
+typedef struct {
+    /** Command. */
+    cmpSpContActivateCmd_t cmd;
+} cmpCmdSpContActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_RSP Response
+ * @{ */
+
+/** SpContActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpActivateRspSdata_t;
+
+/** SpContActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpActivateRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContActivateRsp_t;
+
+/** SpContActivate response. */
+typedef struct {
+    /** Response. */
+    cmpSpContActivateRsp_t rsp;
+} cmpRspSpContActivate_t;
+
+/** @} */
+
+/** Map CMP SpContActivate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContActivate_t cmpCmdSpContActivate;
+    /** Map CMP response. */
+    cmpRspSpContActivate_t cmpRspSpContActivate;
+} cmpMapSpContActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP \
+  MC_CMP_CMD_SP_CONT_LOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_CMD Command
+ * @{ */
+
+/** SpContLockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpLockBySpCmdSdata_t;
+
+/** SpContLockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpLockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockBySpCmd_t;
+
+/** SpContLockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpSpContLockBySpCmd_t cmd;
+} cmpCmdSpContLockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_RSP Response
+ * @{ */
+
+/** SpContLockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpLockBySpRspSdata_t;
+
+/** SpContLockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpLockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContLockBySpRsp_t;
+
+/** SpContLockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpSpContLockBySpRsp_t rsp;
+} cmpRspSpContLockBySp_t;
+
+/** @} */
+
+/** Map CMP SpContLockBySp message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContLockBySp_t cmpCmdSpContLockBySp;
+    /** Map CMP response. */
+    cmpRspSpContLockBySp_t cmpRspSpContLockBySp;
+} cmpMapSpContLockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP \
+  MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_CMD Command
+ * @{ */
+
+/** SpContUnlockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+} cmpSpUnlockBySpCmdSdata_t;
+
+/** SpContUnlockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpSpUnlockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockBySpCmd_t;
+
+/** SpContUnlockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpSpContUnlockBySpCmd_t cmd;
+} cmpCmdSpContUnlockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_RSP Response
+ * @{ */
+
+/** SpContUnlockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpSpUnlockBySpRspSdata_t;
+
+/** SpContUnlockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpSpUnlockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpSpContUnlockBySpRsp_t;
+
+/** SpContUnlockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpSpContUnlockBySpRsp_t rsp;
+} cmpRspSpContUnlockBySp_t;
+
+/** @} */
+
+/** Map CMP SpContUnlockBySp message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdSpContUnlockBySp_t cmpCmdSpContUnlockBySp;
+    /** Map CMP response. */
+    cmpRspSpContUnlockBySp_t cmpRspSpContUnlockBySp;
+} cmpMapSpContUnlockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE \
+  MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_CMD Command
+ * @{ */
+
+/** TltContRegisterActivate encrypted data command. */
+typedef struct {
+    /** Tlt authentication key. */
+    mcSymmetricKey_t kSpTltEnc;
+} cmpTltRegActMsgEdata_t;
+
+/** TltContRegisterActivate encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltRegActMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActMsgEdata_t))];
+} cmpTltRegActCmdEd_t;
+
+/** TltContRegisterActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+    /** Trustlet public key hash. */
+    mcSha256_t skSpTltEnc;
+    /** Minimum trustlet version supported. */
+    mcContVersion_t tltVersion;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpTltRegActCmdEd_t ed;
+} cmpTltRegActCmdSdata_t;
+
+/** TltContRegisterActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltRegActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterActivateCmd_t;
+
+/** TltContRegisterActivate command. */
+typedef struct {
+    /** Command. */
+    cmpTltContRegisterActivateCmd_t cmd;
+} cmpCmdTltContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_RSP Response
+ * @{ */
+
+/** TltContRegisterActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+    /* TltCont mapping info is in TCI cmpRspTltContRegisterActivateTci */
+    uint32_t soTltContLen;
+    mcSoTltCont_2_1_t soTltCont;
+} cmpTltRegActRspSdata_t;
+
+/** TltContRegisterActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltRegActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterActivateRsp_t;
+
+/** TltContRegisterActivate response. */
+typedef struct {
+    cmpTltContRegisterActivateRsp_t rsp;
+} cmpRspTltContRegisterActivate_t;
+
+/** @} */
+
+/** Map CMP TltContRegisterActivate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContRegisterActivate_t cmpCmdTltContRegisterActivate;
+    /** Map CMP response. */
+    cmpRspTltContRegisterActivate_t cmpRspTltContRegisterActivate;
+} cmpMapTltContRegisterActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER \
+  MC_CMP_CMD_TLT_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_CMD Command
+ * @{ */
+
+/** TltContUnregister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltUnregCmdSdata_t;
+
+/** TltContUnregister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltUnregCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnregisterCmd_t;
+
+/** TltContUnregister command. */
+typedef struct {
+    /** Command. */
+    cmpTltContUnregisterCmd_t cmd;
+} cmpCmdTltContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_RSP Response
+ * @{ */
+
+/** TltContUnregister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+} cmpTltUnregRspSdata_t;
+
+/** TltContUnregister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltUnregRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnregisterRsp_t;
+
+/** TltContUnregister response. */
+typedef struct {
+    /** Response. */
+    cmpTltContUnregisterRsp_t rsp;
+} cmpRspTltContUnregister_t;
+
+/** @} */
+
+/** Map CMP TltContUnregister message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContUnregister_t cmpCmdTltContUnregister;
+    /** Map CMP response. */
+    cmpRspTltContUnregister_t cmpRspTltContUnregister;
+} cmpMapTltContUnregister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER \
+  MC_CMP_CMD_TLT_CONT_REGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_CMD Command
+ * @{ */
+
+/** TltContRegister encrypted data command. */
+typedef struct {
+    /** Tlt authentication key. */
+    mcSymmetricKey_t kSpTltEnc;
+} cmpTltRegMsgEdata_t;
+
+/** TltContRegister encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltRegMsgEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegMsgEdata_t))];
+} cmpTltRegCmdEd_t;
+
+/** TltContRegister signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+    /** Trustlet public key hash. */
+    mcSha256_t skSpTltEnc;
+    /** Minimum trustlet version supported. */
+    mcContVersion_t tltVersion;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpTltRegCmdEd_t ed;
+} cmpTltRegCmdSdata_t;
+
+/** TltContRegister signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltRegCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterCmd_t;
+
+/** TltContRegister command. */
+typedef struct {
+    /** Command. */
+    cmpTltContRegisterCmd_t cmd;
+} cmpCmdTltContRegister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_RSP Response
+ * @{ */
+
+/** TltContRegister signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Sp container secure object size. */
+    uint32_t soSpContLen;
+    /** Sp container secure object. */
+    mcSoSpCont_t soSpCont;
+    /** Tlt container secure object size. */
+    uint32_t soTltContLen;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_1_t soTltCont;
+} cmpTltRegRspSdata_t;
+
+/** TltContRegister signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltRegRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContRegisterRsp_t;
+
+/** TltContRegister response. */
+typedef struct {
+    /** Response. */
+    cmpTltContRegisterRsp_t rsp;
+} cmpRspTltContRegister_t;
+
+/** @} */
+
+/** Map CMP TltContRegister message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContRegister_t cmpCmdTltContRegister;
+    /** Map CMP response. */
+    cmpRspTltContRegister_t cmpRspTltContRegister;
+} cmpMapTltContRegister_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE \
+  MC_CMP_CMD_TLT_CONT_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_CMD Command
+ * @{ */
+
+/** TltContActivate signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltActCmdSdata_t;
+
+/** TltContActivate signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltActCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContActivateCmd_t;
+
+/** TltContActivate command. */
+typedef struct {
+    /** Command. */
+    cmpTltContActivateCmd_t cmd;
+} cmpCmdTltContActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_RSP Response
+ * @{ */
+
+/** TltContActivate signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Tlt container secure object size. */
+    uint32_t soTltContLen;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_1_t soTltCont;
+} cmpTltActRspSdata_t;
+
+/** TltContActivate signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltActRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContActivateRsp_t;
+
+/** TltContActivate response. */
+typedef struct {
+    /** Response. */
+    cmpTltContActivateRsp_t rsp;
+} cmpRspTltContActivate_t;
+
+/** @} */
+
+/** Map CMP TltContActivate message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContActivate_t cmpCmdTltContActivate;
+    /** Map CMP response. */
+    cmpRspTltContActivate_t cmpRspTltContActivate;
+} cmpMapTltContActivate_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP \
+  MC_CMP_CMD_TLT_CONT_LOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_CMD Command
+ * @{ */
+
+/** TltContLockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltLockBySpCmdSdata_t;
+
+/** TltContLockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltLockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContLockBySpCmd_t;
+
+/** TltContLockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpTltContLockBySpCmd_t cmd;
+} cmpCmdTltContLockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_RSP Response
+ * @{ */
+
+/** TltContLockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Tlt container secure object size. */
+    uint32_t soTltContLen;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_1_t soTltCont;
+} cmpTltLockBySpRspSdata_t;
+
+/** TltContLockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltLockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContLockBySpRsp_t;
+
+/** TltContLockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpTltContLockBySpRsp_t rsp;
+} cmpRspTltContLockBySp_t;
+
+/** @} */
+
+/** Map CMP TltContLockBySp message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContLockBySp_t cmpCmdTltContLockBySp;
+    /** Map CMP response. */
+    cmpRspTltContLockBySp_t cmpRspTltContLockBySp;
+} cmpMapTltContLockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP \
+  MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_CMD Command
+ * @{ */
+
+/** TltContLockBySp signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+} cmpTltUnlockBySpCmdSdata_t;
+
+/** TltContLockBySp signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltUnlockBySpCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnlockBySpCmd_t;
+
+/** TltContUnlockBySp command. */
+typedef struct {
+    /** Command. */
+    cmpTltContUnlockBySpCmd_t cmd;
+} cmpCmdTltContUnlockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_RSP Response
+ * @{ */
+
+/** TltContUnlockBySp signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Tlt container secure object size. */
+    uint32_t soTltContLen;
+    /** Tlt container secure object. */
+    mcSoTltCont_2_1_t soTltCont;
+} cmpTltUnlockBySpRspSdata_t;
+
+/** TltContUnlockBySp signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltUnlockBySpRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContUnlockBySpRsp_t;
+
+/** TltContUnlockBySp response. */
+typedef struct {
+    /** Response. */
+    cmpTltContUnlockBySpRsp_t rsp;
+} cmpRspTltContUnlockBySp_t;
+
+/** @} */
+
+/** Map CMP TltContUnlockBySp message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContUnlockBySp_t cmpCmdTltContUnlockBySp;
+    /** Map CMP response. */
+    cmpRspTltContUnlockBySp_t cmpRspTltContUnlockBySp;
+} cmpMapTltContUnlockBySp_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE \
+  MC_CMP_CMD_TLT_CONT_PERSONALIZE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_CMD Command
+ * @{ */
+
+/** TltContPersonalize encrypted data command. */
+typedef struct {
+    /** Data. */
+    mcCoDataCont_t dataCont;
+} cmpTltContPersonalizeCmdEdata_t;
+
+/** TltContPersonalize encrypted and padded data command. */
+typedef struct {
+    /** Encrypted data. */
+    cmpTltContPersonalizeCmdEdata_t edata;
+    /** Padding. */
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeCmdEdata_t))];
+} cmpTltContPersonalizeCmdEd_t;
+
+/** TltContPersonalize signed command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Spid. */
+    mcSpid_t spid;
+    /** Uuid. */
+    mcUuid_t uuid;
+    /** Pid. */
+    mcPid_t pid;
+    /** Encrypted and padded data size. */
+    uint32_t edLen;
+    /** Encrypted and padded data. */
+    cmpTltContPersonalizeCmdEd_t ed;
+} cmpTltContPersonalizeCmdSdata_t;
+
+/** TltContPersonalize signed command and signature. */
+typedef struct {
+    /** Signed command. */
+    cmpTltContPersonalizeCmdSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContPersonalizeCmd_t;
+
+/** TltContPersonalize command. */
+typedef struct {
+    cmpTltContPersonalizeCmd_t cmd;
+} cmpCmdTltContPersonalize_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_RSP Response
+ * @{ */
+
+/** TltContPersonalize signed response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+    /** Data container secure object size. */
+    uint32_t soDataContLen;
+    /** Data container secure object. */
+    mcSoDataCont_t soDataCont;
+} cmpTltContPersonalizeRspSdata_t;
+
+/** TltContPersonalize signed response and signature. */
+typedef struct {
+    /** Signed response. */
+    cmpTltContPersonalizeRspSdata_t sdata;
+    /** Signature. */
+    cmpMac_t mac;
+} cmpTltContPersonalizeRsp_t;
+
+/** TltContPersonalize response. */
+typedef struct {
+    /** Response. */
+    cmpTltContPersonalizeRsp_t rsp;
+} cmpRspTltContPersonalize_t;
+
+/** @} */
+
+/** Map CMP TltContPersonalize message. */
+typedef union {
+    /** Map CMP command. */
+    cmpCmdTltContPersonalize_t cmpCmdTltContPersonalize;
+    /** Map CMP response. */
+    cmpRspTltContPersonalize_t cmpRspTltContPersonalize;
+} cmpMapTltContPersonalize_t;
+
+/** @} */
+
+/** Map CMP messages. */
+typedef union {
+    /** Backward compatible command header. */
+    cmpCommandHeader_t commandHeader;
+    /** Backward compatible response header. */
+    cmpResponseHeader_t responseHeader;
+
+    /** Backward compatible system command GetVersion. */
+    cmpCmdGetVersion_t cmpCmdGetVersion;
+    /** Backward compatible system response GetVersion. */
+    cmpRspGetVersion_t cmpRspGetVersion;
+    /** Backward compatible system command GetSuid. */
+    cmpCmdGetSuid_t cmpCmdGetSuid;
+    /** Backward compatible system response GetSuid. */
+    cmpRspGetSuid_t cmpRspGetSuid;
+    /** Backward compatible system command GenAuthToken. */
+    cmpCmdGenAuthToken_t cmpCmdGenAuthToken;
+    /** Backward compatible system response GenAuthToken. */
+    cmpRspGenAuthToken_t cmpRspGenAuthToken;
+    /** Backward compatible system command GenBindingKey. */
+    cmpCmdGenBindingKey_t cmpCmdGenBindingKey;
+    /** Backward compatible system response GenBindingKey. */
+    cmpRspGenBindingKey_t cmpRspGenBindingKey;
+
+    /** Command header. */
+    cmpCommandHeaderMap_t cmdHeader;
+    /** Response header. */
+    cmpResponseHeaderMap_t rspHeader;
+
+    /** Error signed response. */
+    cmpMapError_t cmpMapError;
+
+    /** Authentication command BeginSocAuthentication. */
+    cmpCmdBeginSocAuthentication_t cmpCmdBeginSocAuthentication;
+    /** Authentication response BeginSocAuthentication. */
+    cmpRspBeginSocAuthentication_t cmpRspBeginSocAuthentication;
+    /** Authentication command BeginRootAuthentication. */
+    cmpCmdBeginRootAuthentication_t cmpCmdBeginRootAuthentication;
+    /** Authentication response BeginRootAuthentication. */
+    cmpRspBeginRootAuthentication_t cmpRspBeginRootAuthentication;
+    /** Authentication command BeginSpAuthentication. */
+    cmpCmdBeginSpAuthentication_t cmpCmdBeginSpAuthentication;
+    /** Authentication response BeginSpAuthentication. */
+    cmpRspBeginSpAuthentication_t cmpRspBeginSpAuthentication;
+    /** Authentication command Authenticate. */
+    cmpCmdAuthenticate_t cmpCmdAuthenticate;
+    /** Authentication response Authenticate. */
+    cmpRspAuthenticate_t cmpRspAuthenticate;
+    /** Authentication command AuthenticateTerminate. */
+    cmpCmdAuthenticateTerminate_t cmpCmdAuthenticateTerminate;
+    /** Authentication response AuthenticateTerminate. */
+    cmpRspAuthenticateTerminate_t cmpRspAuthenticateTerminate;
+
+    /** SoC administrative command RootContRegisterActivate. */
+    cmpCmdRootContRegisterActivate_t cmpCmdRootContRegisterActivate;
+    /** SoC administrative response RootContRegisterActivate. */
+    cmpRspRootContRegisterActivate_t cmpRspRootContRegisterActivate;
+
+    /** Root administrative command RootContUnregister. */
+    cmpCmdRootContUnregister_t cmpCmdRootContUnregister;
+    /** Root administrative response RootContUnregister. */
+    cmpRspRootContUnregister_t cmpRspRootContUnregister;
+    /** Root administrative command RootContLockByRoot. */
+    cmpCmdRootContLockByRoot_t cmpCmdRootContLockByRoot;
+    /** Root administrative response RootContLockByRoot. */
+    cmpRspRootContLockByRoot_t cmpRspRootContLockByRoot;
+    /** Root administrative command RootContUnlockByRoot. */
+    cmpCmdRootContUnlockByRoot_t cmpCmdRootContUnlockByRoot;
+    /** Root administrative response RootContUnlockByRoot. */
+    cmpRspRootContUnlockByRoot_t cmpRspRootContUnlockByRoot;
+    /** Root administrative command SpContRegisterActivate. */
+    cmpCmdSpContRegisterActivate_t cmpCmdSpContRegisterActivate;
+    /** Root administrative response SpContRegisterActivate. */
+    cmpRspSpContRegisterActivate_t cmpRspSpContRegisterActivate;
+    /** Root administrative command SpContUnregister. */
+    cmpCmdSpContUnregister_t cmpCmdSpContUnregister;
+    /** Root administrative response SpContUnregister. */
+    cmpRspSpContUnregister_t cmpRspSpContUnregister;
+    /** Root administrative command SpContRegister. */
+    cmpCmdSpContRegister_t cmpCmdSpContRegister;
+    /** Root administrative response SpContRegister. */
+    cmpRspSpContRegister_t cmpRspSpContRegister;
+    /** Root administrative command SpContLockByRoot. */
+    cmpCmdSpContLockByRoot_t cmpCmdSpContLockByRoot;
+    /** Root administrative response SpContLockByRoot. */
+    cmpRspSpContLockByRoot_t cmpRspSpContLockByRoot;
+    /** Root administrative command SpContUnlockByRoot. */
+    cmpCmdSpContUnlockByRoot_t cmpCmdSpContUnlockByRoot;
+    /** Root administrative response SpContUnlockByRoot. */
+    cmpRspSpContUnlockByRoot_t cmpRspSpContUnlockByRoot;
+
+    /** Sp administrative command SpContActivate. */
+    cmpCmdSpContActivate_t cmpCmdSpContActivate;
+    /** Sp administrative response SpContActivate. */
+    cmpRspSpContActivate_t cmpRspSpContActivate;
+    /** Sp administrative command SpContLockBySp. */
+    cmpCmdSpContLockBySp_t cmpCmdSpContLockBySp;
+    /** Sp administrative response SpContLockBySp. */
+    cmpRspSpContLockBySp_t cmpRspSpContLockBySp;
+    /** Sp administrative command SpContUnlockBySp. */
+    cmpCmdSpContUnlockBySp_t cmpCmdSpContUnlockBySp;
+    /** Sp administrative response SpContUnlockBySp. */
+    cmpRspSpContUnlockBySp_t cmpRspSpContUnlockBySp;
+    /** Sp administrative command TltContRegisterActivate. */
+    cmpCmdTltContRegisterActivate_t cmpCmdTltContRegisterActivate;
+    /** Sp administrative response TltContRegisterActivate. */
+    cmpRspTltContRegisterActivate_t cmpRspTltContRegisterActivate;
+    /** Sp administrative command TltContUnregister. */
+    cmpCmdTltContUnregister_t cmpCmdTltContUnregister;
+    /** Sp administrative response TltContUnregister. */
+    cmpRspTltContUnregister_t cmpRspTltContUnregister;
+    /** Sp administrative command TltContRegister. */
+    cmpCmdTltContRegister_t cmpCmdTltContRegister;
+    /** Sp administrative response TltContRegister. */
+    cmpRspTltContRegister_t cmpRspTltContRegister;
+    /** Sp administrative command TltContActivate. */
+    cmpCmdTltContActivate_t cmpCmdTltContActivate;
+    /** Sp administrative response TltContActivate. */
+    cmpRspTltContActivate_t cmpRspTltContActivate;
+    /** Sp administrative command TltContLockBySp. */
+    cmpCmdTltContLockBySp_t cmpCmdTltContLockBySp;
+    /** Sp administrative response TltContLockBySp. */
+    cmpRspTltContLockBySp_t cmpRspTltContLockBySp;
+    /** Sp administrative command TltContUnlockBySp. */
+    cmpCmdTltContUnlockBySp_t cmpCmdTltContUnlockBySp;
+    /** Sp administrative response TltContUnlockBySp. */
+    cmpRspTltContUnlockBySp_t cmpRspTltContUnlockBySp;
+    /** Sp administrative command TltContPersonalize. */
+    cmpCmdTltContPersonalize_t cmpCmdTltContPersonalize;
+    /** Sp administrative response TltContPersonalize. */
+    cmpRspTltContPersonalize_t cmpRspTltContPersonalize;
+} cmpMap_t;
+
+#endif // CMP_MAP_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/3.0/tlCmApi.h b/mobicore/tlcm/TlCm/3.0/tlCmApi.h
new file mode 100644 (file)
index 0000000..e04429d
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP
+ * @{
+ * @file
+ * Interface to content management trustlet (TlCm) definitions.
+ *
+ * The TlCm is responsible for implementing content management protocol (CMP)
+ * commands and generating approriate CMP responses in the trustlet control
+ * interface (TCI).
+ */
+
+#ifndef TL_CM_API_H_
+#define TL_CM_API_H_
+
+#include "TlCm/tlCmApiCommon.h"
+#include "TlCm/3.0/cmp.h"
+#include "TlCm/3.0/cmpMap.h"
+
+/** TCI CMP messages. */
+typedef union {
+    /** Command header. */
+    cmpCommandHeaderTci_t commandHeader;
+    /** Response header. */
+    cmpResponseHeaderTci_t responseHeader;
+
+    /** System command GetVersion. */
+    cmpCmdGetVersionTci_t cmpCmdGetVersionTci;
+    /** System response GetVersion. */
+    cmpRspGetVersionTci_t cmpRspGetVersionTci;
+    /** System command GetSuid. */
+    cmpCmdGetSuidTci_t cmpCmdGetSuidTci;
+    /** System response GetSuid. */
+    cmpRspGetSuidTci_t cmpRspGetSuidTci;
+    /** System command GenAuthToken. */
+    cmpCmdGenAuthTokenTci_t cmpCmdGenAuthTokenTci;
+    /** System response GenAuthToken. */
+    cmpRspGenAuthTokenTci_t cmpRspGenAuthTokenTci;
+    /** System command GenBindingKey. */
+    cmpCmdGenBindingKeyTci_t cmpCmdGenBindingKeyTci;
+    /** System response GenBindingKey. */
+    cmpRspGenBindingKeyTci_t cmpRspGenBindingKeyTci;
+
+    /** Authentication command BeginSocAuthentication. */
+    cmpCmdBeginSocAuthenticationTci_t cmpCmdBeginSocAuthenticationTci;
+    /** Authentication response BeginSocAuthentication. */
+    cmpRspBeginSocAuthenticationTci_t cmpRspBeginSocAuthenticationTci;
+    /** Authentication command BeginRootAuthentication. */
+    cmpCmdBeginRootAuthenticationTci_t cmpCmdBeginRootAuthenticationTci;
+    /** Authentication response BeginRootAuthentication. */
+    cmpRspBeginRootAuthenticationTci_t cmpRspBeginRootAuthenticationTci;
+    /** Authentication command BeginSpAuthentication. */
+    cmpCmdBeginSpAuthenticationTci_t cmpCmdBeginSpAuthenticationTci;
+    /** Authentication response BeginSpAuthentication. */
+    cmpRspBeginSpAuthenticationTci_t cmpRspBeginSpAuthenticationTci;
+    /** Authentication command Authenticate. */
+    cmpCmdAuthenticateTci_t cmpCmdAuthenticateTci;
+    /** Authentication response Authenticate. */
+    cmpRspAuthenticateTci_t cmpRspAuthenticateTci;
+    /** Authentication command AuthenticateTerminate. */
+    cmpCmdAuthenticateTerminateTci_t cmpCmdAuthenticateTerminateTci;
+    /** Authentication response AuthenticateTerminate. */
+    cmpRspAuthenticateTerminateTci_t cmpRspAuthenticateTerminateTci;
+
+    /** SoC administrative command RootContRegisterActivate. */
+    cmpCmdRootContRegisterActivateTci_t cmpCmdRootContRegisterActivateTci;
+    /** SoC administrative response RootContRegisterActivate. */
+    cmpRspRootContRegisterActivateTci_t cmpRspRootContRegisterActivateTci;
+
+    /** Root administrative command RootContUnregister. */
+    cmpCmdRootContUnregisterTci_t cmpCmdRootContUnregisterTci;
+    /** Root administrative response RootContUnregister. */
+    cmpRspRootContUnregisterTci_t cmpRspRootContUnregisterTci;
+    /** Root administrative command RootContLockByRoot. */
+    cmpCmdRootContLockByRootTci_t cmpCmdRootContLockByRootTci;
+    /** Root administrative response RootContLockByRoot. */
+    cmpRspRootContLockByRootTci_t cmpRspRootContLockByRootTci;
+    /** Root administrative command RootContUnlockByRoot. */
+    cmpCmdRootContUnlockByRootTci_t cmpCmdRootContUnlockByRootTci;
+    /** Root administrative command RootContUnlockByRoot. */
+    cmpRspRootContUnlockByRootTci_t cmpRspRootContUnlockByRootTci;
+    /** Root administrative command SpContRegisterActivate. */
+    cmpCmdSpContRegisterActivateTci_t cmpCmdSpContRegisterActivateTci;
+    /** Root administrative response SpContRegisterActivate. */
+    cmpRspSpContRegisterActivateTci_t cmpRspSpContRegisterActivateTci;
+    /** Root administrative command SpContUnregister. */
+    cmpCmdSpContUnregisterTci_t cmpCmdSpContUnregisterTci;
+    /** Root administrative response SpContUnregister. */
+    cmpRspSpContUnregisterTci_t cmpRspSpContUnregisterTci;
+    /** Root administrative command SpContRegister. */
+    cmpCmdSpContRegisterTci_t cmpCmdSpContRegisterTci;
+    /** Root administrative response SpContRegister. */
+    cmpRspSpContRegisterTci_t cmpRspSpContRegisterTci;
+    /** Root administrative command SpContLockByRoot. */
+    cmpCmdSpContLockByRootTci_t cmpCmdSpContLockByRootTci;
+    /** Root administrative response SpContLockByRoot. */
+    cmpRspSpContLockByRootTci_t cmpRspSpContLockByRootTci;
+    /** Root administrative command SpContUnlockByRoot. */
+    cmpCmdSpContUnlockByRootTci_t cmpCmdSpContUnlockByRootTci;
+    /** Root administrative response SpContUnlockByRoot. */
+    cmpRspSpContUnlockByRootTci_t cmpRspSpContUnlockByRootTci;
+
+    /** Sp administrative command SpContActivate. */
+    cmpCmdSpContActivateTci_t cmpCmdSpContActivateTci;
+    /** Sp administrative response SpContActivate. */
+    cmpRspSpContActivateTci_t cmpRspSpContActivateTci;
+    /** Sp administrative command SpContLockBySp. */
+    cmpCmdSpContLockBySpTci_t cmpCmdSpContLockBySpTci;
+    /** Sp administrative response SpContLockBySp. */
+    cmpRspSpContLockBySpTci_t cmpRspSpContLockBySpTci;
+    /** Sp administrative command SpContUnlockBySp. */
+    cmpCmdSpContUnlockBySpTci_t cmpCmdSpContUnlockBySpTci;
+    /** Sp administrative command SpContUnlockBySp. */
+    cmpRspSpContUnlockBySpTci_t cmpRspSpContUnlockBySpTci;
+    /** Sp administrative command TltContRegisterActivate. */
+    cmpCmdTltContRegisterActivateTci_t cmpCmdTltContRegisterActivateTci;
+    /** Sp administrative response TltContRegisterActivate. */
+    cmpRspTltContRegisterActivateTci_t cmpRspTltContRegisterActivateTci;
+    /** Sp administrative command TltContUnregister. */
+    cmpCmdTltContUnregisterTci_t cmpCmdTltContUnregisterTci;
+    /** Sp administrative response TltContUnregister. */
+    cmpRspTltContUnregisterTci_t cmpRspTltContUnregisterTci;
+    /** Sp administrative command TltContRegister. */
+    cmpCmdTltContRegisterTci_t cmpCmdTltContRegisterTci;
+    /** Sp administrative command TltContRegister. */
+    cmpRspTltContRegisterTci_t cmpRspTltContRegisterTci;
+    /** Sp administrative command TltContActivate. */
+    cmpCmdTltContActivateTci_t cmpCmdTltContActivateTci;
+    /** Sp administrative command TltContActivate. */
+    cmpRspTltContActivateTci_t cmpRspTltContActivateTci;
+    /** Sp administrative command TltContLockBySp. */
+    cmpCmdTltContLockBySpTci_t cmpCmdTltContLockBySpTci;
+    /** Sp administrative response TltContLockBySp. */
+    cmpRspTltContLockBySpTci_t cmpRspTltContLockBySpTci;
+    /** Sp administrative command TltContUnlockBySp. */
+    cmpCmdTltContUnlockBySpTci_t cmpCmdTltContUnlockBySpTci;
+    /** Sp administrative response TltContUnlockBySp. */
+    cmpRspTltContUnlockBySpTci_t cmpRspTltContUnlockBySpTci;
+    /** Sp administrative command TltContPersonalize. */
+    cmpCmdTltContPersonalizeTci_t cmpCmdTltContPersonalizeTci;
+    /** Sp administrative response TltContPersonalize. */
+    cmpRspTltContPersonalizeTci_t cmpRspTltContPersonalizeTci;
+} cmpMessage_t;
+
+/** TCI CMP. */
+typedef struct {
+    /** TCI CMP messages. */
+    cmpMessage_t msg;
+} cmp_t;
+
+#endif // TL_CM_API_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/cmpCommon.h b/mobicore/tlcm/TlCm/cmpCommon.h
new file mode 100644 (file)
index 0000000..23f8fcc
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_COMMON
+ * Common definitions of content management protocols (CMP) supported by the
+ * content management trustlet (TlCm).
+ *
+ * @{
+ *
+ * @file
+ * Common 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.
+ */
+
+#ifndef CMP_COMMON_H_
+#define CMP_COMMON_H_
+
+#include "mcContainer.h"
+#include "mcUuid.h"
+#include "mcVersionInfo.h"
+#include "version.h"
+
+/** Minimum TCI CMP 2.0 size. */
+#define CMP_SIZE 4388
+
+/** Default CMP MAP size. */
+#define CMP_MAP_SIZE 2412
+
+/** CMP version id. */
+typedef uint32_t cmpVersionId_t;
+/** CMP command id. */
+typedef uint32_t cmpCommandId_t;
+/** CMP response id. */
+typedef uint32_t cmpResponseId_t;
+/** CMP return code. */
+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. */
+    cmpReturnCode_t returnCode;
+} cmpResponseHeader_t;
+
+/** Total number of bytes used for HMAC-SHA256 message authentication code. */
+#define CMP_MAC_SIZE 32
+
+/** Message authentication code. */
+typedef struct {
+    /** MAC value. */
+    uint8_t mac[CMP_MAC_SIZE];
+} cmpMac_t;
+
+/** 64-bit random number. */
+typedef struct {
+    /** Random number value. */
+    uint8_t data[8];
+} cmpRnd8_t;
+
+/** 256-bit random number. */
+typedef struct {
+    /** Random number value. */
+    uint8_t data[32];
+} cmpRnd32_t;
+
+/** @defgroup MC_CMP_CMD_GET_VERSION MC_CMP_CMD_GET_VERSION
+ * @{ */
+
+/** Version tags. */
+typedef enum {
+    /** Version tag deprecated. */
+    CMP_VERSION_TAG1 = 0x00000001,
+    /** Version tag. */
+    CMP_VERSION_TAG2 = 0x00000002,
+} cmpVersionTag_t;
+
+/** Version data info for deprecated version tag. */
+typedef struct {
+    /** Version data value. */
+    cmpVersionId_t number;
+} cmpVersionData1_t;
+
+/** Version data info. */
+typedef struct {
+    /** Version data value. */
+    mcVersionInfo_t versionInfo;
+} cmpVersionData2_t;
+
+/** Version data infos. */
+typedef union {
+    /** Version data info deprecated. */
+    cmpVersionData1_t versionData1;
+    /** Version data info. */
+    cmpVersionData2_t versionData2;
+} cmpVersionData_t;
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_CMD Command
+ * @{ */
+
+/** GetVersion command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpCmdGetVersion_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_RSP Response
+ * @{ */
+
+/** GetVersion response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Version tag. */
+    cmpVersionTag_t tag;
+    /** Version data info. */
+    cmpVersionData_t data;
+} cmpRspGetVersion_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GET_SUID MC_CMP_CMD_GET_SUID
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_GET_SUID_CMD Command
+ * @{ */
+
+/** GetSuid command. */
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+} cmpCmdGetSuid_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GET_SUID_RSP Response
+ * @{ */
+
+/** GetSuid response. */
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+} cmpRspGetSuid_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN MC_CMP_CMD_GENERATE_AUTH_TOKEN
+ * @{ */
+
+/** 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 PSS signature in GENERATE AUTH TOKEN command. */
+#define CMP_GEN_AUTH_TOKEN_PSS_SIZE 256
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_CMD Command
+ * @{ */
+
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /** Authentication key. */
+    mcSymmetricKey_t kSocAuth;
+    /** Key id. */
+    uint32_t kid;
+} cmpGenAuthTokenCmdSdata_t;
+
+typedef struct {
+    /** Signed data. */
+    cmpGenAuthTokenCmdSdata_t sdata;
+    /** Signature. */
+    uint8_t pssSignature[CMP_GEN_AUTH_TOKEN_PSS_SIZE];
+} cmpGenAuthTokenCmd_t;
+
+/** GenAuthToken command. */
+typedef struct {
+    /** Command. */
+    cmpGenAuthTokenCmd_t cmd;
+} cmpCmdGenAuthToken_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_RSP Response
+ * @{ */
+
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+} cmpGenAuthTokenRsp_t;
+
+/** GenAuthToken response. */
+typedef struct {
+    /** Response. */
+    cmpGenAuthTokenRsp_t rsp;
+    /** AuthToken container. */
+    mcSoAuthTokenCont_t soAuthCont;
+} cmpRspGenAuthToken_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_BINDING_KEY MC_CMP_CMD_GENERATE_BINDING_KEY
+ * @{ */
+
+/** Total number of bytes used for PSS signature in GENERATE BINDING KEY command. */
+#define CMP_GEN_BINDING_KEY_PSS_SIZE 256
+
+/** Total number of bytes used for receipt data in GENERATE BINDING KEY response. */
+#define CMP_GEN_BINDING_RECEIPT_ENC_PART_SIZE  256
+
+/**  Maximum Length in bytes for the entropy input */
+#define CMP_GEN_BINDING_KEY_ENTROPY_SIZE_MAX (56)
+
+/** @defgroup MC_CMP_CMD_GENERATE_BINDING_KEY_CMD Command
+ * @{ */
+
+typedef struct {
+    /** Command header. */
+    cmpCommandHeader_t cmdHeader;
+       /** Key id. */
+    uint32_t           kid;
+} cmpGenBindingKeyCmdSdata_t;
+
+typedef struct {
+    /** Signed data. */
+    cmpGenBindingKeyCmdSdata_t sdata;
+    /** Signature. */
+    uint8_t pssSignature[CMP_GEN_BINDING_KEY_PSS_SIZE];
+    /** Production Station Serial Number. */
+    uint64_t serialNumber;
+    /** Timestamp (seconds since epoch). */
+    uint64_t           timestamp;
+    /** Additional entropy length in bytes. */
+    uint16_t  entropyLen;
+    /** Additional entropy for K.SoC.Auth generation */
+    uint8_t   entropy[CMP_GEN_BINDING_KEY_ENTROPY_SIZE_MAX];
+} cmpCmdGenBindingKeyCmd_t;
+
+/** GenBindingKey command. */
+typedef struct {
+    /** Command. */
+    cmpCmdGenBindingKeyCmd_t cmd;
+} cmpCmdGenBindingKey_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_GENERATE_BINDING_KEY_RSP Response
+ * @{ */
+
+/** Receipt Data. */
+typedef struct {
+    uint8_t dataPart1[CMP_GEN_BINDING_RECEIPT_ENC_PART_SIZE];
+    uint8_t dataPart2[CMP_GEN_BINDING_RECEIPT_ENC_PART_SIZE];
+} receipt_t;
+
+typedef struct {
+    /** Response header. */
+    cmpResponseHeader_t rspHeader;
+    /** Suid. */
+    mcSuid_t suid;
+    /**Receipt data. */
+    receipt_t receipt;
+} cmpGenBindingKeyRsp_t;
+
+/** GenBindingKey response. */
+typedef struct {
+    /** Response. */
+    cmpGenBindingKeyRsp_t rsp;
+    /** AuthToken container. */
+    mcSoAuthTokenCont_t soAuthCont;
+} cmpRspGenBindingKey_t;
+
+/** @} */
+
+/** @} */ 
+
+#endif // CMP_COMMON_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/tlCmApiCommon.h b/mobicore/tlcm/TlCm/tlCmApiCommon.h
new file mode 100644 (file)
index 0000000..b9912cb
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_COMMON
+ * @{
+ * @file
+ * Common interface definitions to content management trustlet (TlCm).
+ *
+ * The TlCm is responsible for implementing content management protocol (CMP)
+ * commands and generating approriate CMP responses.
+ */
+
+#ifndef TL_CM_API_COMMON_H_
+#define TL_CM_API_COMMON_H_
+
+#include "tlCmError.h"
+
+/** TlCm command ids supported.
+ * @note All command ids must be in range 0 to 0x1D.
+ */
+//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_GENERATE_BINDING_KEY = 0x30,
+    //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_GENERATE_BINDING_KEY,
+} cmpCommands_t;
+
+/** TlCm exit code: TlCm exited with error. */
+#define EXIT_ERROR  ((uint32_t)(-1))
+
+#endif // TL_CM_API_COMMON_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/tlCmError.h b/mobicore/tlcm/TlCm/tlCmError.h
new file mode 100644 (file)
index 0000000..3896b7b
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_COMMON
+ * @{
+ *
+ * @file
+ * Content management trustlet (TlCm) error return code definitions.
+ * Definition of all possible TlCm error return codes.
+ */
+
+#ifndef TL_CM_ERROR_H_
+#define TL_CM_ERROR_H_
+
+/** No error. */
+#define  SUCCESSFUL                                 0x00000000
+
+/** Error unknown command. */
+#define RET_ERR_EXT_UNKNOWN_COMMAND                 0xE0000000
+/** Error security status not satified. */
+#define RET_ERR_EXT_SECURITY_STATUS_NOT_SATISFIED   0xE0000010
+/** Error secure messaging failed. */
+#define RET_ERR_EXT_SECURE_MESSAGING_FAILED         0xE0000020
+/** Error incorrect parameters. */
+#define RET_ERR_EXT_INCORRECT_PARAMETERS            0xE0000030
+/** Error referenced data invalid. */
+#define RET_ERR_EXT_REFERENCED_DATA_INVALID         0xE0000040
+/** Error referenced data not found. */
+#define RET_ERR_EXT_REFERENCED_DATA_NOT_FOUND       0xE0000050
+/** Error method blocked. */
+#define RET_ERR_EXT_METHOD_BLOCKED                  0xE0000060
+/** Error conditions of use not satified. */
+#define RET_ERR_EXT_CONDITIONS_OF_USE_NOT_SATISFIED 0xE0000070
+/** Error container already registred error. */
+#define RET_ERR_EXT_ALREADY_REGISTERED              0xE0000090
+/** Error container already activated. */
+#define RET_ERR_EXT_ALREADY_ACTIVATED               0xE00000A0
+/** Error container not registred. */
+#define RET_ERR_EXT_NOT_REGISTERED                  0xE00000B0
+/** Error container not activated. */
+#define RET_ERR_EXT_NOT_ACTIVATED                   0xE00000C0
+/** Error container full. */
+#define RET_ERR_EXT_CONTAINER_FULL                  0xE00000D0
+/** Error container not locked. */
+#define RET_ERR_EXT_NOT_LOCKED                      0xE00000E0
+/** Error container locked. */
+#define RET_ERR_EXT_LOCKED                          0xE00000F0
+/** Error container already locked. */
+#define RET_ERR_EXT_ALREADY_LOCKED                  0xE0000100
+
+/** Internal error. */
+#define RET_ERR_EXT_INTERNAL_ERROR                  0xE0001000
+/** Mapped allocation size error. */
+#define RET_ERR_EXT_SIZE                            0xE0002000
+
+/** Unspecified error. */
+#define RET_ERR_EXT_UNSPECIFIED                     0xEEEEEEEE
+
+#endif // TL_CM_ERROR_H_
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/tlCmUuid.h b/mobicore/tlcm/TlCm/tlCmUuid.h
new file mode 100644 (file)
index 0000000..c433756
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_COMMON
+ * @{
+ * @file
+ * Content management trustlet (TlCm) Uuid definition.
+ */
+
+#ifndef TL_CM_UUID_H
+#define TL_CM_UUID_H
+
+/** Uuid of TlCm. */
+#define TL_CM_UUID { { 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
+
+#endif // TL_CM_UUID_H
+
+/** @} */
diff --git a/mobicore/tlcm/TlCm/version.h b/mobicore/tlcm/TlCm/version.h
new file mode 100644 (file)
index 0000000..c91b71c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 TRUSTONIC LIMITED
+ * All rights reserved.
+ *
+ * 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. Neither the name of the TRUSTONIC LIMITED nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup CMP_COMMON
+ * @{
+ * @file
+ * Content management trustlet (TlCm) version definition.
+ */
+
+#ifndef CMP_VERSION_H_
+#define CMP_VERSION_H_
+
+/** Latest supported CMP major version number. */
+#define CMP_VERSION_MAJOR   3
+/** Latest supported CMP minor version number. */
+#define CMP_VERSION_MINOR   0
+
+#endif // CMP_VERSION_H_
+
+/** @} */
diff --git a/mobicore/tlcm/version.md5 b/mobicore/tlcm/version.md5
new file mode 100644 (file)
index 0000000..3750066
--- /dev/null
@@ -0,0 +1 @@
+a548519579b1a7cddb06c56989fd01f8 *-