From b9b0c08092f5170e61b49dfbbf79dcf3c88f83f3 Mon Sep 17 00:00:00 2001 From: "u.harbuz" Date: Thu, 4 May 2017 13:13:54 +0200 Subject: [PATCH] Initial commit Change-Id: Ibd50eeba46cf910eb59bb45bc631b06c1e9bb742 --- .cproject | 49 + .project | 27 + TEECLib/.cproject | 130 + TEECLib/.gitignore | 1 + TEECLib/.project | 28 + TEECLib/.settings/language.settings.xml | 36 + TEECLib/.settings/org.eclipse.cdt.core.prefs | 13 + TEECLib/inc/teec_connection.h | 65 + TEECLib/src/teec_api.c | 1451 +++++++++ TEECLib/src/teec_connection.c | 434 +++ TEEStub/.cproject | 174 ++ TEEStub/.gitignore | 1 + TEEStub/.project | 84 + TEEStub/.settings/org.eclipse.cdt.core.prefs | 16 + TEEStub/.settings/org.eclipse.cdt.ui.prefs | 2 + .../org.eclipse.ltk.core.refactoring.prefs | 2 + TEEStub/DeveloperReadme.txt | 43 + TEEStub/PropertyAccess/ClientProperty.cpp | 104 + TEEStub/PropertyAccess/ClientProperty.h | 46 + TEEStub/PropertyAccess/Property.h | 56 + TEEStub/PropertyAccess/PropertyApi.cpp | 405 +++ TEEStub/PropertyAccess/PropertyApi.h | 41 + TEEStub/PropertyAccess/PropertyUtility.cpp | 384 +++ TEEStub/PropertyAccess/PropertyUtility.h | 67 + TEEStub/PropertyAccess/TAProperty.cpp | 173 ++ TEEStub/PropertyAccess/TAProperty.h | 49 + TEEStub/PropertyAccess/TEEProperty.cpp | 158 + TEEStub/PropertyAccess/TEEProperty.h | 49 + TEEStub/PropertyAccess/rapidxml/rapidxml.hpp | 2396 +++++++++++++++ .../PropertyAccess/rapidxml/rapidxml_iterators.hpp | 151 + TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp | 426 +++ TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp | 111 + TEEStub/TACommands/CommandBase.cpp | 63 + TEEStub/TACommands/CommandBase.h | 87 + TEEStub/TACommands/CommandCloseSession.cpp | 80 + TEEStub/TACommands/CommandCloseSession.h | 45 + TEEStub/TACommands/CommandCreateEntryPoint.cpp | 71 + TEEStub/TACommands/CommandCreateEntryPoint.h | 45 + TEEStub/TACommands/CommandDestroyEntryPoint.cpp | 74 + TEEStub/TACommands/CommandDestroyEntryPoint.h | 44 + TEEStub/TACommands/CommandInvoke.cpp | 99 + TEEStub/TACommands/CommandInvoke.h | 44 + TEEStub/TACommands/CommandOpenSession.cpp | 91 + TEEStub/TACommands/CommandOpenSession.h | 44 + TEEStub/TACommands/CommandRequestCancel.cpp | 112 + TEEStub/TACommands/CommandRequestCancel.h | 63 + TEEStub/TACommands/MakeCommand.cpp | 119 + TEEStub/TACommands/MakeCommand.h | 53 + TEEStub/TACommands/SharedMemoryMap.cpp | 160 + TEEStub/TACommands/SharedMemoryMap.h | 60 + TEEStub/TEEStubServer/ConnectionSession.cpp | 162 + TEEStub/TEEStubServer/ConnectionSession.h | 75 + TEEStub/TEEStubServer/TAProperty.cpp | 85 + TEEStub/TEEStubServer/TAProperty.h | 60 + TEEStub/TEEStubServer/TEEStubServer.cpp | 61 + TEEStub/TEEStubServer/TEEStubServer.h | 47 + TEEStub/TaskStrategy/SessionState.cpp | 74 + TEEStub/TaskStrategy/SessionState.h | 52 + TEEStub/TaskStrategy/TaskQueuedStrategy.cpp | 181 ++ TEEStub/TaskStrategy/TaskQueuedStrategy.h | 74 + TEEStub/TaskStrategy/TaskStrategy.cpp | 31 + TEEStub/TaskStrategy/TaskStrategy.h | 45 + TEEStub/teestubmain.cpp | 105 + build/TEECLib/makefile | 51 + build/TEECLib/objects.mk | 8 + build/TEECLib/sources.mk | 17 + build/TEECLib/src/subdir.mk | 23 + build/TEEStub/PropertyAccess/subdir.mk | 32 + build/TEEStub/TACommands/subdir.mk | 44 + build/TEEStub/TEEStubServer/subdir.mk | 26 + build/TEEStub/TaskStrategy/subdir.mk | 26 + build/TEEStub/makefile | 69 + build/TEEStub/objects.mk | 8 + build/TEEStub/sources.mk | 31 + build/TEEStub/subdir.mk | 20 + build/build.sh | 173 ++ build/log/makefile | 46 + build/log/objects.mk | 8 + build/log/sources.mk | 17 + build/log/subdir.mk | 19 + build/osal/makefile | 46 + build/osal/objects.mk | 8 + build/osal/sources.mk | 17 + build/osal/subdir.mk | 35 + build/simulatordaemon/makefile | 69 + build/simulatordaemon/objects.mk | 8 + build/simulatordaemon/sources.mk | 30 + build/simulatordaemon/src/ClientCommands/subdir.mk | 55 + .../simulatordaemon/src/ResponseCommands/subdir.mk | 32 + .../simulatordaemon/src/TABinaryManager/subdir.mk | 29 + build/simulatordaemon/src/subdir.mk | 41 + build/ssflib/dep/cryptocore/source/base/subdir.mk | 59 + .../ssflib/dep/cryptocore/source/middle/subdir.mk | 47 + build/ssflib/dep/cryptocore/source/subdir.mk | 20 + build/ssflib/dep/swdss/source/subdir.mk | 35 + build/ssflib/dep/time/subdir.mk | 20 + build/ssflib/dep/uci/source/subdir.mk | 29 + build/ssflib/makefile | 72 + build/ssflib/objects.mk | 8 + build/ssflib/sources.mk | 33 + build/ssflib/src/subdir.mk | 44 + include/.cproject | 107 + include/.project | 26 + include/.settings/language.settings.xml | 25 + include/.settings/org.eclipse.cdt.core.prefs | 6 + include/include/config.h | 15 + include/include/tee_client_api.h | 197 ++ include/include/tee_command.h | 38 + include/include/tee_internal_api.h | 2045 +++++++++++++ include/include/tee_sim_command.h | 77 + include/include/teec_data.h | 100 + include/include/teestub_command_data.h | 59 + log/.cproject | 105 + log/.gitignore | 1 + log/.project | 26 + log/.settings/language.settings.xml | 36 + log/.settings/org.eclipse.cdt.core.prefs | 13 + log/log.c | 200 ++ log/log.h | 164 + osal/.cproject | 129 + osal/.gitignore | 1 + osal/.project | 26 + osal/.settings/org.eclipse.cdt.core.prefs | 11 + .../org.eclipse.cdt.managedbuilder.core.prefs | 7 + osal/OsaCommon.c | 439 +++ osal/OsaIpc.c | 350 +++ osal/OsaLinuxUser.h | 48 + osal/OsaQueue.c | 461 +++ osal/OsaSem.c | 448 +++ osal/OsaSignal.c | 146 + osal/OsaTask.c | 424 +++ osal/Osal.h | 459 +++ simulatordaemon/.cproject | 151 + simulatordaemon/.gitignore | 1 + simulatordaemon/.project | 29 + simulatordaemon/.settings/language.settings.xml | 22 + .../.settings/org.eclipse.cdt.core.prefs | 11 + simulatordaemon/inc/ClientCommands/CommandBase.h | 62 + .../inc/ClientCommands/CommandCloseSession.h | 39 + .../inc/ClientCommands/CommandCloseTASession.h | 39 + .../inc/ClientCommands/CommandFinContext.h | 39 + .../inc/ClientCommands/CommandInitContext.h | 39 + .../inc/ClientCommands/CommandInvokeCommand.h | 40 + .../inc/ClientCommands/CommandInvokeTACommand.h | 40 + .../inc/ClientCommands/CommandOpenSession.h | 39 + .../inc/ClientCommands/CommandOpenTASession.h | 39 + simulatordaemon/inc/ClientCommands/CommandPanic.h | 40 + .../inc/ClientCommands/CommandRegSharedMem.h | 40 + .../inc/ClientCommands/CommandRelSharedMem.h | 40 + .../inc/ClientCommands/CommandReqCancellation.h | 40 + simulatordaemon/inc/ClientCommands/MakeCommand.h | 52 + simulatordaemon/inc/ConnectionSession.h | 87 + simulatordaemon/inc/IConnectionSession.h | 37 + simulatordaemon/inc/ISession.h | 49 + simulatordaemon/inc/ITAInstance.h | 81 + .../inc/ResponseCommands/ResCommandBase.h | 56 + .../inc/ResponseCommands/ResCommandCloseSession.h | 39 + .../inc/ResponseCommands/ResCommandInvokeCommand.h | 40 + .../inc/ResponseCommands/ResCommandOpenSession.h | 39 + .../ResponseCommands/ResCommandReqCancellation.h | 41 + .../inc/ResponseCommands/ResMakeCommand.h | 52 + simulatordaemon/inc/Session.h | 58 + simulatordaemon/inc/SimulatorDaemonServer.h | 41 + simulatordaemon/inc/TAFactory.h | 59 + simulatordaemon/inc/TAInstance.h | 107 + simulatordaemon/inc/TEEContext.h | 75 + simulatordaemon/inc/ioService.h | 47 + simulatordaemon/inc/path.h | 31 + .../src/ClientCommands/CommandCloseSession.cpp | 57 + .../src/ClientCommands/CommandCloseTASession.cpp | 49 + .../src/ClientCommands/CommandFinContext.cpp | 48 + .../src/ClientCommands/CommandInitContext.cpp | 49 + .../src/ClientCommands/CommandInvokeCommand.cpp | 56 + .../src/ClientCommands/CommandInvokeTACommand.cpp | 53 + .../src/ClientCommands/CommandOpenSession.cpp | 54 + .../src/ClientCommands/CommandOpenTASession.cpp | 53 + .../src/ClientCommands/CommandPanic.cpp | 48 + .../src/ClientCommands/CommandRegSharedMem.cpp | 56 + .../src/ClientCommands/CommandRelSharedMem.cpp | 56 + .../src/ClientCommands/CommandReqCancellation.cpp | 48 + simulatordaemon/src/ClientCommands/MakeCommand.cpp | 192 ++ simulatordaemon/src/ConnectionSession.cpp | 210 ++ .../src/RemoteSystemsTempFiles/.project | 12 + .../ResponseCommands/ResCommandCloseSession.cpp | 117 + .../ResponseCommands/ResCommandInvokeCommand.cpp | 115 + .../src/ResponseCommands/ResCommandOpenSession.cpp | 112 + .../ResponseCommands/ResCommandReqCancellation.cpp | 49 + .../src/ResponseCommands/ResMakeCommand.cpp | 116 + simulatordaemon/src/Session.cpp | 353 +++ simulatordaemon/src/SimulatorDaemon.cpp | 85 + simulatordaemon/src/SimulatorDaemonServer.cpp | 66 + simulatordaemon/src/TABinaryManager/.cproject | 123 + simulatordaemon/src/TABinaryManager/.project | 64 + simulatordaemon/src/TABinaryManager/Config.h | 28 + .../src/TABinaryManager/Debug/TABinaryManager | Bin 0 -> 380816 bytes .../src/TABinaryManager/Debug/TABinaryManager.d | 13 + .../src/TABinaryManager/Debug/TAManifest.d | 10 + .../src/TABinaryManager/Debug/TAUnpack.d | 3 + .../src/TABinaryManager/Debug/TestMain.d | 13 + simulatordaemon/src/TABinaryManager/Debug/makefile | 58 + .../src/TABinaryManager/Debug/objects.mk | 8 + .../src/TABinaryManager/Debug/sources.mk | 27 + .../src/TABinaryManager/Debug/subdir.mk | 33 + .../src/TABinaryManager/TABinaryManager.cpp | 505 +++ .../src/TABinaryManager/TABinaryManager.h | 104 + simulatordaemon/src/TABinaryManager/TAManifest.cpp | 213 ++ simulatordaemon/src/TABinaryManager/TAManifest.h | 104 + simulatordaemon/src/TABinaryManager/TAUnpack.cpp | 163 + simulatordaemon/src/TABinaryManager/TAUnpack.h | 80 + simulatordaemon/src/TABinaryManager/TestMain.cpp | 80 + .../src/TABinaryManager/rapidxml/rapidxml.hpp | 2396 +++++++++++++++ .../rapidxml/rapidxml_iterators.hpp | 151 + .../TABinaryManager/rapidxml/rapidxml_print.hpp | 426 +++ .../TABinaryManager/rapidxml/rapidxml_utils.hpp | 111 + simulatordaemon/src/TAFactory.cpp | 440 +++ simulatordaemon/src/TAInstance.cpp | 444 +++ simulatordaemon/src/TEEContext.cpp | 544 ++++ simulatordaemon/src/ioService.cpp | 39 + simulatordaemon/src/rapidxml/rapidxml.hpp | 2396 +++++++++++++++ simulatordaemon/src/scripts/update_uuid_list.sh | 1189 ++++++++ ssflib/.cproject | 177 ++ ssflib/.gitignore | 1 + ssflib/.project | 27 + ssflib/.settings/org.eclipse.cdt.core.prefs | 31 + ssflib/dep/cryptocore/include/CC_API.h | 243 ++ ssflib/dep/cryptocore/include/CC_Constants.h | 162 + ssflib/dep/cryptocore/include/CC_Context.h | 387 +++ ssflib/dep/cryptocore/include/CC_Type.h | 38 + ssflib/dep/cryptocore/include/CryptoCore.h | 51 + ssflib/dep/cryptocore/include/base/cc_ANSI_x931.h | 49 + ssflib/dep/cryptocore/include/base/cc_aes.h | 171 ++ ssflib/dep/cryptocore/include/base/cc_bignum.h | 697 +++++ ssflib/dep/cryptocore/include/base/cc_des.h | 412 +++ ssflib/dep/cryptocore/include/base/cc_ecc.h | 249 ++ ssflib/dep/cryptocore/include/base/cc_fast_math.h | 290 ++ ssflib/dep/cryptocore/include/base/cc_hash.h | 337 ++ ssflib/dep/cryptocore/include/base/cc_md5.h | 30 + ssflib/dep/cryptocore/include/base/cc_moo.h | 206 ++ ssflib/dep/cryptocore/include/base/cc_pkcs1_v21.h | 195 ++ ssflib/dep/cryptocore/include/base/cc_rc4.h | 61 + ssflib/dep/cryptocore/include/base/cc_sha1.h | 30 + ssflib/dep/cryptocore/include/base/cc_sha2.h | 44 + ssflib/dep/cryptocore/include/base/cc_snow2.h | 68 + ssflib/dep/cryptocore/include/drm_macro.h | 201 ++ ssflib/dep/cryptocore/include/middle/cc_cmac.h | 96 + ssflib/dep/cryptocore/include/middle/cc_dh.h | 94 + ssflib/dep/cryptocore/include/middle/cc_dsa.h | 171 ++ ssflib/dep/cryptocore/include/middle/cc_ecdh.h | 61 + ssflib/dep/cryptocore/include/middle/cc_ecdsa.h | 144 + ssflib/dep/cryptocore/include/middle/cc_hmac.h | 94 + ssflib/dep/cryptocore/include/middle/cc_rng.h | 60 + ssflib/dep/cryptocore/include/middle/cc_rsa.h | 351 +++ .../dep/cryptocore/include/middle/cc_symmetric.h | 247 ++ ssflib/dep/cryptocore/include/middle/cc_tdes.h | 85 + ssflib/dep/cryptocore/source/CC_API.c | 448 +++ ssflib/dep/cryptocore/source/base/cc_ANSI_x931.c | 110 + ssflib/dep/cryptocore/source/base/cc_aes.c | 1389 +++++++++ ssflib/dep/cryptocore/source/base/cc_bignum.c | 3202 ++++++++++++++++++++ ssflib/dep/cryptocore/source/base/cc_des.c | 168 + ssflib/dep/cryptocore/source/base/cc_ecc.c | 1280 ++++++++ ssflib/dep/cryptocore/source/base/cc_fast_math.c | 914 ++++++ ssflib/dep/cryptocore/source/base/cc_hash.c | 578 ++++ ssflib/dep/cryptocore/source/base/cc_md5.c | 267 ++ ssflib/dep/cryptocore/source/base/cc_moo.c | 487 +++ ssflib/dep/cryptocore/source/base/cc_pkcs1_v21.c | 1068 +++++++ ssflib/dep/cryptocore/source/base/cc_rc4.c | 161 + ssflib/dep/cryptocore/source/base/cc_sha1.c | 477 +++ ssflib/dep/cryptocore/source/base/cc_sha2.c | 660 ++++ ssflib/dep/cryptocore/source/base/cc_snow2.c | 404 +++ ssflib/dep/cryptocore/source/middle/cc_cmac.c | 260 ++ ssflib/dep/cryptocore/source/middle/cc_dh.c | 333 ++ ssflib/dep/cryptocore/source/middle/cc_dsa.c | 608 ++++ ssflib/dep/cryptocore/source/middle/cc_ecdh.c | 204 ++ ssflib/dep/cryptocore/source/middle/cc_ecdsa.c | 666 ++++ ssflib/dep/cryptocore/source/middle/cc_hmac.c | 574 ++++ ssflib/dep/cryptocore/source/middle/cc_rng.c | 69 + ssflib/dep/cryptocore/source/middle/cc_rsa.c | 1924 ++++++++++++ ssflib/dep/cryptocore/source/middle/cc_symmetric.c | 1703 +++++++++++ ssflib/dep/cryptocore/source/middle/cc_tdes.c | 131 + ssflib/dep/swdss/include/file_op.h | 117 + ssflib/dep/swdss/include/secure_file.h | 301 ++ ssflib/dep/swdss/include/slog.h | 31 + ssflib/dep/swdss/include/ss_api.h | 179 ++ ssflib/dep/swdss/include/ss_crypto.h | 130 + ssflib/dep/swdss/include/ss_misc.h | 29 + ssflib/dep/swdss/include/ss_temp_store.h | 81 + ssflib/dep/swdss/include/ss_types.h | 99 + ssflib/dep/swdss/source/file_op.cpp | 243 ++ ssflib/dep/swdss/source/secure_file.cpp | 1743 +++++++++++ ssflib/dep/swdss/source/ss_api.cpp | 150 + ssflib/dep/swdss/source/ss_crypto.cpp | 316 ++ ssflib/dep/swdss/source/ss_misc.cpp | 62 + ssflib/dep/swdss/source/ss_temp_store.cpp | 189 ++ ssflib/dep/time/ssf_time.cpp | 209 ++ ssflib/dep/uci/include/uci_aes_xcbc_mac.h | 52 + ssflib/dep/uci/include/uci_api.h | 465 +++ ssflib/dep/uci/include/uci_cryptocore.h | 380 +++ ssflib/dep/uci/include/uci_hwcrypto.h | 109 + ssflib/dep/uci/include/uci_internal.h | 39 + ssflib/dep/uci/include/uci_type.h | 456 +++ ssflib/dep/uci/source/uci_aes_xcbc_mac.c | 137 + ssflib/dep/uci/source/uci_api.c | 674 ++++ ssflib/dep/uci/source/uci_cryptocore.c | 972 ++++++ ssflib/dep/uci/source/uci_hwcrypto.c | 813 +++++ ssflib/inc/app_debug.h | 75 + ssflib/inc/ssf_client.h | 34 + ssflib/inc/ssf_lib.h | 45 + ssflib/inc/ssf_storage.h | 263 ++ ssflib/src/app_debug.c | 108 + ssflib/src/ssf_arithmetic.c | 741 +++++ ssflib/src/ssf_client.c | 190 ++ ssflib/src/ssf_crypto.c | 2598 ++++++++++++++++ ssflib/src/ssf_lib.c | 114 + ssflib/src/ssf_malloc.c | 239 ++ ssflib/src/ssf_panic.c | 48 + ssflib/src/ssf_storage.c | 2037 +++++++++++++ ssflib/src/ssf_taentrypoint.c | 118 + 317 files changed, 68913 insertions(+) create mode 100644 .cproject create mode 100644 .project create mode 100755 TEECLib/.cproject create mode 100755 TEECLib/.gitignore create mode 100755 TEECLib/.project create mode 100755 TEECLib/.settings/language.settings.xml create mode 100755 TEECLib/.settings/org.eclipse.cdt.core.prefs create mode 100755 TEECLib/inc/teec_connection.h create mode 100755 TEECLib/src/teec_api.c create mode 100755 TEECLib/src/teec_connection.c create mode 100755 TEEStub/.cproject create mode 100755 TEEStub/.gitignore create mode 100755 TEEStub/.project create mode 100755 TEEStub/.settings/org.eclipse.cdt.core.prefs create mode 100755 TEEStub/.settings/org.eclipse.cdt.ui.prefs create mode 100755 TEEStub/.settings/org.eclipse.ltk.core.refactoring.prefs create mode 100755 TEEStub/DeveloperReadme.txt create mode 100755 TEEStub/PropertyAccess/ClientProperty.cpp create mode 100755 TEEStub/PropertyAccess/ClientProperty.h create mode 100755 TEEStub/PropertyAccess/Property.h create mode 100755 TEEStub/PropertyAccess/PropertyApi.cpp create mode 100755 TEEStub/PropertyAccess/PropertyApi.h create mode 100755 TEEStub/PropertyAccess/PropertyUtility.cpp create mode 100755 TEEStub/PropertyAccess/PropertyUtility.h create mode 100755 TEEStub/PropertyAccess/TAProperty.cpp create mode 100755 TEEStub/PropertyAccess/TAProperty.h create mode 100755 TEEStub/PropertyAccess/TEEProperty.cpp create mode 100755 TEEStub/PropertyAccess/TEEProperty.h create mode 100755 TEEStub/PropertyAccess/rapidxml/rapidxml.hpp create mode 100755 TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp create mode 100755 TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp create mode 100755 TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp create mode 100755 TEEStub/TACommands/CommandBase.cpp create mode 100755 TEEStub/TACommands/CommandBase.h create mode 100755 TEEStub/TACommands/CommandCloseSession.cpp create mode 100755 TEEStub/TACommands/CommandCloseSession.h create mode 100755 TEEStub/TACommands/CommandCreateEntryPoint.cpp create mode 100755 TEEStub/TACommands/CommandCreateEntryPoint.h create mode 100755 TEEStub/TACommands/CommandDestroyEntryPoint.cpp create mode 100755 TEEStub/TACommands/CommandDestroyEntryPoint.h create mode 100755 TEEStub/TACommands/CommandInvoke.cpp create mode 100755 TEEStub/TACommands/CommandInvoke.h create mode 100755 TEEStub/TACommands/CommandOpenSession.cpp create mode 100755 TEEStub/TACommands/CommandOpenSession.h create mode 100755 TEEStub/TACommands/CommandRequestCancel.cpp create mode 100755 TEEStub/TACommands/CommandRequestCancel.h create mode 100755 TEEStub/TACommands/MakeCommand.cpp create mode 100755 TEEStub/TACommands/MakeCommand.h create mode 100755 TEEStub/TACommands/SharedMemoryMap.cpp create mode 100755 TEEStub/TACommands/SharedMemoryMap.h create mode 100755 TEEStub/TEEStubServer/ConnectionSession.cpp create mode 100755 TEEStub/TEEStubServer/ConnectionSession.h create mode 100755 TEEStub/TEEStubServer/TAProperty.cpp create mode 100755 TEEStub/TEEStubServer/TAProperty.h create mode 100755 TEEStub/TEEStubServer/TEEStubServer.cpp create mode 100755 TEEStub/TEEStubServer/TEEStubServer.h create mode 100755 TEEStub/TaskStrategy/SessionState.cpp create mode 100755 TEEStub/TaskStrategy/SessionState.h create mode 100755 TEEStub/TaskStrategy/TaskQueuedStrategy.cpp create mode 100755 TEEStub/TaskStrategy/TaskQueuedStrategy.h create mode 100755 TEEStub/TaskStrategy/TaskStrategy.cpp create mode 100755 TEEStub/TaskStrategy/TaskStrategy.h create mode 100755 TEEStub/teestubmain.cpp create mode 100755 build/TEECLib/makefile create mode 100755 build/TEECLib/objects.mk create mode 100755 build/TEECLib/sources.mk create mode 100755 build/TEECLib/src/subdir.mk create mode 100755 build/TEEStub/PropertyAccess/subdir.mk create mode 100755 build/TEEStub/TACommands/subdir.mk create mode 100755 build/TEEStub/TEEStubServer/subdir.mk create mode 100755 build/TEEStub/TaskStrategy/subdir.mk create mode 100755 build/TEEStub/makefile create mode 100755 build/TEEStub/objects.mk create mode 100755 build/TEEStub/sources.mk create mode 100755 build/TEEStub/subdir.mk create mode 100755 build/build.sh create mode 100755 build/log/makefile create mode 100755 build/log/objects.mk create mode 100755 build/log/sources.mk create mode 100755 build/log/subdir.mk create mode 100755 build/osal/makefile create mode 100755 build/osal/objects.mk create mode 100755 build/osal/sources.mk create mode 100755 build/osal/subdir.mk create mode 100755 build/simulatordaemon/makefile create mode 100755 build/simulatordaemon/objects.mk create mode 100755 build/simulatordaemon/sources.mk create mode 100755 build/simulatordaemon/src/ClientCommands/subdir.mk create mode 100755 build/simulatordaemon/src/ResponseCommands/subdir.mk create mode 100755 build/simulatordaemon/src/TABinaryManager/subdir.mk create mode 100755 build/simulatordaemon/src/subdir.mk create mode 100755 build/ssflib/dep/cryptocore/source/base/subdir.mk create mode 100755 build/ssflib/dep/cryptocore/source/middle/subdir.mk create mode 100755 build/ssflib/dep/cryptocore/source/subdir.mk create mode 100755 build/ssflib/dep/swdss/source/subdir.mk create mode 100755 build/ssflib/dep/time/subdir.mk create mode 100755 build/ssflib/dep/uci/source/subdir.mk create mode 100755 build/ssflib/makefile create mode 100755 build/ssflib/objects.mk create mode 100755 build/ssflib/sources.mk create mode 100755 build/ssflib/src/subdir.mk create mode 100755 include/.cproject create mode 100755 include/.project create mode 100755 include/.settings/language.settings.xml create mode 100755 include/.settings/org.eclipse.cdt.core.prefs create mode 100755 include/include/config.h create mode 100755 include/include/tee_client_api.h create mode 100755 include/include/tee_command.h create mode 100755 include/include/tee_internal_api.h create mode 100755 include/include/tee_sim_command.h create mode 100755 include/include/teec_data.h create mode 100755 include/include/teestub_command_data.h create mode 100755 log/.cproject create mode 100755 log/.gitignore create mode 100755 log/.project create mode 100755 log/.settings/language.settings.xml create mode 100755 log/.settings/org.eclipse.cdt.core.prefs create mode 100755 log/log.c create mode 100755 log/log.h create mode 100755 osal/.cproject create mode 100755 osal/.gitignore create mode 100755 osal/.project create mode 100755 osal/.settings/org.eclipse.cdt.core.prefs create mode 100755 osal/.settings/org.eclipse.cdt.managedbuilder.core.prefs create mode 100755 osal/OsaCommon.c create mode 100755 osal/OsaIpc.c create mode 100755 osal/OsaLinuxUser.h create mode 100755 osal/OsaQueue.c create mode 100755 osal/OsaSem.c create mode 100755 osal/OsaSignal.c create mode 100755 osal/OsaTask.c create mode 100755 osal/Osal.h create mode 100755 simulatordaemon/.cproject create mode 100755 simulatordaemon/.gitignore create mode 100755 simulatordaemon/.project create mode 100755 simulatordaemon/.settings/language.settings.xml create mode 100755 simulatordaemon/.settings/org.eclipse.cdt.core.prefs create mode 100755 simulatordaemon/inc/ClientCommands/CommandBase.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandCloseSession.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandCloseTASession.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandFinContext.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandInitContext.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandInvokeCommand.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandInvokeTACommand.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandOpenSession.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandOpenTASession.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandPanic.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandRegSharedMem.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandRelSharedMem.h create mode 100755 simulatordaemon/inc/ClientCommands/CommandReqCancellation.h create mode 100755 simulatordaemon/inc/ClientCommands/MakeCommand.h create mode 100755 simulatordaemon/inc/ConnectionSession.h create mode 100644 simulatordaemon/inc/IConnectionSession.h create mode 100644 simulatordaemon/inc/ISession.h create mode 100644 simulatordaemon/inc/ITAInstance.h create mode 100755 simulatordaemon/inc/ResponseCommands/ResCommandBase.h create mode 100755 simulatordaemon/inc/ResponseCommands/ResCommandCloseSession.h create mode 100755 simulatordaemon/inc/ResponseCommands/ResCommandInvokeCommand.h create mode 100755 simulatordaemon/inc/ResponseCommands/ResCommandOpenSession.h create mode 100755 simulatordaemon/inc/ResponseCommands/ResCommandReqCancellation.h create mode 100755 simulatordaemon/inc/ResponseCommands/ResMakeCommand.h create mode 100755 simulatordaemon/inc/Session.h create mode 100755 simulatordaemon/inc/SimulatorDaemonServer.h create mode 100755 simulatordaemon/inc/TAFactory.h create mode 100755 simulatordaemon/inc/TAInstance.h create mode 100755 simulatordaemon/inc/TEEContext.h create mode 100755 simulatordaemon/inc/ioService.h create mode 100755 simulatordaemon/inc/path.h create mode 100755 simulatordaemon/src/ClientCommands/CommandCloseSession.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandCloseTASession.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandFinContext.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandInitContext.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandInvokeCommand.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandInvokeTACommand.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandOpenSession.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandOpenTASession.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandPanic.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandRegSharedMem.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandRelSharedMem.cpp create mode 100755 simulatordaemon/src/ClientCommands/CommandReqCancellation.cpp create mode 100755 simulatordaemon/src/ClientCommands/MakeCommand.cpp create mode 100755 simulatordaemon/src/ConnectionSession.cpp create mode 100755 simulatordaemon/src/RemoteSystemsTempFiles/.project create mode 100755 simulatordaemon/src/ResponseCommands/ResCommandCloseSession.cpp create mode 100755 simulatordaemon/src/ResponseCommands/ResCommandInvokeCommand.cpp create mode 100755 simulatordaemon/src/ResponseCommands/ResCommandOpenSession.cpp create mode 100755 simulatordaemon/src/ResponseCommands/ResCommandReqCancellation.cpp create mode 100755 simulatordaemon/src/ResponseCommands/ResMakeCommand.cpp create mode 100755 simulatordaemon/src/Session.cpp create mode 100755 simulatordaemon/src/SimulatorDaemon.cpp create mode 100755 simulatordaemon/src/SimulatorDaemonServer.cpp create mode 100755 simulatordaemon/src/TABinaryManager/.cproject create mode 100755 simulatordaemon/src/TABinaryManager/.project create mode 100755 simulatordaemon/src/TABinaryManager/Config.h create mode 100755 simulatordaemon/src/TABinaryManager/Debug/TABinaryManager create mode 100755 simulatordaemon/src/TABinaryManager/Debug/TABinaryManager.d create mode 100755 simulatordaemon/src/TABinaryManager/Debug/TAManifest.d create mode 100755 simulatordaemon/src/TABinaryManager/Debug/TAUnpack.d create mode 100755 simulatordaemon/src/TABinaryManager/Debug/TestMain.d create mode 100755 simulatordaemon/src/TABinaryManager/Debug/makefile create mode 100755 simulatordaemon/src/TABinaryManager/Debug/objects.mk create mode 100755 simulatordaemon/src/TABinaryManager/Debug/sources.mk create mode 100755 simulatordaemon/src/TABinaryManager/Debug/subdir.mk create mode 100755 simulatordaemon/src/TABinaryManager/TABinaryManager.cpp create mode 100755 simulatordaemon/src/TABinaryManager/TABinaryManager.h create mode 100755 simulatordaemon/src/TABinaryManager/TAManifest.cpp create mode 100755 simulatordaemon/src/TABinaryManager/TAManifest.h create mode 100755 simulatordaemon/src/TABinaryManager/TAUnpack.cpp create mode 100755 simulatordaemon/src/TABinaryManager/TAUnpack.h create mode 100755 simulatordaemon/src/TABinaryManager/TestMain.cpp create mode 100755 simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp create mode 100755 simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_iterators.hpp create mode 100755 simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_print.hpp create mode 100755 simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_utils.hpp create mode 100755 simulatordaemon/src/TAFactory.cpp create mode 100755 simulatordaemon/src/TAInstance.cpp create mode 100755 simulatordaemon/src/TEEContext.cpp create mode 100755 simulatordaemon/src/ioService.cpp create mode 100755 simulatordaemon/src/rapidxml/rapidxml.hpp create mode 100755 simulatordaemon/src/scripts/update_uuid_list.sh create mode 100755 ssflib/.cproject create mode 100755 ssflib/.gitignore create mode 100755 ssflib/.project create mode 100755 ssflib/.settings/org.eclipse.cdt.core.prefs create mode 100755 ssflib/dep/cryptocore/include/CC_API.h create mode 100755 ssflib/dep/cryptocore/include/CC_Constants.h create mode 100755 ssflib/dep/cryptocore/include/CC_Context.h create mode 100755 ssflib/dep/cryptocore/include/CC_Type.h create mode 100755 ssflib/dep/cryptocore/include/CryptoCore.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_ANSI_x931.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_aes.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_bignum.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_des.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_ecc.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_fast_math.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_hash.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_md5.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_moo.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_pkcs1_v21.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_rc4.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_sha1.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_sha2.h create mode 100755 ssflib/dep/cryptocore/include/base/cc_snow2.h create mode 100755 ssflib/dep/cryptocore/include/drm_macro.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_cmac.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_dh.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_dsa.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_ecdh.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_ecdsa.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_hmac.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_rng.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_rsa.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_symmetric.h create mode 100755 ssflib/dep/cryptocore/include/middle/cc_tdes.h create mode 100755 ssflib/dep/cryptocore/source/CC_API.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_ANSI_x931.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_aes.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_bignum.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_des.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_ecc.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_fast_math.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_hash.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_md5.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_moo.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_pkcs1_v21.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_rc4.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_sha1.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_sha2.c create mode 100755 ssflib/dep/cryptocore/source/base/cc_snow2.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_cmac.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_dh.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_dsa.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_ecdh.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_ecdsa.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_hmac.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_rng.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_rsa.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_symmetric.c create mode 100755 ssflib/dep/cryptocore/source/middle/cc_tdes.c create mode 100755 ssflib/dep/swdss/include/file_op.h create mode 100755 ssflib/dep/swdss/include/secure_file.h create mode 100755 ssflib/dep/swdss/include/slog.h create mode 100755 ssflib/dep/swdss/include/ss_api.h create mode 100755 ssflib/dep/swdss/include/ss_crypto.h create mode 100755 ssflib/dep/swdss/include/ss_misc.h create mode 100755 ssflib/dep/swdss/include/ss_temp_store.h create mode 100755 ssflib/dep/swdss/include/ss_types.h create mode 100755 ssflib/dep/swdss/source/file_op.cpp create mode 100755 ssflib/dep/swdss/source/secure_file.cpp create mode 100755 ssflib/dep/swdss/source/ss_api.cpp create mode 100755 ssflib/dep/swdss/source/ss_crypto.cpp create mode 100755 ssflib/dep/swdss/source/ss_misc.cpp create mode 100755 ssflib/dep/swdss/source/ss_temp_store.cpp create mode 100755 ssflib/dep/time/ssf_time.cpp create mode 100755 ssflib/dep/uci/include/uci_aes_xcbc_mac.h create mode 100755 ssflib/dep/uci/include/uci_api.h create mode 100755 ssflib/dep/uci/include/uci_cryptocore.h create mode 100755 ssflib/dep/uci/include/uci_hwcrypto.h create mode 100755 ssflib/dep/uci/include/uci_internal.h create mode 100755 ssflib/dep/uci/include/uci_type.h create mode 100755 ssflib/dep/uci/source/uci_aes_xcbc_mac.c create mode 100755 ssflib/dep/uci/source/uci_api.c create mode 100755 ssflib/dep/uci/source/uci_cryptocore.c create mode 100755 ssflib/dep/uci/source/uci_hwcrypto.c create mode 100755 ssflib/inc/app_debug.h create mode 100755 ssflib/inc/ssf_client.h create mode 100755 ssflib/inc/ssf_lib.h create mode 100755 ssflib/inc/ssf_storage.h create mode 100755 ssflib/src/app_debug.c create mode 100755 ssflib/src/ssf_arithmetic.c create mode 100755 ssflib/src/ssf_client.c create mode 100755 ssflib/src/ssf_crypto.c create mode 100755 ssflib/src/ssf_lib.c create mode 100755 ssflib/src/ssf_malloc.c create mode 100755 ssflib/src/ssf_panic.c create mode 100755 ssflib/src/ssf_storage.c create mode 100755 ssflib/src/ssf_taentrypoint.c diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..2e304b4 --- /dev/null +++ b/.cproject @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..bc6a330 --- /dev/null +++ b/.project @@ -0,0 +1,27 @@ + + + simulator + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/TEECLib/.cproject b/TEECLib/.cproject new file mode 100755 index 0000000..9a99562 --- /dev/null +++ b/TEECLib/.cproject @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TEECLib/.gitignore b/TEECLib/.gitignore new file mode 100755 index 0000000..3df573f --- /dev/null +++ b/TEECLib/.gitignore @@ -0,0 +1 @@ +/Debug/ diff --git a/TEECLib/.project b/TEECLib/.project new file mode 100755 index 0000000..6b5f6d3 --- /dev/null +++ b/TEECLib/.project @@ -0,0 +1,28 @@ + + + TEECLib + + + log + osal + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/TEECLib/.settings/language.settings.xml b/TEECLib/.settings/language.settings.xml new file mode 100755 index 0000000..a85d310 --- /dev/null +++ b/TEECLib/.settings/language.settings.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TEECLib/.settings/org.eclipse.cdt.core.prefs b/TEECLib/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..40a6ba6 --- /dev/null +++ b/TEECLib/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.1187618160/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.1187618160/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.295131884/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.295131884/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.295131884/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\Program Files (x86)\\Java\\jre1.8.0_45\\bin;C\:\\Program Files\\eclipse;C\:/Program Files/Java/jre1.8.0_31/bin/server;C\:/Program Files/Java/jre1.8.0_31/bin;C\:/Program Files/Java/jre1.8.0_31/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\csvn\\bin\\;C\:\\csvn\\Python25\\;C\:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files\\Diskeeper Corporation\\ExpressCache\\;C\:\\Program Files (x86)\\Windows Live\\Shared;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x64;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files (x86)\\WinSCP\\;C\:\\Program Files (x86)\\PuTTY;C\:\\Program Files\\Microsoft\\Web Platform Installer\\;C\:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C\:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;C\:\\Program Files (x86)\\doxygen\\bin;C\:\\Program Files (x86)\\sfk168;C\:\\Program Files (x86)\\vlc-2.1.0;C\:\\Python27\\Scripts;C\:\\Program Files (x86)\\GnuWin32\\bin;C\:\\Python27;C\:\\Program Files (x86)\\Subversion\\bin;c\:\\Program Files\\Synergy;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\MinGW\\lib\\gcc\\mingw32\\4.8.1;C\:\\Program Files (x86)\\Windows Kits\\8.1\\Windows Performance Toolkit\\;C\:\\Program Files (x86)\\GitExtensions\\;C\:\\Program Files\\Perforce;c\:\\Program Files\\Java\\jre1.8.0_31\\bin\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;D\:\\samsung-tv-sdk\\ide;${Path};D\:\\samsung-tv-sdk\\tools\\i386-linux-gnueabi-gcc-4.6\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.295131884/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838.295131884/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x64;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files (x86)\\GitExtensions\\;D\:\\Tizen\\tizen-sdk\\tools;D\:\\Android\\android-sdk\\platform-tools;D\:\\Android\\android-ndk-r10c;C\:\\Program Files\\Perforce;D\:\\eclipse\\eclipse-rcp-luna-SR1-win32-x86_64;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\bin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\mingbin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1008004838/appendContributed=true diff --git a/TEECLib/inc/teec_connection.h b/TEECLib/inc/teec_connection.h new file mode 100755 index 0000000..a921a03 --- /dev/null +++ b/TEECLib/inc/teec_connection.h @@ -0,0 +1,65 @@ +/* + * ===================================================================================== + * + * Filename: teec_connection.h + * + * Description: TEEC Connection Header file + * + * Version: 1.0 + * Created: 26 March 2015 12:43:30 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef __TEEC_CONNECTION_H__ +#define __TEEC_CONNECTION_H__ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include "OsaLinuxUser.h" +#include "tee_client_api.h" +#include "tee_command.h" +#include "teec_data.h" +#include "log.h" + +// TEEC_Context void* imp structure +typedef struct TEEC_CONTEXT_IMP { + uint32_t contextID; + int32_t sockfd; + pthread_mutex_t lock; +} TEEC_ContextImp; + +// TEEC_Session void* imp structure +typedef struct TEEC_SESSION_IMP { + uint32_t sessionID; + TEEC_Context *context; +} TEEC_SessionImp; + +// TEEC_SharedMemory void* imp structure +typedef struct TEEC_SHARED_MEMORY_IMP { + int32_t shmKey; + int32_t memId; + void* allocPtr; + TEEC_Context *context; +} TEEC_SharedMemoryImp; + +// TEEC_Operation void* imp structure +typedef struct TEEC_OPERATION_IMP { +TEEC_Session *session; +uint32_t OperationID; +} TEEC_OperationImp; + +int32_t connecttoServer(void); +void disconnectfromServer(int32_t ServerSocket); +uint32_t sendCommand(int32_t sockfd, TEE_CMD cmd, void* data, size_t size); + +#endif /* __TEEC_CONNECTION_H__ */ diff --git a/TEECLib/src/teec_api.c b/TEECLib/src/teec_api.c new file mode 100755 index 0000000..7a81e34 --- /dev/null +++ b/TEECLib/src/teec_api.c @@ -0,0 +1,1451 @@ +/* + * ===================================================================================== + * + * Filename: teec_api.c + * + * Description: TEEC API implementation + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "teec_connection.h" +#include + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define PAGE_SIZE 0x1000 +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +#define MAX_ID 64U +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ + +typedef struct smem_info { + int32_t memKey; + uint32_t ftokID; + uint32_t pathID; +} mem_info; + +typedef struct sTEEC_ContextList { + LIST_ENTRY(sTEEC_ContextList) list; + TEEC_Context *context; +} TEEC_ContextList; + +typedef struct sMemkeyList { + LIST_ENTRY(sMemkeyList) mem_list; + mem_info *mem; +} MemkeyList; + +LIST_HEAD(context_listhead, sTEEC_ContextList) context_list = LIST_HEAD_INITIALIZER(NULL); + +LIST_HEAD(memkey_listhead, sMemkeyList) memkey_list = LIST_HEAD_INITIALIZER(NULL); + +uint32_t ftokId = 0; +uint32_t pathId = 0; + +static pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER; +static pthread_rwlock_t context_list_lock = PTHREAD_RWLOCK_INITIALIZER; +static pthread_rwlock_t memkey_list_lock = PTHREAD_RWLOCK_INITIALIZER; +static pthread_rwlock_t file_create_lock = PTHREAD_RWLOCK_INITIALIZER; + + +/*----------------------------------------------------------------------------- + * Local functions + *-----------------------------------------------------------------------------*/ +/* + * === FUNCTION ====================================================================== + * Name: initShm + * Description: Local function to create shm pathname file + * Parameters: path - pathname + * Return: 0 on success + * -1 on failure + * ===================================================================================== + */ +static int32_t initShm(char* path) { + LOGD(TEEC_LIB, "Entry"); + int fd; + struct stat attr; + snprintf(path, 20, "/tmp/shm%d", pathId); + + pthread_rwlock_wrlock(&file_create_lock); + if (stat(path, &attr) == -1) { + fd = creat(path, S_IRWXU); + if (-1 == fd) { + LOGE(TEEC_LIB, "shm file creation failed"); + return -1; + } + close(fd); + } + pthread_rwlock_unlock(&file_create_lock); + return 0; +} + +/* + * === FUNCTION ====================================================================== + * Name: checkMemory + * Description: Local function to check if the Memory is already in use + * Parameters: None + * Return: 0 on success + * -1 on failure + * ===================================================================================== + */ +static int32_t checkMemory(void) { + LOGD(TEEC_LIB, "Entry"); + uint32_t found = 0; + MemkeyList *pmem_info; + + /* Check if the memory is in the memory list containing all the allocated + * shared memory info + */ + pthread_rwlock_wrlock(&memkey_list_lock); + LIST_FOREACH(pmem_info, &memkey_list, mem_list) + { + if ((pmem_info->mem->ftokID == ftokId) && (pmem_info->mem->pathID == pathId)) { + found = 1; + break; + } + } + pthread_rwlock_unlock(&memkey_list_lock); + return found; +} + +/* + * === FUNCTION ====================================================================== + * Name: allocateSharedMemory + * Description: Local function to allocate shared memory + * Parameters: shm - TEEC_SharedMemory type of data to allocate memory and update + * Return: memoryKey on success + * -1 on failure + * ===================================================================================== + */ +static int32_t allocateSharedMemory(TEEC_SharedMemory *shm) { + LOGD(TEEC_LIB, "Entry"); + TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)shm->imp; + int32_t memKey = -1; + uint32_t size = shm->size; + int32_t shmid = -1; + char path[20]; + uint32_t pathIdBase = pathId; + uint32_t ftokIdBase = ftokId; + MemkeyList *pmem_info = NULL; + + pthread_rwlock_wrlock(&key_lock); + // Get shared memory key to be shared with TEEStub + do { + ftokId = (ftokId % MAX_ID) + 1; + if (1 == ftokId) { + pathId = (pathId % MAX_ID) + 1; + if (-1 == initShm(path)) { + LOGE(TEEC_LIB, "initShm failed"); + return TEEC_ERROR_GENERIC; + } + } else { + snprintf(path, 20, "/tmp/shm%d", pathId); + } + } while((checkMemory()) && (pathIdBase != pathId) && (ftokIdBase != ftokId)); + + if (checkMemory()) { + LOGE(TEEC_LIB, "All memory segments already in use"); + return TEEC_ERROR_OUT_OF_MEMORY; + } + + if ((memKey = ftok(path, ftokId)) == -1) { + perror("ftok: ftok failed"); + } + + pmem_info = (MemkeyList*)OsaMalloc(sizeof(MemkeyList)); + if (!pmem_info) { + LOGE(TEEC_LIB, "pmem_info malloc failed"); + return TEEC_ERROR_OUT_OF_MEMORY; + } + pmem_info->mem = (mem_info*)OsaMalloc(sizeof(mem_info)); + if (!pmem_info->mem) { + LOGE(TEEC_LIB, "pmem_info->mem malloc failed"); + OsaFree(pmem_info); + return TEEC_ERROR_OUT_OF_MEMORY; + } + + pmem_info->mem->ftokID = ftokId; + pmem_info->mem->pathID = pathId - 1; + pthread_rwlock_unlock(&key_lock); + // Check if the obtained Shared Memory Key is valid + if (memKey == -1) { + LOGE(TEEC_LIB, "ftok failed"); + OsaFree(pmem_info->mem); + OsaFree(pmem_info); + return TEEC_ERROR_GENERIC; + } + /* Allocate page aligned buffer */ + if (size < PAGE_SIZE) { + size = PAGE_SIZE; + } else if (size & (PAGE_SIZE - 1)) { + size = (size & ~(PAGE_SIZE - 1)) + PAGE_SIZE; + } + size = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + + // Get the shared memory ID + if ((shmid = shmget(memKey, size, IPC_CREAT | 0666)) == -1) { + perror("shmget: shmget failed"); + } + // Check if the obtained Shared Memory ID is valid + if (shmid == -1) { + LOGE(TEEC_LIB, "shmget failed"); + OsaFree(pmem_info->mem); + OsaFree(pmem_info); + return TEEC_ERROR_GENERIC; + } + + // attach a buffer with the obtained shared memory ID + shm->buffer = (void*)shmat(shmid, NULL, 0); + // Check if the obtained buffer is valid + if (!shm->buffer) { + LOGE(TEEC_LIB, "shmat failed - allocateSharedMemory failed"); + OsaFree(pmem_info->mem); + OsaFree(pmem_info); + return TEEC_ERROR_GENERIC; + } + + // Clear the buffer + memset(shm->buffer, 0x00, shm->size); + + // Add the mem in the mem list + pmem_info->mem->memKey = memKey; + pthread_rwlock_wrlock(&memkey_list_lock); + LIST_INSERT_HEAD(&memkey_list, pmem_info, mem_list); + pthread_rwlock_unlock(&memkey_list_lock); + + // Update shared memory imp structure + sharedMem_imp->shmKey = memKey; + sharedMem_imp->memId = shmid; + sharedMem_imp->allocPtr = shm->buffer; + return TEEC_SUCCESS; +} + +/* + * === FUNCTION ====================================================================== + * Name: freeSharedMemory + * Description: Local function to free shared memory + * Parameters: shm - TEEC_SharedMemory type of data to free memory + * ===================================================================================== + */ +static void freeSharedMemory(TEEC_SharedMemory *shm) { + LOGD(TEEC_LIB, "Entry"); + MemkeyList *pmem_info; + TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)shm->imp; + + // Detach the buffer atached with the Shared Memory ID + if (shmdt(sharedMem_imp->allocPtr) == -1) { + LOGE(TEEC_LIB, "freeSharedMemory failed"); + } + sharedMem_imp->allocPtr = NULL; + + if ( -1 == shmctl( sharedMem_imp->memId, IPC_RMID, 0)) { + LOGE(TEEC_LIB, "freeSharedMemory shmctl IPC_RMID failed"); + } + sharedMem_imp->memId = -1; + // Remove the memKey from the list + pthread_rwlock_wrlock(&memkey_list_lock); + LIST_FOREACH(pmem_info, &memkey_list, mem_list) + { + if (pmem_info->mem->memKey == sharedMem_imp->shmKey) { + LIST_REMOVE(pmem_info, mem_list); + OsaFree(pmem_info->mem); + OsaFree(pmem_info); + break; + } + } + pthread_rwlock_unlock(&memkey_list_lock); + +} + +/* + * === FUNCTION ====================================================================== + * Name: getMemoryKey + * Description: Local function to generate shmkey for shared memory + * Parameters: shm - TEEC_SharedMemory type of data to allocate memory and update + * ===================================================================================== + */ +static TEEC_Result getMemoryKey(TEEC_SharedMemory *shm) { + TEEC_Result result; + LOGD(TEEC_LIB, "Entry"); + TEEC_SharedMemory sharedmem; + sharedmem.imp = shm->imp; + sharedmem.size = shm->size; + sharedmem.flags = shm->flags; + sharedmem.buffer = NULL; + + // Allocate shared memory and get the shared memory key + result = allocateSharedMemory(&sharedmem); + // Copy the input buffer data to shared buffer + if ((result == TEEC_SUCCESS) && ((shm->flags && TEEC_MEM_INPUT) != 0)) + memcpy(sharedmem.buffer, shm->buffer, shm->size); + + return result; +} + +/* + * === FUNCTION ====================================================================== + * Name: checkContext + * Description: Local function to check if the context is valid + * Parameters: context - TEEC_Context* to check if context exists + * Return: 0 on success + * -1 on failure + * ===================================================================================== + */ +static uint32_t checkContext(TEEC_Context * context) { + LOGD(TEEC_LIB, "Entry"); + + TEEC_ContextList *pContext; + uint32_t found = 0; + + /* Check if the context is in the Context list containing all the alive + * contexts + */ + pthread_rwlock_wrlock(&context_list_lock); + LIST_FOREACH(pContext, &context_list, list) + { + if (pContext->context == context) { + found = 1; + break; + } + } + pthread_rwlock_unlock(&context_list_lock); + return found; +} + +/* + * === FUNCTION ====================================================================== + * Name: preProcessOperation + * Description: Local function to pre-process TEEC_Operation structure passed by CA + * Parameters: session - TEEC_Session* (Session handler) + * operation - TEEC_Operation* (Operation structure pointer) + * op - OperationData* (Structure to be filled and returned) + * tmpSharedMem[4] - TEEC_SharedMemory* (Shared memory in params) + * Return: TEEC_SUCCESS: Success + * Another error code: Failure + * ===================================================================================== + */ +static TEEC_Result preProcessOperation(TEEC_Session *session, + TEEC_Operation *operation, OperationData *op, + TEEC_SharedMemory *tmpSharedMem[4]) { + TEEC_Context *context = NULL; + + LOGD(TEEC_LIB, "Entry"); + TEEC_RegisteredMemoryReference *memref; + TEEC_SharedMemoryImp *memref_imp; + TEEC_Result result = TEEC_SUCCESS; + uint32_t i, type; + + // Check if Session is valid + if (session) + context = ((TEEC_SessionImp*)session->imp)->context; + else return TEEC_ERROR_BAD_PARAMETERS; + // Check if output Operation structure is valid + if (!op) { + return TEEC_ERROR_GENERIC; + } + // Initialize output Operation structure paramtypes to NONE + op->paramTypes = (TEE_PARAM_TYPE_NONE << 24) | (TEE_PARAM_TYPE_NONE << 16) + | (TEE_PARAM_TYPE_NONE << 8) | TEE_PARAM_TYPE_NONE; + + /* Process params in output Operation structure based on input Operation + * structure + */ + for (i = 0; i < 4; i++) { + type = ((operation->paramTypes) >> (8 * i)) & 0x7f; + switch (type) { + case TEEC_NONE: + op->paramTypes |= TEE_PARAM_TYPE_NONE << (8 * i); + break; + case TEEC_VALUE_INPUT: + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + /* + * TEEC_VALUE_* and TEE_PARAM_TYPE_VALUE_* constants have + * equal values according to TEE Internal API and Client API + * specifications, so assign them without modifications. + */ + op->paramTypes |= type << (8 * i); + memcpy(&op->params[i].value, &operation->params[i].value, + sizeof(TEEC_Value)); + break; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + /* + * TEEC_MEMREF_TEMP_* and TEE_PARAM_TYPE_MEMREF_* constants have + * equal values according to TEE Internal API and Client API + * specifications, so assign them without modifications. + */ + op->paramTypes |= type << (8 * i); + if (!tmpSharedMem[i]) { + tmpSharedMem[i] = (TEEC_SharedMemory*)OsaMalloc( + sizeof(TEEC_SharedMemory)); + tmpSharedMem[i]->size = operation->params[i].tmpref.size; + tmpSharedMem[i]->buffer = operation->params[i].tmpref.buffer; + result = TEEC_RegisterSharedMemory( + ((TEEC_SessionImp*)session->imp)->context, tmpSharedMem[i]); + if (result != TEEC_SUCCESS) { + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } + if (type == TEEC_MEMREF_TEMP_INPUT) { + tmpSharedMem[i]->flags = TEEC_MEM_INPUT; + memcpy(((TEEC_SharedMemoryImp*)tmpSharedMem[i]->imp)->allocPtr, + tmpSharedMem[i]->buffer, tmpSharedMem[i]->size); + } else if (type == TEEC_MEMREF_TEMP_OUTPUT) + tmpSharedMem[i]->flags = TEEC_MEM_OUTPUT; + else { + tmpSharedMem[i]->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + memcpy(((TEEC_SharedMemoryImp*)tmpSharedMem[i]->imp)->allocPtr, + tmpSharedMem[i]->buffer, tmpSharedMem[i]->size); + } + } + op->params[i].mem.size = tmpSharedMem[i]->size; + op->params[i].mem.offset = 0; + op->params[i].mem.shmKey = ((TEEC_SharedMemoryImp*)tmpSharedMem[i]->imp) + ->shmKey; + break; + case TEEC_MEMREF_WHOLE: + op->paramTypes |= TEE_PARAM_TYPE_MEMREF_INOUT << (8 * i); + memref = &operation->params[i].memref; + if ((NULL == memref) || (NULL == memref->parent) + || (((TEEC_SharedMemoryImp*)memref->parent->imp)->context->imp + != context->imp)) { + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + LOGE(TEEC_LIB, "Bad parameters"); + return TEEC_ERROR_BAD_PARAMETERS; + } + memref_imp = (TEEC_SharedMemoryImp*)memref->parent->imp; + op->params[i].mem.offset = 0; + op->params[i].mem.size = memref->parent->size; + op->params[i].mem.shmKey = memref_imp->shmKey; + if (memref->parent->buffer != memref_imp->allocPtr) { + memcpy(memref_imp->allocPtr, memref->parent->buffer, memref->size); + } + break; + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + op->paramTypes |= (type + TEE_PARAM_TYPE_MEMREF_INPUT + - TEEC_MEMREF_PARTIAL_INPUT) << (8 * i); + memref = &operation->params[i].memref; + if ((NULL == memref) || (NULL == memref->parent) + || (((TEEC_SharedMemoryImp*)memref->parent->imp)->context->imp + != context->imp)) { + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + LOGE(TEEC_LIB, "Bad parameters"); + return TEEC_ERROR_BAD_PARAMETERS; + } + memref_imp = (TEEC_SharedMemoryImp*)memref->parent->imp; + op->params[i].mem.size = memref->size; + op->params[i].mem.offset = memref->offset; + op->params[i].mem.shmKey = memref_imp->shmKey; + + if (memref->parent->buffer != memref_imp->allocPtr) { + if ((type == TEEC_MEMREF_PARTIAL_INPUT) + || (type == TEEC_MEMREF_PARTIAL_INOUT)) + memcpy((uint8_t*)(memref_imp->allocPtr) + memref->offset, + (uint8_t*)(memref->parent->buffer) + memref->offset, + memref->size); + } + break; + default: + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return TEEC_ERROR_BAD_PARAMETERS; + } + } + return TEEC_SUCCESS; +} + +/* + * === FUNCTION ====================================================================== + * Name: postProcessOperation + * Description: Local function to post-process the TEEC_Operation structure + * returned by Simulator Daemon + * Parameters: operation - TEEC_Operation* (Operation structure pointer) + * op - OperationData* (Structure to read) + * tmpSharedMem[4] - TEEC_SharedMemory* (Shared memory in params) + * ===================================================================================== + */ +static void postProcessOperation(TEEC_Operation *operation, OperationData *op, + TEEC_SharedMemory *tmpSharedMem[4]) { + LOGD(TEEC_LIB, "Entry"); + uint32_t i, type; + TEEC_RegisteredMemoryReference *memref; + TEEC_SharedMemoryImp *memref_imp; + + /* Process params in output Operation structure based on input Operation + * structure + */ + for (i = 0; i < 4; i++) { + type = ((operation->paramTypes) >> (8 * i)) & 0x7f; + switch (type) { + case TEEC_VALUE_INPUT: + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + memcpy(&operation->params[i].value, &op->params[i].value, + sizeof(TEEC_Value)); + break; + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + operation->params[i].tmpref.size = op->params[i].mem.size; + memcpy(operation->params[i].tmpref.buffer, + ((TEEC_SharedMemoryImp*)tmpSharedMem[i]->imp)->allocPtr, + operation->params[i].tmpref.size); + break; + case TEEC_MEMREF_WHOLE: + memref = &operation->params[i].memref; + memref->parent->size = op->params[i].mem.size; + memref_imp = (TEEC_SharedMemoryImp*)memref->parent->imp; + + if (memref->parent->buffer != memref_imp->allocPtr) { + memcpy((uint8_t*)(memref->parent->buffer) + memref->offset, + (uint8_t*)(memref_imp->allocPtr) + memref->offset, memref->size); + } + break; + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + memref = &operation->params[i].memref; + memref_imp = (TEEC_SharedMemoryImp*)memref->parent->imp; + memref->size = op->params[i].mem.size; + if (memref->parent->buffer != memref_imp->allocPtr) { + memcpy((uint8_t*)(memref->parent->buffer) + memref->offset, + (uint8_t*)(memref_imp->allocPtr) + memref->offset, memref->size); + } + break; + } + } +} + +/*----------------------------------------------------------------------------- + * TEEC API implementation + *-----------------------------------------------------------------------------*/ +/* + * === FUNCTION ====================================================================== + * Name: TEEC_InitializeContext + * Description: API implementation for initializing a context with TEE + * Parameters: name - a zero-terminated string that describes the TEE to connect to. + * If this parameter is set to NULL the Implementation MUST + * select a default TEE. + * context - a TEEC_Context structure that MUST be initialized by the + * Implementation. + * Return: TEEC_SUCCESS: the initialization was successful. + * Another error code: initialization was not successful. + * ===================================================================================== + */ + +TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context) { + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + TEEC_ContextImp* context_imp = NULL; + TEEC_ContextList* pContext = NULL; + InitContextData ctx; + + // Check if the context is valid + if (!context) { + LOGE(TEEC_LIB, "NULL Context"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Initialize Context imp structure + context->imp = (TEEC_ContextImp*)OsaMalloc(sizeof(TEEC_ContextImp)); + context_imp = (TEEC_ContextImp*)context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "context_imp malloc failed"); + return TEEC_ERROR_OUT_OF_MEMORY; + } + memset(context_imp, 0x00, sizeof(TEEC_ContextImp)); + + // Initialize InitContextData structure to be sent to Simulator Daemon + memset(&ctx, 0x00, sizeof(InitContextData)); + + /* check if the Context name is NULL. If it is NULL then set the namelength + * to zero else update it accordingly, also update TEEName accordingly + */ + ctx.nameLength = (name == NULL) ? 0 : strlen(name) + 1; + if (ctx.nameLength > MAX_CONTEXT_NAME_LEN) { + OsaFree(context_imp); + context->imp = NULL; + LOGE(TEEC_LIB, "TEE name length exceeding"); + return TEEC_ERROR_BAD_PARAMETERS; + } + if (name) strncpy(ctx.TEEName, name, ctx.nameLength); + + // Connect to Simulator Daemon as a client + context_imp->sockfd = connecttoServer(); + if (context_imp->sockfd == -1) { + OsaFree(context_imp); + context->imp = NULL; + LOGE(TEEC_LIB, "Unable to connect to Simulator daemon"); + return TEEC_ERROR_GENERIC; + } + ctx.returnValue = TEEC_SUCCESS; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, INITIALIZE_CONTEXT, &ctx, + sizeof(InitContextData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + // Disconnect from Simulator Daemon + disconnectfromServer(context_imp->sockfd); + + OsaFree(context_imp); + context->imp = NULL; + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + return result; + } + + if (ctx.returnValue != TEEC_SUCCESS) { // Command Failure + // Disconnect from Simulator Daemon + disconnectfromServer(context_imp->sockfd); + + OsaFree(context_imp); + context->imp = NULL; + LOGE(TEEC_LIB, "Simulator Daemon Initialize context returned failure"); + return ctx.returnValue; + } + + // Update the Context ID in context imp structure + context_imp->contextID = ctx.contextID; + + // Add the context in the Context list + pContext = (TEEC_ContextList*)OsaMalloc(sizeof(TEEC_ContextList)); + if (!pContext) { + LOGE(TEEC_LIB, "pContext malloc failed"); + return TEEC_ERROR_OUT_OF_MEMORY; + } + pContext->context = context; + pthread_rwlock_wrlock(&context_list_lock); + LIST_INSERT_HEAD(&context_list, pContext, list); + pthread_rwlock_unlock(&context_list_lock); + + return result; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_FinalizeContext + * Description: API implementation for finalizing a context with TEE + * Parameters: context - an initialized TEEC_Context structure which is to be + * finalized. + * ===================================================================================== + */ +void TEEC_FinalizeContext(TEEC_Context *context) { + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + FinalizeContextData ctx; + TEEC_ContextList *pContext; + uint32_t context_initialized = 0; + + // Check if the Context is valid + if (!context) { + LOGE(TEEC_LIB, "NULL context"); + return; + } + // Remove the Context from the list + pthread_rwlock_wrlock(&context_list_lock); + LIST_FOREACH(pContext, &context_list, list) + { + if (pContext->context == context) { + context_initialized = 1; + LIST_REMOVE(pContext, list); + OsaFree(pContext); + break; + } + } + pthread_rwlock_unlock(&context_list_lock); + + if (!context_initialized) { + LOGE(TEEC_LIB, "Invalid Context"); + return; + } + // Check if the Context imp structure is valid + TEEC_ContextImp* context_imp = (TEEC_ContextImp*)context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "NULL context_imp"); + return; + } + + // Initialize FinalizeContextData structure to be sent to Simulator Daemon + memset(&ctx, 0x00, sizeof(FinalizeContextData)); + ctx.contextID = context_imp->contextID; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, FINALIZE_CONTEXT, &ctx, + sizeof(FinalizeContextData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + + // Disconnect from Simulator Daemon + disconnectfromServer(context_imp->sockfd); + // Release Context imp + OsaFree(context_imp); + context->imp = NULL; + return; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_RegisterSharedMemory + * Description: API implementation for registering shared memory with TEE + * Parameters: context - a pointer to an initialized TEE Context + * sharedMem - a pointer to a Shared Memory structure to register: + * the buffer, size, and flags fields of the sharedMem + * structure MUST be set in accordance with the + * specification + * Return: TEEC_SUCCESS: the registration was successful. + * TEEC_ERROR_OUT_OF_MEMORY: the registration could not be completed + * because of a lack of resources. + * Another error code: registration was not successful for another reason + * ===================================================================================== + */ +TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, + TEEC_SharedMemory *sharedMem) { + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + RegSharedMemData regmem; + + // Check if the Context is valid + if (!context) { + LOGE(TEEC_LIB, "NULL context"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the context is initialized + if (!checkContext(context)) { + LOGE(TEEC_LIB, "Invalid context"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the Context imp structure is valid + TEEC_ContextImp* context_imp = (TEEC_ContextImp*)context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "NULL context_imp"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the socket is valid + if (context_imp->sockfd < 0) { + LOGE(TEEC_LIB, "Bad parameter context_imp->sockfd = %d", + context_imp->sockfd); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if shared memory pointer is valid + if (!sharedMem) { + LOGE(TEEC_LIB, "Shared Memory is NULL"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + /* + * Restrict registration of shared memory regions more than + * TEEC_CONFIG_SHAREDMEM_MAX_SIZE and less than PAGE_SIZE. + */ + if (sharedMem->size > TEEC_CONFIG_SHAREDMEM_MAX_SIZE) { + LOGE(TEEC_LIB, "Shared Memory size is too large 0x%x", sharedMem->size); + return TEEC_ERROR_BAD_PARAMETERS; + } + + // Check if the Shared Memory Buffer is valid + if (!sharedMem->buffer) { + LOGE(TEEC_LIB, "Shared Memory buffer is NULL"); + return TEEC_ERROR_NO_DATA; + } + // Check if the Shared memory flags are valid + if ((sharedMem->flags == 0) + || (sharedMem->flags > (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) { + LOGE(TEEC_LIB, "Shared Memory flag is a bad parameter"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + // Initialize RegSharedMemData structure to sent to Simulator Daemon + memset(®mem, 0x00, sizeof(RegSharedMemData)); + + sharedMem->imp = (TEEC_SharedMemoryImp*)OsaMalloc( + sizeof(TEEC_SharedMemoryImp)); + TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)sharedMem->imp; + sharedMem_imp->context = context; + regmem.contextID = context_imp->contextID; + regmem.sharedMem.size = sharedMem->size; + regmem.sharedMem.flags = sharedMem->flags; + regmem.returnValue = TEEC_SUCCESS; + + // Generate shared memory key to be shared with TEEStub + result = getMemoryKey(sharedMem); + if (result != TEEC_SUCCESS) { // Memory allocation Failure + LOGE(TEEC_LIB, "Memory alocation failed"); + OsaFree(sharedMem_imp); + return result; + } + // Check if the obained shared memory is valid + if (sharedMem_imp->shmKey == -1) { + LOGE(TEEC_LIB, "Failed to get MemoryID"); + OsaFree(sharedMem_imp); + return TEEC_ERROR_GENERIC; + } + regmem.sharedMem.shmKey = sharedMem_imp->shmKey; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, REGISTER_SHARED_MEMORY, ®mem, + sizeof(RegSharedMemData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + OsaFree(sharedMem_imp); + return result; + } + result = regmem.returnValue; + if (result != TEEC_SUCCESS) { // Command Failure + LOGE(TEEC_LIB, "Simulator Daemon Register Shared Memory returned failure"); + OsaFree(sharedMem_imp); + return result; + } + return result; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_AllocateSharedMemory + * Description: API implementation for requesting TEE to allocate shared memory + * Parameters: context - a pointer to an initialized TEE Context + * sharedMem - a pointer to a Shared Memory structure to allocate: + * Before calling this function, the Client Application MUST have set + * the size, and flags fields. On return, for a successful allocation + * the Implementation MUST have set the pointer buffer to the address + * of the allocated block, otherwise it MUST set buffer to NULL. + * Return: TEEC_SUCCESS: the registration was successful. + * TEEC_ERROR_OUT_OF_MEMORY: the registration could not be completed + * because of a lack of resources. + * Another error code: registration was not successful for another + * reason + * ===================================================================================== + */ +TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, + TEEC_SharedMemory *sharedMem) { + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + TEEC_ContextImp* context_imp; + RegSharedMemData regmem; + + // Check if the Context is valid + if (!context) { + LOGE(TEEC_LIB, "context is NULL"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the Context is initialized + if (!checkContext(context)) { + LOGE(TEEC_LIB, "context is not found"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the Context imp structure is valid + context_imp = (TEEC_ContextImp*)context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "context_imp is not found"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the socket is valid + if (context_imp->sockfd < 0) { + LOGE(TEEC_LIB, "Bad parameter context_imp->sockfd = %d", + context_imp->sockfd); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if shared memory pointer is valid + if (!sharedMem) { + LOGE(TEEC_LIB, "Shared Memory is NULL"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + /* + * Restrict registration of shared memory regions more than + * TEEC_CONFIG_SHAREDMEM_MAX_SIZE and less than PAGE_SIZE. + */ + if (sharedMem->size > TEEC_CONFIG_SHAREDMEM_MAX_SIZE) { + LOGE(TEEC_LIB, "Shared Memory size is too large 0x%x", sharedMem->size); + return TEEC_ERROR_BAD_PARAMETERS; + } + + // Check if the Shared memory flags are valid + if ((sharedMem->flags == 0) + || (sharedMem->flags > (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) { + LOGE(TEEC_LIB, "Shared Memory flag is a bad parameter"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Generate Shared Memory imp structure + sharedMem->imp = (TEEC_SharedMemoryImp*)OsaMalloc( + sizeof(TEEC_SharedMemoryImp)); + TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)sharedMem->imp; + sharedMem->buffer = NULL; + sharedMem_imp->context = context; + + /* Allocate shared memory and get the Shared Memory key to be shared with + * TEEStub + */ + result = allocateSharedMemory(sharedMem); + if (result != TEEC_SUCCESS) { // Memory Allocation Failure + LOGE(TEEC_LIB, "allocateSharedMemory failed"); + OsaFree(sharedMem_imp); + return result; + } + // Check if the obtained key is valid + if (sharedMem_imp->shmKey == -1) { + LOGE(TEEC_LIB, "allocateSharedMemory failed"); + OsaFree(sharedMem_imp); + return TEEC_ERROR_GENERIC; + } + + // Initialize RegSharedMemData to be sent to Simulator Daemon + memset(®mem, 0x00, sizeof(RegSharedMemData)); + + regmem.contextID = context_imp->contextID; + regmem.returnValue = TEEC_SUCCESS; + regmem.sharedMem.size = sharedMem->size; + regmem.sharedMem.flags = sharedMem->flags; + regmem.sharedMem.shmKey = sharedMem_imp->shmKey; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, REGISTER_SHARED_MEMORY, ®mem, + sizeof(RegSharedMemData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + sharedMem->buffer = NULL; + OsaFree(sharedMem_imp); + return result; + } + result = regmem.returnValue; + if (result != TEEC_SUCCESS) { // Command Failure + LOGE(TEEC_LIB, "Simulator Daemon Allocate Shared Memory returned failure"); + OsaFree(sharedMem_imp); + return result; + } + return result; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_ReleaseSharedMemory + * Description: API implementation for releasing shared memory + * Parameters: sharedMem - a pointer to a valid Shared Memory structure + * ===================================================================================== + */ +void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem) { + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + TEEC_Context* context; + TEEC_ContextImp* context_imp; + RelSharedMemData relmem; + + // Check if the Shared Memory is valid + if (!sharedMem) { + LOGE(TEEC_LIB, "SharedMem is NULL"); + return; + } + // Check if the Shared Memory imp structure is valid + TEEC_SharedMemoryImp* sharedMem_imp = (TEEC_SharedMemoryImp*)sharedMem->imp; + if (!sharedMem_imp) { + LOGE(TEEC_LIB, "NULL sharedMem_imp"); + return; + } + // Check if the Context is valid + context = sharedMem_imp->context; + if (!context) { + LOGE(TEEC_LIB, "context is NULL"); + return; + } + // Check if the Context imp structure is valid + context_imp = (TEEC_ContextImp*)context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "context_imp is NULL"); + return; + } + + // Initialize RelSharedMemData structure to be sent to Simulator Daemon + memset(&relmem, 0x00, sizeof(RelSharedMemData)); + + relmem.contextID = context_imp->contextID; + relmem.sharedMem.size = sharedMem->size; + relmem.sharedMem.flags = sharedMem->flags; + relmem.sharedMem.shmKey = sharedMem_imp->shmKey; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, RELEASE_SHARED_MEMORY, &relmem, + sizeof(RelSharedMemData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + return; + } + // free Shared Memory + freeSharedMemory(sharedMem); + OsaFree(sharedMem_imp); + sharedMem->imp = NULL; + return; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_OpenSession + * Description: API implementation for opening a session with TA + * Parameters: context - a pointer to an initialized TEE Context + * session - a pointer to a Session structure to open + * destination - a pointer to a structure containing the UUID of the + * destination Trusted Application + * connectionMethod - the method of connection to use + * connectionData - any necessary data required to support the + * connection method chosen + * operation - a pointer to an Operation containing a set of Parameters + * to exchange with the Trusted Application, or NULL if no + * Parameters are to be exchanged or if the operation cannot + * be cancelled + * returnOrigin - a pointer to a variable which will contain the return + * origin. This field may be NULL if the return origin is not needed + * Return: If the returnOrigin is different from TEEC_ORIGIN_TRUSTED_APP, + * an error code + * 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. In any case, a return code set to + * TEEC_SUCCESS means that the session was successfully opened and a + * return code different from TEEC_SUCCESS means that the session + * opening failed + * ===================================================================================== + */ +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) { + + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + OpenSessionData os; + OperationData op; + TEEC_SharedMemory *tmpSharedMem[4]; + memset(tmpSharedMem, 0x0, sizeof(TEEC_SharedMemory *) * 4); + uint32_t i; + + // Check if the context, session and UUID is valid + if (!session || !context || !destination) { + LOGE(TEEC_LIB, "Invalid input parameters"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if the context imp is valid + TEEC_ContextImp* context_imp = (TEEC_ContextImp*)context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "NULL context_imp"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + /* Initialize the OpenSessionData and OperationData structures to be sent to + * Simulator daemon + */ + memset(&os, 0x00, sizeof(OpenSessionData)); + memset(&op, 0x00, sizeof(OperationData)); + + // Set returnOrigin + if (returnOrigin) { + *returnOrigin = TEEC_ORIGIN_API; + os.returnOrigin = *returnOrigin; + } else os.returnOrigin = 0x00; + + // Update Context ID + os.contextID = context_imp->contextID; + // Update Connection details + switch (connectionMethod) { + case TEEC_LOGIN_PUBLIC: + case TEEC_LOGIN_USER: + case TEEC_LOGIN_APPLICATION: + case TEEC_LOGIN_USER_APPLICATION: + if (connectionData != NULL) { + return TEEC_ERROR_BAD_PARAMETERS; + } + break; + case TEEC_LOGIN_GROUP: + case TEEC_LOGIN_GROUP_APPLICATION: + if (connectionData == NULL) { + return TEEC_ERROR_BAD_PARAMETERS; + } + os.connData = *(uint32_t*)connectionData; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + + os.connMeth = connectionMethod; + + session->imp = (TEEC_SessionImp*)OsaMalloc(sizeof(TEEC_SessionImp)); + TEEC_SessionImp* session_imp = (TEEC_SessionImp*)session->imp; + if (!session_imp) { + LOGE(TEEC_LIB, "NULL session_imp"); + return TEEC_ERROR_OUT_OF_MEMORY; + } + session_imp->context = context; + memcpy(&os.uuid, destination, sizeof(TEEC_UUID)); + + if (operation) { + result = preProcessOperation(session, operation, &op, tmpSharedMem); + if (result != TEEC_SUCCESS) { + LOGE(TEEC_LIB, "preProcessOperation failed"); + OsaFree(session_imp); + session->imp = NULL; + if (operation) postProcessOperation(operation, &op, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } + memcpy(&os.operation, &op, sizeof(OperationData)); + } else memset(&os.operation, 0x00, sizeof(OperationData)); + + os.returnValue = TEEC_SUCCESS; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, OPEN_SESSION, &os, + sizeof(OpenSessionData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + if (returnOrigin) *returnOrigin = TEEC_ORIGIN_COMMS; + OsaFree(session_imp); + session->imp = NULL; + if (operation) postProcessOperation(operation, &os.operation, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } + + if (returnOrigin) *returnOrigin = os.returnOrigin; + + result = os.returnValue; + if (result != TEEC_SUCCESS) { // Command Failure + LOGE(TEEC_LIB, "Simulator Daemon Open Session returned failure"); + OsaFree(session_imp); + session->imp = NULL; + if (operation) postProcessOperation(operation, &os.operation, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } else session_imp->sessionID = os.sessionID; + + if (operation) postProcessOperation(operation, &os.operation, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_CloseSession + * Description: API implementation for closing a session with TA + * Parameters: session - the session to close. + * ===================================================================================== + */ +void TEEC_CloseSession(TEEC_Session *session) { + + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + CloseSessionData cs; + + // Check if Session is valid + if (!session) { + LOGE(TEEC_LIB, "NULL session"); + return; + } + // Check if Session imp is valid + TEEC_SessionImp* session_imp = (TEEC_SessionImp*)session->imp; + if (!session_imp) { + LOGE(TEEC_LIB, "NULL session_imp"); + return; + } + // Check if Context imp is valid + TEEC_ContextImp* context_imp = (TEEC_ContextImp*)session_imp->context->imp; + if (!context_imp || context_imp->sockfd < 0) { + LOGE(TEEC_LIB, "Bad parameters"); + return; + } + + // Initialize CloseSessionData structure to be sent to Simulator Daemon + memset(&cs, 0x00, sizeof(CloseSessionData)); + + cs.contextID = context_imp->contextID; + cs.sessionID = session_imp->sessionID; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, CLOSE_SESSION, &cs, + sizeof(CloseSessionData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + return; + } + // Release Session + session->imp = NULL; + OsaFree(session_imp); + return; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_InvokeCommand + * Description: API implementation for invoking a command in a session with TA + * Parameters: session - the open Session in which the command will be invoked + * commandID - the identifier of the Command within the Trusted + * Application to invoke. The meaning of each Command + * Identifier must be defined in the protocol exposed + * by the Trusted Application + * operation - a pointer to a Client Application initialized + * TEEC_Operation structure, or NULL if there is no payload + * to send or if the Command does not need to support cancellation + * returnOrigin - a pointer to a variable which will contain the return + * origin. This field may be NULL if the return origin + * is not needed + * Return: If the return origin is different from TEEC_ORIGIN_TRUSTED_APP, + * an error code + * If the return origin is TEEC_ORIGIN_TRUSTED_APP, a return code + * defined by the Trusted Application protocol + * ===================================================================================== + */ +TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t commandID, + TEEC_Operation *operation, uint32_t *returnOrigin) { + + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + + InvokeCommandData ic; + OperationData op; + TEEC_SharedMemory *tmpSharedMem[4]; + memset(tmpSharedMem, 0x0, sizeof(TEEC_SharedMemory*) * 4); + uint32_t i; + + // Check if Session is valid + if (!session) { + LOGE(TEEC_LIB, "NULL session"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + // Check if Session imp is valid + TEEC_SessionImp* session_imp = (TEEC_SessionImp*)session->imp; + if (!session_imp) { + LOGE(TEEC_LIB, "NULL session_imp"); + return TEEC_ERROR_BAD_PARAMETERS; + } + // Check if Context imp is valid + TEEC_ContextImp *context_imp = (TEEC_ContextImp*)session_imp->context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "NULL context_imp"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + /* Initialize InvokeCommandData and OperationData structures to be sent to + * Simulator Daemon + */ + memset(&ic, 0x00, sizeof(InvokeCommandData)); + memset(&op, 0x00, sizeof(OperationData)); + + // Set returnOrigin + if (returnOrigin) { + *returnOrigin = TEEC_ORIGIN_API; + ic.returnOrigin = *returnOrigin; + } else ic.returnOrigin = 0x00; + + if (operation) { + result = preProcessOperation(session, operation, &op, tmpSharedMem); + if (result != TEEC_SUCCESS) { + LOGE(TEEC_LIB, "preProcessOperation failed"); + if (operation) postProcessOperation(operation, &op, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } + memcpy(&ic.operation, &op, sizeof(OperationData)); + } else memset(&ic.operation, 0x00, sizeof(OperationData)); + + ic.contextID = context_imp->contextID; + ic.sessionID = session_imp->sessionID; + ic.commandID = commandID; + ic.returnValue = TEEC_SUCCESS; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, INVOKE_COMMAND, &ic, + sizeof(InvokeCommandData)); + pthread_mutex_unlock(&context_imp->lock); + + if (result != TEEC_SUCCESS) { // Communication Failure + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + if (returnOrigin) *returnOrigin = TEEC_ORIGIN_COMMS; + if (operation) postProcessOperation(operation, &ic.operation, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } + + if (returnOrigin) *returnOrigin = ic.returnOrigin; + + result = ic.returnValue; + if (result != TEEC_SUCCESS) { // Command Failure + if (operation) postProcessOperation(operation, &ic.operation, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; + } + + if (operation) postProcessOperation(operation, &ic.operation, tmpSharedMem); + /* temp memref cleanup & release */ + for (i = 0; i < 4; i++) { + if (tmpSharedMem[i]) { + TEEC_ReleaseSharedMemory(tmpSharedMem[i]); + OsaFree(tmpSharedMem[i]); + tmpSharedMem[i] = NULL; + } + } + return result; +} + +/* + * === FUNCTION ====================================================================== + * Name: TEEC_RequestCancellation + * Description: API implementation for requesting cancellation of an operation + * Parameters: operation - a pointer to a Client Application instantiated Operation + * structure. + * ===================================================================================== + */ +void TEEC_RequestCancellation(TEEC_Operation *operation) { + + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + + ReqCancellationData rc; + + // Check if cancellation is allowed + if (operation->started != 0) { + LOGE(TEEC_LIB, "Cancellation not allowed"); + return; + } + // Check if Operation imp is valid + TEEC_OperationImp* operation_imp = (TEEC_OperationImp*)operation->imp; + if (!operation_imp) { + LOGE(TEEC_LIB, "NULL operation_imp"); + return; + } + // Check if session is valid + if (!operation_imp->session) { + LOGE(TEEC_LIB, "NULL session"); + return; + } + // check if Session imp is valid + TEEC_SessionImp* session_imp = (TEEC_SessionImp*)operation_imp->session->imp; + if (!session_imp) { + LOGE(TEEC_LIB, "NULL session_imp"); + return; + } + // Check if Context imp is valid + TEEC_ContextImp *context_imp = (TEEC_ContextImp*)session_imp->context->imp; + if (!context_imp) { + LOGE(TEEC_LIB, "NULL context_imp"); + return; + } + + // Initialize ReqCancellationData structure to be sent to Simulator Daemon + memset(&rc, 0x00, sizeof(ReqCancellationData)); + + rc.contextID = context_imp->contextID; + rc.sessionID = session_imp->sessionID; + rc.operationID = operation_imp->OperationID; + + // Send the command and data to Simulator Daemon through the socket + pthread_mutex_lock(&context_imp->lock); + result = sendCommand(context_imp->sockfd, REQUEST_CANCELLATION, &rc, + sizeof(ReqCancellationData)); + pthread_mutex_unlock(&context_imp->lock); + if (result != TEEC_SUCCESS) { + LOGE(TEEC_LIB, "sendCommand to Simulator Daemon failed"); + } + return; +} diff --git a/TEECLib/src/teec_connection.c b/TEECLib/src/teec_connection.c new file mode 100755 index 0000000..34c0968 --- /dev/null +++ b/TEECLib/src/teec_connection.c @@ -0,0 +1,434 @@ +/* + * ===================================================================================== + * + * Filename: teec_connection.c + * + * Description: TEEC Library connection with Simulator Daemon is handled here + * + * Version: 1.0 + * Created: 26 March 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "teec_connection.h" + +/*----------------------------------------------------------------------------- + * Macros + *-----------------------------------------------------------------------------*/ +#define SOCKPATH "/tmp/simdaemon" + +/*----------------------------------------------------------------------------- + * TEST MACROS + *-----------------------------------------------------------------------------*/ +//#define TEST + +/* + * === FUNCTION ====================================================================== + * Name: connecttoServer + * Description: API (Interface for TEECAPI) implementation for connecting to + * the Simulator Daemon through socket + * Return: Socket fd on success + * -1 on failure + * ===================================================================================== + */ +int32_t connecttoServer(void) { + LOGD(TEEC_LIB, "Entry"); + int32_t serverSocket, socklen; + size_t sock_path_len = 0; + struct sockaddr* sockptr; + struct sockaddr_un daemonsock; + + // Get socket decriptor + if ((serverSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + LOGE(TEEC_LIB, "No socket for simdaemon"); + return -1; + } + daemonsock.sun_family = AF_UNIX; + + sock_path_len = strlen(SOCKPATH); + strncpy(daemonsock.sun_path, SOCKPATH, sock_path_len+1); + + socklen = sizeof(daemonsock); + sockptr = (struct sockaddr*)&daemonsock; + + // Connect to Simulator Daemon + if (connect(serverSocket, sockptr, socklen) == -1) { + LOGE(TEEC_LIB, "connection to simdaemon failed"); + close(serverSocket); + return -1; + } + return serverSocket; +} + +/* + * === FUNCTION ====================================================================== + * Name: disconnectfromServer + * Description: API (Interface for TEECAPI) implementation for disconnecting + * from the Simulator daemon through socket + * Parameters: serverSocket - Socket fd + * ===================================================================================== + */ +void disconnectfromServer(int32_t serverSocket) { + int32_t result; + LOGD(TEEC_LIB, "Entry"); + + if (serverSocket > 0) { + // shutdown the socket + result = shutdown(serverSocket, SHUT_WR); + if (result != 0) + LOGE(TEEC_LIB, "disconnectfromServer failed"); + + // close the socket + close(serverSocket); + } else { + LOGE(TEEC_LIB, "Invalid socket, disconnectfromServer failed"); + } +} + +/* + * === FUNCTION ====================================================================== + * Name: sendCommandtoDaemon + * Description: Function implementation for sending data to Simulator daemon + * through socket + * Parameters: serverSocket - Socket fd + * fdata - data to be sent to Simulator Daemon + * size - Size of data to be sent + * Return: 0 on success + * errno on failure + * ===================================================================================== + */ +static uint32_t sendCommandtoDaemon(int32_t sockfd, char* fdata, size_t size) { + LOGD(TEEC_LIB, "Entry"); + ssize_t nwrite = 0; + size_t nbytes = 0; + + if (sockfd > 0) { + // send size number of bytes to Simulator Daemon + do { + nwrite = send(sockfd, fdata + nbytes, size - nbytes, 0); + } while ((nwrite == -1 && errno == EINTR) || (nwrite > 0 && ((nbytes += + nwrite) < size))); + return (size != nbytes) ? errno : 0; + } + LOGE(TEEC_LIB, "failed"); + return TEEC_ERROR_COMMUNICATION; +} + +/* + * === FUNCTION ====================================================================== + * Name: receiveResponse + * Description: Function implementation for recieving data from Simulator + * daemon through socket + * Parameters: serverSocket - Socket fd + * fdata - data received from Simulator Daemon + * size - Size of received data + * Return: 0 on success + * errno on failure + * ===================================================================================== + */ +static uint32_t receiveResponse(int32_t sockfd, char* fdata, size_t size) { + LOGD(TEEC_LIB, "Entry"); + ssize_t nread = 0; + size_t nbytes = 0; + + if (sockfd > 0) { + // receive size number of bytes to Simulator Daemon + do { + nread = recv(sockfd, fdata + nbytes, size - nbytes, 0); + } while ((nread == -1 && errno == EINTR) + || (nread > 0 && ((nbytes += nread) < size))); + + return (size != nbytes) ? errno : 0; + } + LOGE(TEEC_LIB, "failed"); + return TEEC_ERROR_COMMUNICATION; +} + +#ifdef TEST +/* + * === FUNCTION ====================================================================== + * Name: Test + * Description: Local function for Unit testing of TEECLib module + * Parameters: cmd - Command sent/received + * fdata - data sent/received + * size - size of data sent/received + * in - 1: Sent data + * Any other value: Received data + * Return: TEEC_SUCCESS: Success + * TEEC_ERROR_GENERIC: Failure + * ===================================================================================== + */ +static uint32_t Test(char cmd, char* fdata, size_t size, uint32_t in) { + + LOGD(TEEC_LIB, "Entry"); + FILE *f1; + char *fname; + uint32_t type, i, j, shmid, key; + char *buffer; + + switch (cmd) { + case INITIALIZE_CONTEXT: + if (in == 1) + fname = "InitContext.txt"; + else + fname = "InitContextResult.txt"; + f1 = fopen(fname, "w+"); + InitContextData initdata = *(InitContextData*) fdata; + fprintf(f1, + "InitializeContextData ---------\ncontextID %d\nnameLength %d\ + \nTEEName %s\nreturnValue %d\n", + initdata.contextID, initdata.nameLength, &initdata.TEEName[0], + initdata.returnValue); + fclose(f1); + break; + case FINALIZE_CONTEXT: + if (in == 1) + fname = "FinContext.txt"; + else + fname = "FinContextResult.txt"; + f1 = fopen(fname, "w+"); + FinalizeContextData findata = *(FinalizeContextData*) fdata; + fprintf(f1, "FinalizeContextData ---------\ncontextID %d\n", + findata.contextID); + fclose(f1); + break; + case REGISTER_SHARED_MEMORY: + if (in == 1) + fname = "RegMem.txt"; + else + fname = "RegMemResult.txt"; + f1 = fopen(fname, "w+"); + RegSharedMemData regdata = *(RegSharedMemData*) fdata; + fprintf(f1, + "RegSharedMemData ---------\ncontextID %d\nsize %d\nflags %d\ + \nshmKey %d\nreturnValue %d\n", + regdata.contextID, regdata.sharedMem.size, regdata.sharedMem.flags, + regdata.sharedMem.shmKey, regdata.returnValue); + fclose(f1); + break; + case RELEASE_SHARED_MEMORY: + if (in == 1) + fname = "RelMem.txt"; + else + fname = "RelMemResult.txt"; + f1 = fopen(fname, "w+"); + RelSharedMemData reldata = *(RelSharedMemData*) fdata; + fprintf(f1, + "RelSharedMemData ---------\ncontextID %d\nsize %d\nflags %d\ + \nshmKey %d\n", + reldata.contextID, reldata.sharedMem.size, reldata.sharedMem.flags, + reldata.sharedMem.shmKey); + break; + case OPEN_SESSION: + if (in == 1) + fname = "OpenSess.txt"; + else + fname = "OpenSessResult.txt"; + f1 = fopen(fname, "w+"); + OpenSessionData osdata = *(OpenSessionData*) fdata; + fprintf(f1, + "OpensessionData ---------\ncontextID %d\nSessionID %d\ + \nuuidtimeLow %d\nuuidtimeMid %d\ntimeHiAndVersion %d\n", + osdata.contextID, osdata.sessionID, osdata.uuid.timeLow, + osdata.uuid.timeMid, osdata.uuid.timeHiAndVersion); + for (i = 0; i < 8; i++) + fprintf(f1, "clockSeqAndNode[%d] %d\n", i, + osdata.uuid.clockSeqAndNode[i]); + fprintf(f1, "connMethod %d\nconnData %d\nparamTypes %d\n", osdata.connMeth, + osdata.connData, osdata.operation.paramTypes); + for (i = 0; i < 4; i++) { + type = ((osdata.operation.paramTypes) >> (8 * i)) & 0x7f; + if (type == TEEC_NONE) + fprintf(f1, "param[%d] NONE\n", i); + else if ((type + == TEEC_VALUE_INPUT) | (type == TEEC_VALUE_OUTPUT) | (type == TEEC_VALUE_INOUT)) + fprintf(f1, "param[%d] value a %d value b %d\n", i, + osdata.operation.params[i].value.a, + osdata.operation.params[i].value.b); + else { + fprintf(f1, "param[%d] mem shmKey %d size %d offset %d\n", i, + osdata.operation.params[i].mem.shmKey, + osdata.operation.params[i].mem.size, + osdata.operation.params[i].mem.offset); + key = osdata.operation.params[i].mem.shmKey; + shmid = shmget(key, osdata.operation.params[i].mem.size, + IPC_CREAT | 0666); + if (shmid == -1) { + LOGE(TEEC_LIB, "shmget failed"); + return TEEC_ERROR_GENERIC; + } + + if ((buffer = (char*) shmat(shmid, NULL, 0)) == (char*) -1) { + LOGE(TEEC_LIB, "shmat failed"); + return TEEC_ERROR_GENERIC; + } + + if (!buffer) { + LOGE(TEEC_LIB, "shmat failed"); + return TEEC_ERROR_GENERIC; + } + + fprintf(f1, "SharedMemData: \n"); + char *shmdata = (buffer + osdata.operation.params[i].mem.offset); + for (j = 0; j < osdata.operation.params[i].mem.size; j++) + fprintf(f1, "%x", shmdata[j]); + fprintf(f1, "\n"); + + if (shmdt(buffer) == -1) { + printf("shmdt failed"); + } + buffer = NULL; + } + } + fprintf(f1, "OperationID %d\nreturnOrigin %d\nreturnValue %d\n", + osdata.operation.OperationID, osdata.returnOrigin, osdata.returnValue); + fclose(f1); + break; + case CLOSE_SESSION: + if (in == 1) + fname = "CloseSess.txt"; + else + fname = "CloseSessResult.txt"; + f1 = fopen(fname, "w+"); + CloseSessionData csdata = *(CloseSessionData*) fdata; + fprintf(f1, "ClosesessionData ---------\ncontextID %d\nSessionID %d\n", + csdata.contextID, csdata.sessionID); + fclose(f1); + break; + case INVOKE_COMMAND: + if (in == 1) + fname = "InvComm.txt"; + else + fname = "InvCommResult.txt"; + f1 = fopen(fname, "w+"); + InvokeCommandData icdata = *(InvokeCommandData*) fdata; + fprintf(f1, + "InvokeCommandData ---------\ncontextID %d\nSessionID %d\ + \nCommandID %d\nparamTypes %d\n", + icdata.contextID, icdata.sessionID, icdata.commandID, + icdata.operation.paramTypes); + for (i = 0; i < 4; i++) { + type = ((icdata.operation.paramTypes) >> (8 * i)) & 0x7f; + if (type == TEEC_NONE) + fprintf(f1, "param[%d] NONE\n", i); + else if ((type + == TEEC_VALUE_INPUT) | (type == TEEC_VALUE_OUTPUT) | (type == TEEC_VALUE_INOUT)) + fprintf(f1, "param[%d] value a %d value b %d\n", i, + icdata.operation.params[i].value.a, + icdata.operation.params[i].value.b); + else { + fprintf(f1, "param[%d] mem shmKey %d size %d offset %d\n", i, + icdata.operation.params[i].mem.shmKey, + icdata.operation.params[i].mem.size, + icdata.operation.params[i].mem.offset); + key = icdata.operation.params[i].mem.shmKey; + shmid = shmget(key, icdata.operation.params[i].mem.size, + IPC_CREAT | 0666); + if (shmid == -1) { + LOGE(TEEC_LIB, "shmget failed"); + return TEEC_ERROR_GENERIC; + } + + if ((buffer = (char*) shmat(shmid, NULL, 0)) == (char*) -1) { + LOGE(TEEC_LIB, "shmat failed"); + return TEEC_ERROR_GENERIC; + } + + if (!buffer) { + LOGE(TEEC_LIB, "shmat failed"); + return TEEC_ERROR_GENERIC; + } + + fprintf(f1, "SharedMemData: \n"); + char *shmdata = (buffer + icdata.operation.params[i].mem.offset); + for (j = 0; j < icdata.operation.params[i].mem.size; j++) + fprintf(f1, "%x", shmdata[j]); + fprintf(f1, "\n"); + + if (shmdt(buffer) == -1) { + printf("shmdt failed"); + } + buffer = NULL; + } + } + fprintf(f1, "OperationID %d\nreturnOrigin %d\nreturnValue %d\n", + icdata.operation.OperationID, icdata.returnOrigin, icdata.returnValue); + fclose(f1); + break; + case REQUEST_CANCELLATION: + if (in == 1) + fname = "ReqCancell.txt"; + else + fname = "ReqCancellResult.txt"; + //Not supported in current design + break; + default: + LOGE(TEEC_LIB, "Invalid command"); + } + return TEEC_SUCCESS; +} +#endif + +/* + * === FUNCTION ====================================================================== + * Name: sendCommand + * Description: API (Interface for TEECAPI) implementation for sending a + * command to Simulator daemon + * Parameters: sockfd - Socket fd + * cmd - Command sent/received + * fdata - data sent/received + * size - size of data sent/received + * Return: TEEC_SUCCESS: Success + * TEEC_ERROR_GENERIC: Failure + * ===================================================================================== + */ +uint32_t sendCommand(int32_t sockfd, TEE_CMD cmd, void* data, size_t size) { + LOGD(TEEC_LIB, "Entry"); + TEEC_Result result = TEEC_SUCCESS; + char command = (char)cmd; + +#ifdef TEST + // Check if the data is proper + result = Test(command, data, size, 1); + if (result != TEEC_SUCCESS) { + return TEEC_ERROR_GENERIC; + } +#endif + // send command to Simulator Daemon + result = sendCommandtoDaemon(sockfd, (char*)&command, sizeof(char)); + if (result != TEEC_SUCCESS) { + return TEEC_ERROR_GENERIC; + } + // send command data to Simulator Daemon + result = sendCommandtoDaemon(sockfd, (char*)data, size); + if (result != TEEC_SUCCESS) { + return TEEC_ERROR_GENERIC; + } + // receive command from Simulator Daemon + result = receiveResponse(sockfd, (char*)&command, sizeof(char)); + if (result != TEEC_SUCCESS) { + return TEEC_ERROR_GENERIC; + } + // receive command data from Simulator Daemon + result = receiveResponse(sockfd, (char*)data, size); + if (result != TEEC_SUCCESS) { + return TEEC_ERROR_GENERIC; + } +#ifdef TEST + // Check if the data is proper + result = Test(command, data, size, 0); + if (result != TEEC_SUCCESS) { + return TEEC_ERROR_GENERIC; + } +#endif + return result; +} diff --git a/TEEStub/.cproject b/TEEStub/.cproject new file mode 100755 index 0000000..9ed7e56 --- /dev/null +++ b/TEEStub/.cproject @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TEEStub/.gitignore b/TEEStub/.gitignore new file mode 100755 index 0000000..3df573f --- /dev/null +++ b/TEEStub/.gitignore @@ -0,0 +1 @@ +/Debug/ diff --git a/TEEStub/.project b/TEEStub/.project new file mode 100755 index 0000000..dae54e6 --- /dev/null +++ b/TEEStub/.project @@ -0,0 +1,84 @@ + + + TEEStub + + + ssflib + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/TEEStub/Debug} + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/TEEStub/.settings/org.eclipse.cdt.core.prefs b/TEEStub/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..935792c --- /dev/null +++ b/TEEStub/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,16 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152.533145061/PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152.533145061/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152.533145061/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\Program Files (x86)\\Java\\jre1.8.0_45\\bin;C\:\\Program Files\\eclipse;C\:/Program Files/Java/jre1.8.0_31/bin/server;C\:/Program Files/Java/jre1.8.0_31/bin;C\:/Program Files/Java/jre1.8.0_31/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\csvn\\bin\\;C\:\\csvn\\Python25\\;C\:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files\\Diskeeper Corporation\\ExpressCache\\;C\:\\Program Files (x86)\\Windows Live\\Shared;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x64;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files (x86)\\WinSCP\\;C\:\\Program Files (x86)\\PuTTY;C\:\\Program Files\\Microsoft\\Web Platform Installer\\;C\:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C\:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;C\:\\Program Files (x86)\\doxygen\\bin;C\:\\Program Files (x86)\\sfk168;C\:\\Program Files (x86)\\vlc-2.1.0;C\:\\Python27\\Scripts;C\:\\Program Files (x86)\\GnuWin32\\bin;C\:\\Python27;C\:\\Program Files (x86)\\Subversion\\bin;c\:\\Program Files\\Synergy;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\MinGW\\lib\\gcc\\mingw32\\4.8.1;C\:\\Program Files (x86)\\Windows Kits\\8.1\\Windows Performance Toolkit\\;C\:\\Program Files (x86)\\GitExtensions\\;C\:\\Program Files\\Perforce;c\:\\Program Files\\Java\\jre1.8.0_31\\bin\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;D\:\\tizen-sdk\\ide;D\:\\samsung-tv-sdk\\tasdk_ide\\tasdk_tools\\i386-linux-gnueabi-gcc-4.6\\bin;D\:\\samsung-tv-sdk\\tasdk_ide\\tasdk_tools\\mingw\\bin;D\:\\samsung-tv-sdk\\tasdk_ide\\tasdk_tools\\mingw\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152.533145061/append=true +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152.533145061/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152/PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152/PATH/value=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/usr/games\:/usr/local/games\:/usr/local/lib\:usr/lib;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\bin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\mingbin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152/append=true +environment/project/cdt.managedbuild.config.gnu.exe.debug.1955467152/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.exe.release.1350514530/PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.release.1350514530/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.exe.release.1350514530/PATH/value=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/usr/games\:/usr/local/games +environment/project/cdt.managedbuild.config.gnu.exe.release.1350514530/append=true +environment/project/cdt.managedbuild.config.gnu.exe.release.1350514530/appendContributed=true diff --git a/TEEStub/.settings/org.eclipse.cdt.ui.prefs b/TEEStub/.settings/org.eclipse.cdt.ui.prefs new file mode 100755 index 0000000..4ee12a4 --- /dev/null +++ b/TEEStub/.settings/org.eclipse.cdt.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +formatter_settings_version=1 diff --git a/TEEStub/.settings/org.eclipse.ltk.core.refactoring.prefs b/TEEStub/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100755 index 0000000..b196c64 --- /dev/null +++ b/TEEStub/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/TEEStub/DeveloperReadme.txt b/TEEStub/DeveloperReadme.txt new file mode 100755 index 0000000..58c5444 --- /dev/null +++ b/TEEStub/DeveloperReadme.txt @@ -0,0 +1,43 @@ +# Samsung Research and Development Institute, Bangalore +# Copyright (c) 2015, All Rights Reserved + +This readme is a developer's log book on progress of implementation and status +of functionality. It is intended to aid development and is not to be +used for any other purpose. + + +Properties: +1. As per specification, Property access function shall be accessible as described below: + + Excerpt from TEE Internal Specification: + | Note that Client Properties can be accessed only in the context of a TA entry point associated with + | a client, i.e. in one of the following entry point + | functions: TA_OpenSessionEntryPoint, TA_InvokeCommandEntryPoint, or TA_CloseSessionEntryPoint + + Access to the property functions in above mentioned restricted context is yet to be implemented in case of + Client properties. + +2. Due to change in C standards, compilers do not support typecasting to pointer type of constant values + in #define s. As per spec. we need to define Propsets as: + TEE_PROPSET_TEE_IMPLEMENTATION (TEE_PropSetHandle)0xFFFFFFFD + The above is not possible anymore. Specification does not understand this. + + As of now, above macro is defined as: + TEE_PROPSET_TEE_IMPLEMENTATION 0xFFFFFFFD + + Which forces user to typecast TEE_PROPSET_TEE_IMPLEMENTATION to (TEE_PropSetHandle)TEE_PROPSET_TEE_IMPLEMENTATION + when calling Property Access APIs + +3. Client Identity for client properties: UUID of client doesn't make sense as it is not defined in the + specificationc clearly. As of now the client UUID is set to Nil UUID. This needs to be fixed when + permission management to access TA Entrypoints is to be enforced. + +4. Client Properties may need to stored on each new session and appended to a list of client props. + All of the client properties bear the name "gpd.client.identity" hence has to be a list + unlike other propsets which use maps as they have unique keys. This feature is yet to be implemented. + +SSFLib: +1. Communication with other TAs from this TA: + Replies from other multiple TA to be handled yet based on operation IDs or some other + way of unique identification of commands to map replies to caller. + \ No newline at end of file diff --git a/TEEStub/PropertyAccess/ClientProperty.cpp b/TEEStub/PropertyAccess/ClientProperty.cpp new file mode 100755 index 0000000..1184d3d --- /dev/null +++ b/TEEStub/PropertyAccess/ClientProperty.cpp @@ -0,0 +1,104 @@ +/* + * ===================================================================================== + * + * Filename: ClientProperty.cpp + * + * Description: ClientProperty class + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor of Client Property + * @param filePath[in] file to read Client properties from. + */ +// TODO: identity by defauly in property file to be stored as +// identity: integer (‘:’ uuid)? +// so that when fetched, is by default in string format as stated above +ClientProperty::ClientProperty(PropertyValue init) : + theOnlyClientPropertyName("gpd.client.identity"), theOnlyCientProperty(init) { +} + +/** + * Get name of the property in format gpd.client.* + * @param name[out] Name of property + * @return true if enumerator marker is pointing in valid range else false/ + */ +bool ClientProperty::getPropertyName(string &name) { + name = theOnlyClientPropertyName; + return true; +} + +/** + * Advance the marker of enumerator to point to next property + * @return true if successfully advanced to next property else false + * if marker reached end of enumeration. + */ +bool ClientProperty::getNextProperty() { + // Do nothing, as we have only one property in enumeration + return false; +} + +/** + * Start enumeration by reading the property file and set marker to first property + * @return true if property file successfully read else false + */ +bool ClientProperty::start() { + // Do nothing, as we have only one property in enumeration + return true; +} + +/** + * Reset marker to start from first. + */ +void ClientProperty::reset() { + // Do nothing, as we have only one property in enumeration +} + +/** + * Get property value pointed by marker currently. + * @param pv[out] Property value pointed by marker + * @return If marker is not pointing to end of enumeration then returns true + * else false + */ +bool ClientProperty::getPropertyValue(PropertyValue &pv) { + pv = theOnlyCientProperty; + return true; +} + +/** + * Client property destructor + */ +ClientProperty::~ClientProperty() { +} + +/** + * Get property value associated with given property name by searching for it + * @param propName[in] Property name in format gpd.client.* + * @param value[out] Property value on successful match + * @return true if property of given name exists else false + */ +bool ClientProperty::getPropertyByName(const string &propName, + PropertyValue &value) { + if (theOnlyClientPropertyName == propName) { + value = theOnlyCientProperty; + return true; + } + return false; +} diff --git a/TEEStub/PropertyAccess/ClientProperty.h b/TEEStub/PropertyAccess/ClientProperty.h new file mode 100755 index 0000000..e6c0a91 --- /dev/null +++ b/TEEStub/PropertyAccess/ClientProperty.h @@ -0,0 +1,46 @@ +/* + * ===================================================================================== + * + * Filename: ClientProperty.h + * + * Description: ClientProperty header file + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef PROPERTYACCESS_CLIENTPROPERTY_H_ +#define PROPERTYACCESS_CLIENTPROPERTY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ClientProperty: + public Property { +private: + string theOnlyClientPropertyName; + PropertyValue theOnlyCientProperty; +public: + bool getPropertyName(string&); + bool getPropertyByName(const string &propName, PropertyValue &value); + bool getNextProperty(); + bool getPropertyValue(PropertyValue&); + bool start(); + void reset(); + ClientProperty(PropertyValue init); + virtual ~ClientProperty(); +}; + +#endif /* PROPERTYACCESS_CLIENTPROPERTY_H_ */ diff --git a/TEEStub/PropertyAccess/Property.h b/TEEStub/PropertyAccess/Property.h new file mode 100755 index 0000000..a0b3519 --- /dev/null +++ b/TEEStub/PropertyAccess/Property.h @@ -0,0 +1,56 @@ +/* + * ===================================================================================== + * + * Filename: Property.h + * + * Description: Property header file + * + * Version: 1.0 + * Created: 20 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef PROPERTYACCESS_PROPERTY_H_ +#define PROPERTYACCESS_PROPERTY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +using namespace std; + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +typedef struct { + string type; + string value; +} PropertyValue; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class Property { +public: + virtual bool getPropertyName(string&) = 0; + virtual bool getPropertyByName(const string &propName, + PropertyValue &value) = 0; + virtual bool getNextProperty() = 0; + virtual bool start() = 0; + virtual void reset() = 0; + virtual bool getPropertyValue(PropertyValue&) = 0; + Property() { + } + ; + virtual ~Property() { + } + ; +}; + +#endif /* PROPERTYACCESS_PROPERTY_H_ */ diff --git a/TEEStub/PropertyAccess/PropertyApi.cpp b/TEEStub/PropertyAccess/PropertyApi.cpp new file mode 100755 index 0000000..7cc2e15 --- /dev/null +++ b/TEEStub/PropertyAccess/PropertyApi.cpp @@ -0,0 +1,405 @@ +/* + * ===================================================================================== + * + * Filename: PropertyApi.cpp + * + * Description: PropertyApi class + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include + +using namespace std; + +// PRIVATE TO THIS API FILE +static Property* clientProperty; +static Property* taProperty; +static Property* teeProperty; +static uint32_t clientLoginGlobal = 0; +static string thisTAUUIDGlobal = ""; +bool _allowPropertyAccess = false; + +/** + * Static local function to identify the right object of Property + * If propsetOrEnumerator is a constant propset then existing objects of + * Property on given propset is returned. If propsetOrEnumerator is a handle to + * an enumerator then PropertyEnumHandle object is returned. + * @param propsetOrEnumerator[in] A handle of type TEE_PropSetHandle + * @return NULL if handle is invalid else returns valid handle + */ +static Property* _GetTargetProperty(TEE_PropSetHandle propsetOrEnumerator); + +//GLOBAL DEFNS +typedef struct { + Property* property; +} PropertyEnumHandle; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Initialization routine of PropertyAccess Module. This function should be + * called when TA stub starts with UUID of this TA. + * @param UUID[in] UUID of this TA + * @param clientLogin[in] login method to this TA from client. + * Refer Table 4-13: Client Identities + * @return TEE_ERROR_OUT_OF_MEMORY on failure to initialize else TEE_SUCCESS + */ +TEE_Result InitPropertyModule(char* UUID, uint32_t clientLogin) { + PropertyValue pv; + pv.type = "identity"; + pv.value = "" + clientLogin; + string thisTA_UUID(UUID); + clientLoginGlobal = clientLogin; + thisTAUUIDGlobal = thisTA_UUID; + try { + clientProperty = new ClientProperty(pv); + clientProperty->start(); + teeProperty = new TEEProperty(); + teeProperty->start(); + taProperty = new TAProperty( + string(TEE_TASTORE_ROOT) + thisTA_UUID + "-ext/" + thisTA_UUID + + ".manifest"); + taProperty->start(); + } catch (std::bad_alloc &ba) { + return TEE_ERROR_OUT_OF_MEMORY; + } + return TEE_SUCCESS; +} + +/** + * Deallocate Property Access objects + */ +void DeInitPropertyModule() { + delete clientProperty; + delete taProperty; + delete teeProperty; +} + +//TODO: TEE_ERROR_ITEM_NOT_FOUND also to be returned when the string +//received in not UTF8 encoded format +//Assuming valueBufferLen is [in] param only. + +TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + const char* name, char* valueBuffer, size_t* valueBufferLen) { + TEE_Result returnValue = TEE_SUCCESS; + Property* targetProperty = NULL; + PropertyValue pv; + string queryProp = ""; + + if (NULL == propsetOrEnumerator){ + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (NULL != name) queryProp = string(name); + // 1. Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(propsetOrEnumerator); + // 2. after selecting targetProperty fetch the property name + if (targetProperty + && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv)) + || (NULL == name && targetProperty->getPropertyValue(pv)))) { + if (valueBuffer && pv.value.size() < *valueBufferLen) + strncpy(valueBuffer, pv.value.c_str(), *valueBufferLen); + else returnValue = TEE_ERROR_SHORT_BUFFER; + } else returnValue = TEE_ERROR_ITEM_NOT_FOUND; + +// Above is optimized version of below +#if 0 + + if (NULL != name && targetProperty && targetProperty->getPropertyByName(queryProp, pv)) + { + // SIZE FITS IN BUFFER + if (pv.value.size() < *valueBufferLen) + strcpy(valueBuffer, pv.value.c_str()); + else + returnValue = TEE_ERROR_SHORT_BUFFER; + } + else if (NULL == name && targetProperty && targetProperty->getPropertyValue(pv)) + { + if (pv.value.size() < *valueBufferLen) + strcpy(valueBuffer, pv.value.c_str()); + else + returnValue = TEE_ERROR_SHORT_BUFFER; + } + else + returnValue = TEE_ERROR_ITEM_NOT_FOUND; +#endif + return returnValue; +} + +TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, + const char* name, bool* value) { + TEE_Result returnValue = TEE_SUCCESS; + Property* targetProperty = NULL; + PropertyValue pv; + string queryProp = ""; + if (NULL != name) queryProp = string(name); + // 1. Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(propsetOrEnumerator); + // 2. after selecting targetProperty fetch the property by name or as in + // pointed by enumerator marker + if (targetProperty + && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv)) + || (NULL == name && targetProperty->getPropertyValue(pv)))) { + returnValue = PropertyUtility::convertToBool(pv, *value); + } else returnValue = TEE_ERROR_ITEM_NOT_FOUND; +// Above is optimized version of below +#if 0 + if (NULL != name && targetProperty && targetProperty->getPropertyByName(queryProp, pv)) + { + returnValue = PropertyUtility::convertToBool(pv, *value); + } + else if (NULL == name && targetProperty && targetProperty->getPropertyValue(pv)) + { + returnValue = PropertyUtility::convertToBool(pv, *value); + } + else + returnValue = TEE_ERROR_ITEM_NOT_FOUND; +#endif + return returnValue; +} + +TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, + const char* name, uint32_t* value) { + TEE_Result returnValue = TEE_SUCCESS; + Property* targetProperty = NULL; + PropertyValue pv; + string queryProp = ""; + if (NULL != name) queryProp = string(name); + // 1. Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(propsetOrEnumerator); + // 2. after selecting targetProperty fetch the property by name or as in + // pointed by enumerator marker + if (targetProperty + && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv)) + || (NULL == name && targetProperty->getPropertyValue(pv)))) { + returnValue = PropertyUtility::convertToU32(pv, *value); + } else returnValue = TEE_ERROR_ITEM_NOT_FOUND; + return returnValue; +} + +TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + const char* name, void* valueBuffer, size_t* valueBufferLen) { + TEE_Result returnValue = TEE_SUCCESS; + Property* targetProperty = NULL; + PropertyValue pv; + string queryProp = ""; + if (NULL != name) queryProp = string(name); + + // Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(propsetOrEnumerator); + // After selecting targetProperty fetch the property name + if (targetProperty + && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv)) + || (NULL == name && targetProperty->getPropertyValue(pv)))) { + + string binaryBlockOut; + returnValue = PropertyUtility::convertToBinaryBlock(pv, binaryBlockOut); + bool conversionStatus = (returnValue == TEE_SUCCESS) ? true : false; + if (valueBuffer && conversionStatus + && binaryBlockOut.size() < *valueBufferLen) { + strncpy((char*)valueBuffer, binaryBlockOut.c_str(), *valueBufferLen); + } else returnValue = TEE_ERROR_SHORT_BUFFER; + } else returnValue = TEE_ERROR_ITEM_NOT_FOUND; + return returnValue; +} + +// TODO: In spec: value: A pointer filled with the UUID. MUST NOT be NULL. +// What does it mean? Must not be NULL +TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, + const char* name, TEE_UUID* value) { + TEE_Result returnValue = TEE_SUCCESS; + Property* targetProperty = NULL; + PropertyValue pv; + string queryProp = ""; + if (NULL != name) queryProp = string(name); + // 1. Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(propsetOrEnumerator); + // 2. after selecting targetProperty fetch the property by name or as in + // pointed by enumerator marker + if (targetProperty + && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv)) + || (NULL == name && targetProperty->getPropertyValue(pv)))) { + returnValue = PropertyUtility::convertToUUID(pv, *value); + } else returnValue = TEE_ERROR_ITEM_NOT_FOUND; + return returnValue; +} + +// TODO: In spec: value: A pointer filled with the UUID. MUST NOT be NULL. +// What does it mean? Must not be NULL +TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, + const char* name, TEE_Identity* value) { + TEE_Result returnValue = TEE_SUCCESS; + Property* targetProperty = NULL; + PropertyValue pv; + string queryProp = ""; + if (NULL != name) queryProp = string(name); + // 1. Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(propsetOrEnumerator); + // 2. after selecting targetProperty fetch the property by name or as in + // pointed by enumerator marker + if (targetProperty + && ((NULL != name && targetProperty->getPropertyByName(queryProp, pv)) + || (NULL == name && targetProperty->getPropertyValue(pv)))) { + returnValue = PropertyUtility::convertToIdentity(pv, *value); + } else returnValue = TEE_ERROR_ITEM_NOT_FOUND; + return returnValue; +} + +TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle* enumerator) { + try { + PropertyEnumHandle *newEnumHandle = new PropertyEnumHandle; + newEnumHandle->property = NULL; + *enumerator = (TEE_PropSetHandle)newEnumHandle; + } catch (std::bad_alloc &ba) { + return TEE_ERROR_OUT_OF_MEMORY; + } + return TEE_SUCCESS; +} + +void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) { + PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator; + if (enumeratorHandle) { + delete enumeratorHandle->property; + enumeratorHandle = NULL; + delete enumeratorHandle; + } +} + +//TODO: propSet value sent from user has to typecased to TEE_PropSetHandle +// this shouldnt happen, make it straight +void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, + TEE_PropSetHandle propSet) { + PropertyEnumHandle *newEnumHandle = (PropertyEnumHandle*)enumerator; + switch ((uint32_t)propSet) { + case TEE_PROPSET_CURRENT_TA: { + newEnumHandle->property = new TAProperty( + string(TEE_TASTORE_ROOT) + thisTAUUIDGlobal + "-ext/" + + thisTAUUIDGlobal + ".manifest"); + break; + } + case TEE_PROPSET_CURRENT_CLIENT: { + PropertyValue pv; + pv.type = "identity"; + pv.value = "" + clientLoginGlobal; + if(!_allowPropertyAccess) + { + break; + } + newEnumHandle->property = new ClientProperty(pv); + break; + } + case TEE_PROPSET_TEE_IMPLEMENTATION: { + newEnumHandle->property = new TEEProperty(); + break; + } + default: { + // Nothing + break; + } + } + + if (newEnumHandle && newEnumHandle->property) + newEnumHandle->property->start(); +} + +void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) { + PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator; + if (enumeratorHandle->property) delete enumeratorHandle->property; +} + +/* + * Considers nameBufferLen as [in] param as spec. is ambiguous + */ +TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, void* nameBuffer, + size_t* nameBufferLen) { + Property* targetProperty = NULL; + // 1. Select the enumerator object based on propset or consider given enumerator + // if any + targetProperty = _GetTargetProperty(enumerator); + + PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator; + // Check if enumerator and property are valid + //if (enumeratorHandle && enumeratorHandle->property) { + if (enumeratorHandle && targetProperty) { + string propName; + // If item exists and and not reached end of enumerator, get the name + if (enumeratorHandle->property->getPropertyName(propName)) { + if (*nameBufferLen < propName.size() + 1) return TEE_ERROR_SHORT_BUFFER; + strncpy((char*)nameBuffer, propName.c_str(), *nameBufferLen); + } + // item not found or enumerator end has reached + else { + return TEE_ERROR_ITEM_NOT_FOUND; + } + } else { + return TEE_ERROR_ITEM_NOT_FOUND; + } + return TEE_SUCCESS; +} + +TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) { + PropertyEnumHandle* enumeratorHandle = (PropertyEnumHandle*)enumerator; + // Check if enumerator and property are valid and enumerator has not reached end of enum + if (enumeratorHandle && enumeratorHandle->property + && enumeratorHandle->property->getNextProperty()) { + return TEE_SUCCESS; + } else return TEE_ERROR_ITEM_NOT_FOUND; + +} + +Property* _GetTargetProperty(TEE_PropSetHandle propsetOrEnumerator) { + Property *targetProperty = NULL; + switch ((uint32_t)propsetOrEnumerator) { + case TEE_PROPSET_TEE_IMPLEMENTATION: { + targetProperty = teeProperty; + break; + } + case TEE_PROPSET_CURRENT_CLIENT: { + if(!_allowPropertyAccess) + { + break; + } + targetProperty = clientProperty; + break; + } + case TEE_PROPSET_CURRENT_TA: { + targetProperty = taProperty; + break; + } +/* default: { + PropertyEnumHandle *newEnumHandle = + (PropertyEnumHandle*)propsetOrEnumerator; + + if (newEnumHandle && newEnumHandle->property) + targetProperty = newEnumHandle->property; + break; + } +*/ } + return targetProperty; +} diff --git a/TEEStub/PropertyAccess/PropertyApi.h b/TEEStub/PropertyAccess/PropertyApi.h new file mode 100755 index 0000000..f7e5de3 --- /dev/null +++ b/TEEStub/PropertyAccess/PropertyApi.h @@ -0,0 +1,41 @@ +/* + * ===================================================================================== + * + * Filename: PropertyApi.h + * + * Description: PropertyApi header file + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef PROPERTYACCESS_PROPERTYAPI_H_ +#define PROPERTYACCESS_PROPERTYAPI_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_internal_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +TEE_Result InitPropertyModule(char* UUID, uint32_t clientLogin); +void DeInitPropertyModule(); + +#ifdef __cplusplus +} +#endif + +#endif /* PROPERTYACCESS_PROPERTYAPI_H_ */ diff --git a/TEEStub/PropertyAccess/PropertyUtility.cpp b/TEEStub/PropertyAccess/PropertyUtility.cpp new file mode 100755 index 0000000..7603aa0 --- /dev/null +++ b/TEEStub/PropertyAccess/PropertyUtility.cpp @@ -0,0 +1,384 @@ +/* + * ===================================================================================== + * + * Filename: PropertyUtility.cpp + * + * Description: PropertyUtility class + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/// Constant charset of base64 encoding +static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Converts a string in properties entry to UTF8 + * ACSII printable characters are subset of UTF8 hence no need of conversion. + * @param in[in] a property to be converted to UTF8 + * @param out[out] converted property + * @return TEE_SUCCESS always. Here function returns fixed value for the + * to maintain uniformity. + */ +TEE_Result PropertyUtility::convertToUTF8(const PropertyValue& in, + string& out) { + out = in.value; + return TEE_SUCCESS; +} + +/** + * Try to convert given property to bool + * @param in[in] a property to be converted to bool + * @param out[out] converted property + * @return + */ +TEE_Result PropertyUtility::convertToBool(const PropertyValue &in, bool& out) { + TEE_Result returnval = TEE_SUCCESS; + if (in.type == "boolean") { + if ("true" == in.value) + out = true; + else out = false; + } else { + // As per spec: A pointer to the variable that will contain the value of the + // property on success or "false" on error. Hence default value is "false" + out = false; + returnval = TEE_ERROR_BAD_FORMAT; + } + return returnval; +} + +/** + * Try to convert given property to unsigned 32 bit integer + * @param in[in] a property to be converted to 32 bit unsigned integer + * @param out[out] converted property + * @return + */ +TEE_Result PropertyUtility::convertToU32(const PropertyValue& in, + uint32_t &out) { + TEE_Result returnval = TEE_SUCCESS; + stringstream sstr; + if (in.type == "integer") { + sstr << in.value; + sstr >> out; + } + else if (in.type == "boolean") + { + out = (in.value == "true" ? 1 : 0); + } + else + { // As per spec:A pointer to the variable that will contain the value of the property + // on success, or zero on error + // Hence default value is "false" + out = 0; + returnval = TEE_ERROR_BAD_FORMAT; + } + return returnval; +} + +/** + * Try to convert given property to TEE_UUID + * @param in[in] a property to be converted to TEE_UUID + * @param out[out] converted property + * @return + */ +TEE_Result PropertyUtility::convertToUUID(const PropertyValue& in, + TEE_UUID& out) { + TEE_UUID uuid; + TEE_Result returnValue = TEE_SUCCESS; + if ("uuid" == in.type) { + // Split UUID string into tokens + string text = in.value; + + string tokensString[8]; + int i = 0; + for (i = 0; i < 8; i++) { + strncpy(&tokensString[i][0], &text[4 * i], 4); + } + // convert each token + sscanf((tokensString[0] + tokensString[1]).c_str(), "%8x", &uuid.timeLow); + sscanf(tokensString[2].c_str(), "%4hx", &uuid.timeMid); + sscanf(tokensString[3].c_str(), "%4hx", &uuid.timeHiAndVersion); + uint64_t clockSeq; + string clockSeqStr = tokensString[4] + tokensString[5] + tokensString[6] + + tokensString[7]; + //TEST CODE: string clockSeqStr("0123456789ABCDEF"); + sscanf(clockSeqStr.c_str(), "%16llx", &clockSeq); + memcpy(uuid.clockSeqAndNode, &clockSeq, sizeof(uint64_t)); + // Change endian-ness + uint8_t temp[4]; + temp[0] = uuid.clockSeqAndNode[0]; + temp[1] = uuid.clockSeqAndNode[1]; + temp[2] = uuid.clockSeqAndNode[2]; + temp[3] = uuid.clockSeqAndNode[3]; + uuid.clockSeqAndNode[0] = uuid.clockSeqAndNode[7]; + uuid.clockSeqAndNode[1] = uuid.clockSeqAndNode[6]; + uuid.clockSeqAndNode[2] = uuid.clockSeqAndNode[5]; + uuid.clockSeqAndNode[3] = uuid.clockSeqAndNode[4]; + uuid.clockSeqAndNode[4] = temp[3]; + uuid.clockSeqAndNode[5] = temp[2]; + uuid.clockSeqAndNode[6] = temp[1]; + uuid.clockSeqAndNode[7] = temp[0]; + out = uuid; + } else returnValue = TEE_ERROR_BAD_FORMAT; + return returnValue; +} + +// TODO: If UUID exists need to append that to identity +// Right now it is Nil UUID always +/** + * Try to convert given property to TEE_Identity + * @param in[in] a property to be converted to TEE_Identity + * @param out[out] converted property + * @return + */ +TEE_Result PropertyUtility::convertToIdentity(const PropertyValue& in, + TEE_Identity& out) { + if ("identity" != in.type) + return TEE_ERROR_BAD_FORMAT; + else { + out.login = atoi(in.value.c_str()); + // Set to Nil UUID as per [RFC 4122]. + out.uuid.timeLow = 0; + out.uuid.timeMid = 0; + out.uuid.timeHiAndVersion = 0; + for (int i = 0; i < 8; i++) { + out.uuid.clockSeqAndNode[i] = 0; + } + } + return TEE_SUCCESS; +} + +/** + * Convert given property to BinaryBlock in Base64 encoding. + * + * @param in[in] a property to be converted to a block of Base64 encoded data + * @param out[out] converted property + * @return TEE_SUCCESS always. Here function returns fixed value for the + * to maintain uniformity. + */ +TEE_Result PropertyUtility::convertToBinaryBlock(const PropertyValue& in, + string& out) { + string s = in.value; + string base64Encoded = PropertyUtility::base64_encode( + reinterpret_cast(s.c_str()), s.size()); + out = base64Encoded; + return TEE_SUCCESS; +} + +/** + * Convert given Base64 encoded data to its original form. + * @param in[in] a property to be converted from Base64 encoding + * @param out[out] converted property back to its original form + * @return + */ +// TODO: This function to be removed for final release. This is just for testing +TEE_Result PropertyUtility::convertFromBinaryBlock(const string& in, + string& out) { + out = PropertyUtility::base64_decode(in); + return TEE_SUCCESS; +} + +/** + * Checks if a characters is part of base64 encoding character set + * @param c character to be verified + * @return true if conformant to base64 charset else false + */ +bool PropertyUtility::is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +/** + * Thanks to: René Nyffenegger + * Reused from: http://www.adp-gmbh.ch/cpp/common/base64.html + * License Notice: + * Copyright (C) 2004-2008 René Nyffenegger + * + * This source code is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented; you must not + * claim that you wrote the original source code. If you use this source code + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original source code. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * René Nyffenegger rene.nyffenegger@adp-gmbh.ch + * + * @param bytes_to_encode + * @param in_len + * @return encoded string + */ +string PropertyUtility::base64_encode(unsigned char const* bytes_to_encode, + unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (i = 0; (i < 4); i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + if (i) { + for (j = i; j < 3; j++) + char_array_3[j] = '\0'; + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + while ((i++ < 3)) + ret += '='; + } + return ret; +} + +/** + * Thanks to: René Nyffenegger + * Reused from: http://www.adp-gmbh.ch/cpp/common/base64.html + * License Notice: + * Copyright (C) 2004-2008 René Nyffenegger + * + * This source code is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented; you must not + * claim that you wrote the original source code. If you use this source code + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original source code. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * René Nyffenegger rene.nyffenegger@adp-gmbh.ch + * + * @param encoded_string + * @return + */ +//TODO: This function to be removed for final release +string PropertyUtility::base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && (encoded_string[in_] != '=') + && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; + in_++; + if (i == 4) { + for (i = 0; i < 4; i++) + char_array_4[i] = (unsigned char)base64_chars.find(char_array_4[i]); + char_array_3[0] = (char_array_4[0] << 2) + + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + if (i) { + for (j = i; j < 4; j++) + char_array_4[j] = 0; + for (j = 0; j < 4; j++) + char_array_4[j] = (unsigned char)base64_chars.find(char_array_4[j]); + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + for (j = 0; (j < i - 1); j++) + ret += char_array_3[j]; + } + return ret; +} + +/** + * Utility function to check if a string is a positive number + * @param s Input string to be validated + * @return true if a number else false + */ +bool PropertyUtility::isNumber(const string& s) { + std::string::const_iterator it = s.begin(); + while (it != s.end() && std::isdigit(*it)) + ++it; + return (!s.empty() && it == s.end()); +} + +/** + * Converts UUID from TEE_UUID to a string + * @return string of TEE_UUID + */ +string PropertyUtility::getUUIDAsString(TEE_UUID uuid) { + // E.g. returns a string in the format 79B77788-9789-4a7a-A2BE-B60155EEF5F3 + std::stringstream strStream; + strStream << IntToHex(uuid.timeLow) << "-"; + strStream << IntToHex(uuid.timeMid) << "-"; + strStream << IntToHex(uuid.timeHiAndVersion) << "-"; + strStream << IntToHex((short)uuid.clockSeqAndNode[0], 2); + strStream << IntToHex((short)uuid.clockSeqAndNode[1], 2); + strStream << "-"; + for (int i = 2; i < 8; i++) { + strStream << IntToHex((short)uuid.clockSeqAndNode[i], 2); + } + return strStream.str(); +} diff --git a/TEEStub/PropertyAccess/PropertyUtility.h b/TEEStub/PropertyAccess/PropertyUtility.h new file mode 100755 index 0000000..a74eaca --- /dev/null +++ b/TEEStub/PropertyAccess/PropertyUtility.h @@ -0,0 +1,67 @@ +/* + * ===================================================================================== + * + * Filename: PropertyUtility.h + * + * Description: PropertyUtility header file + * + * Version: 1.0 + * Created: 20 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef PROPERTYACCESS_PROPERTYUTILITY_H_ +#define PROPERTYACCESS_PROPERTYUTILITY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_internal_api.h" +#include "log.h" +#include +#include +#include +#include + +using namespace std; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class PropertyUtility { +private: + PropertyUtility() { + } + ; + static bool is_base64(unsigned char c); + static string base64_encode(unsigned char const*, unsigned int len); + static string base64_decode(std::string const& s); + static string getUUIDAsString(TEE_UUID uuid); + template + static string IntToHex(T i, int width = sizeof(T) * 2) { + stringstream stream; + stream << std::setfill('0') << std::setw(width) << std::hex << i; + return stream.str(); + } +public: + static bool isNumber(const string &s); + static TEE_Result convertToUTF8(const PropertyValue &in, string &out); + static TEE_Result convertToBool(const PropertyValue &in, bool &out); + static TEE_Result convertToU32(const PropertyValue &in, uint32_t &out); + static TEE_Result convertToBinaryBlock(const PropertyValue &in, string &out); + static TEE_Result convertFromBinaryBlock(const string &in, string& out); + static TEE_Result convertToUUID(const PropertyValue &in, TEE_UUID &out); + static TEE_Result convertToIdentity(const PropertyValue &in, + TEE_Identity &out); + virtual ~PropertyUtility() { + } + ; +}; + +#endif /* PROPERTYACCESS_PROPERTYUTILITY_H_ */ diff --git a/TEEStub/PropertyAccess/TAProperty.cpp b/TEEStub/PropertyAccess/TAProperty.cpp new file mode 100755 index 0000000..0fcb988 --- /dev/null +++ b/TEEStub/PropertyAccess/TAProperty.cpp @@ -0,0 +1,173 @@ +/* + * ===================================================================================== + * + * Filename: TAProperty.cpp + * + * Description: TAProperty class + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace rapidxml; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor of TA Property + * @param filePath[in] file to read TA properties from. + */ +TAProperty::TAProperty(string filePath) { + currentItr = propertiesMap.begin(); + this->filePath = filePath; + +} + +/** + * Read property file of TA which is nothing but the manifest in XML format. + * @return true if successfully read else false + */ +bool TAProperty::readPropertyFile() { + // Open file + std::ifstream xmlfile(filePath.c_str()); + std::stringstream buffer; + buffer << xmlfile.rdbuf(); + xmlfile.close(); + std::string content(buffer.str()); + // Create xml DOM + xml_document<> doc; + // Parse XML from file and populate doc + doc.parse<0>((char*)content.c_str()); + try { + xml_node<> *propertiesName = doc.first_node("manifest")->first_node( + "properties")->first_node("general"); + for (xml_attribute<> *attr = propertiesName->first_attribute(); attr; attr = + attr->next_attribute()) { + //LOGD(TEE_STUB, "Permission vector: %s", string(childnode->first_attribute("name")->value())); + //1. Populate the map + PropertyValue newValue; + string type; + //1a. Get property value + newValue.value = attr->value(); + + //1b. Identify type + // TODO: UUID type to be added yet + if (PropertyUtility::isNumber(newValue.value)) { + type = "integer"; + } else if (newValue.value == "true" || newValue.value == "false") + type = "boolean"; + else type = "string"; + //1c. Assign type identified + newValue.type = type; + //2. Assign property value to map + propertiesMap[attr->name()] = newValue; + } + } + // Catch rapid xml errors + catch (rapidxml::parse_error &e) { + LOGE(TEE_STUB, "xml exception, at TA Properties %d", e.what()); + return false; + } + return true; +} + +/** + * Get name of the property in format gpd.ta.* + * @param name[out] Name of property + * @return true if enumerator marker is pointing in valid range else false/ + */ +bool TAProperty::getPropertyName(string &name) { + if (currentItr != propertiesMap.end()) { + name = "gpd.ta." + currentItr->first; + return true; + } + return false; +} + +/** + * Advance the marker of enumerator to point to next property + * @return true if successfully advanced to next property else false + * if marker reached end of enumeration. + */ +bool TAProperty::getNextProperty() { + if (currentItr == propertiesMap.end()) { + return false; + } else { + ++currentItr; + if (currentItr == propertiesMap.end()) + return false; + else return true; + } +} + +/** + * Start enumeration by reading the property file and set marker to first property + * @return true if property file successfully read else false + */ +bool TAProperty::start() { + bool ret = readPropertyFile(); + currentItr = propertiesMap.begin(); + return ret; +} + +/** + * Reset marker to start from first. + */ +void TAProperty::reset() { + currentItr = propertiesMap.begin(); +} + +/** + * Get property value pointed by marker currently. + * @param pv[out] Property value pointed by marker + * @return If marker is not pointing to end of enumeration then returns true + * else false + */ +bool TAProperty::getPropertyValue(PropertyValue &pv) { + if (currentItr != propertiesMap.end()) { + pv = currentItr->second; + return true; + } else return false; +} + +/** + * TA property destructor + */ +TAProperty::~TAProperty() { +} + +/** + * Get property value associated with given property name by searching for it + * @param propName[in] Property name in format gpd.ta.* + * @param value[out] Property value on successful match + * @return true if property of given name exists else false + */ +bool TAProperty::getPropertyByName(const string &propName, + PropertyValue &value) { + bool returnval = true; + map::iterator it = propertiesMap.find(propName); + if (it != propertiesMap.end()) { + value = it->second; + } else returnval = false; + return returnval; +} diff --git a/TEEStub/PropertyAccess/TAProperty.h b/TEEStub/PropertyAccess/TAProperty.h new file mode 100755 index 0000000..6adcbe6 --- /dev/null +++ b/TEEStub/PropertyAccess/TAProperty.h @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * Filename: TAProperty.h + * + * Description: TAProperty header file + * + * Version: 1.0 + * Created: 20 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef PROPERTYACCESS_TAPROPERTY_H_ +#define PROPERTYACCESS_TAPROPERTY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TAProperty: + public Property { +private: + string filePath; + map propertiesMap; + bool readPropertyFile(); + map::iterator currentItr; +public: + bool getPropertyName(string&); + bool getPropertyByName(const string &propName, PropertyValue &value); + bool getNextProperty(); + bool getPropertyValue(PropertyValue&); + bool start(); + void reset(); + TAProperty(string filePath); + virtual ~TAProperty(); +}; + +#endif /* PROPERTYACCESS_TAPROPERTY_H_ */ diff --git a/TEEStub/PropertyAccess/TEEProperty.cpp b/TEEStub/PropertyAccess/TEEProperty.cpp new file mode 100755 index 0000000..44b5b40 --- /dev/null +++ b/TEEStub/PropertyAccess/TEEProperty.cpp @@ -0,0 +1,158 @@ +/* + * ===================================================================================== + * + * Filename: TEEProperty.cpp + * + * Description: TEEProperty class + * + * Version: 1.0 + * Created: 21 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +using namespace rapidxml; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor of TEE Property Set + * @param filePath[in] file to read TEE properties from. + */ +TEEProperty::TEEProperty() { + currentItr = propertiesMap.begin(); +} + +/** + * Read property file of TEE and parse it to extract property values and types. + * @return true if successfully read else false + */ +bool TEEProperty::readPropertyFile(string filePath) { + + // Open file + std::ifstream xmlfile(filePath.c_str()); + if (xmlfile.fail()) return false; + std::stringstream buffer; + buffer << xmlfile.rdbuf(); + xmlfile.close(); + std::string content(buffer.str()); + // Create xml DOM + xml_document<> doc; + // Parse XML from file and populate doc + doc.parse<0>((char*)content.c_str()); + try { + xml_node<> *propertiesName = doc.first_node("teeproperties"); + for (xml_node<> *childnode = propertiesName->first_node("property"); + childnode; childnode = childnode->next_sibling()) { + //LOGD(TEE_STUB, "Permission vector: %s", string(childnode->first_attribute("name")->value())); + // Populate the map + PropertyValue newValue; + newValue.type = childnode->first_attribute("type")->value(); + newValue.value = childnode->first_attribute("value")->value(); + propertiesMap[childnode->first_attribute("name")->value()] = newValue; + } + } + // Catch rapid xml errors + catch (rapidxml::parse_error &e) { + LOGE(TEE_STUB, "xml exception, at TEE Properties %s", e.what()); + return false; + } + return true; +} + +/** + * Get name of the property in format gpd.tee.* + * @param name[out] Name of property + * @return true if enumerator marker is pointing in valid range else false/ + */ +bool TEEProperty::getPropertyName(string &name) { + if (currentItr != propertiesMap.end()) { + name = currentItr->first; + return true; + } + return false; +} + +/** + * Advance the marker of enumerator to point to next property + * @return true if successfully advanced to next property else false + * if marker reached end of enumeration. + */ +bool TEEProperty::getNextProperty() { + if (currentItr == propertiesMap.end()) { + return false; + } else { + ++currentItr; + if (currentItr == propertiesMap.end()) + return false; + else return true; + } +} + +/** + * Start enumeration by reading the property file and set marker to first property + * @return true if property file successfully read else false + */ +bool TEEProperty::start() { + bool ret = readPropertyFile(string(TEE_PROP_FILE)); + currentItr = propertiesMap.begin(); + return ret; +} + +/** + * Reset marker to start from first. + */ +void TEEProperty::reset() { + currentItr = propertiesMap.begin(); +} + +/** + * Get property value pointed by marker currently. + * @param pv[out] Property value pointed by marker + * @return If marker is not pointing to end of enumeration then returns true + * else false + */ +bool TEEProperty::getPropertyValue(PropertyValue &pv) { + if (currentItr != propertiesMap.end()) { + pv = currentItr->second; + return true; + } else return false; +} + +/** + * TEE property destructor + */ +TEEProperty::~TEEProperty() { +} + +/** + * Get property value associated with given property name by searching for it + * @param propName[in] Property name in format gpd.tee.* + * @param value[out] Property value on successful match + * @return true if property of given name exists else false + */ +bool TEEProperty::getPropertyByName(const string &propName, + PropertyValue &value) { + bool returnval = true; + map::iterator it = propertiesMap.find(propName); + if (it != propertiesMap.end()) { + value = it->second; + } else returnval = false; + return returnval; +} diff --git a/TEEStub/PropertyAccess/TEEProperty.h b/TEEStub/PropertyAccess/TEEProperty.h new file mode 100755 index 0000000..690c8c2 --- /dev/null +++ b/TEEStub/PropertyAccess/TEEProperty.h @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * Filename: TEEProperty.h + * + * Description: TEEProperty header file + * + * Version: 1.0 + * Created: 20 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef PROPERTYACCESS_TEEPROPERTY_H_ +#define PROPERTYACCESS_TEEPROPERTY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include "log.h" +#include + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TEEProperty: + public Property { +private: + map propertiesMap; + map::iterator currentItr; + bool readPropertyFile(string filePath); +public: + bool getPropertyName(string&); + bool getPropertyByName(const string &propName, PropertyValue &value); + bool getNextProperty(); + bool getPropertyValue(PropertyValue&); + bool start(); + void reset(); + TEEProperty(); + virtual ~TEEProperty(); +}; + +#endif /* PROPERTYACCESS_TEEPROPERTY_H_ */ diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml.hpp new file mode 100755 index 0000000..73a2b78 --- /dev/null +++ b/TEEStub/PropertyAccess/rapidxml/rapidxml.hpp @@ -0,0 +1,2396 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) +#include // For std::size_t +#include // For assert +#include // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //!

+ //! This function cannot return. If it does, the results are undefined. + //!

+ //! A very simple definition might look like that: + //!
+	//! void %rapidxml::%parse_error_handler(const char *what, void *where)
+	//! {
+	//!     LOGE(TEE_STUB, "Parse error: %s", what);
+	//!     std::abort();
+	//! }
+	//! 
+ //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml { + +//! Parse error exception. +//! This exception is thrown by the parser when an error occurs. +//! Use what() function to get human-readable error message. +//! Use where() function to get a pointer to position within source text where error was detected. +//!

+//! If throwing exceptions by the parser is undesirable, +//! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. +//! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. +//! This function must be defined by the user. +//!

+//! This class derives from std::exception class. +class parse_error: + public std::exception { + +public: + + //! Constructs parse error + parse_error(const char *what, void *where) : + m_what(what), m_where(where) { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw () { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template + Ch *where() const { + return reinterpret_cast(m_where); + } + +private: + + const char *m_what; + void *m_where; + +}; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE +// Size of static memory block of memory_pool. +// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. +// No dynamic memory allocations are performed by memory_pool until static memory is exhausted. +#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE +// Size of dynamic memory block of memory_pool. +// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. +// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. +#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT +// Memory allocation alignment. +// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. +// All memory allocations for nodes, attributes and strings will be aligned to this value. +// This must be a power of 2 and at least 1, otherwise memory_pool will not work. +#define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml { +// Forward declarations +template class xml_node; +template class xml_attribute; +template class xml_document; + +//! Enumeration listing all node types produced by the parser. +//! Use xml_node::type() function to query node type. +enum node_type { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. +}; + +/////////////////////////////////////////////////////////////////////// +// Parsing flags + +//! Parse flag instructing the parser to not create data nodes. +//! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_data_nodes = 0x1; + +//! Parse flag instructing the parser to not use text of first data node as a value of parent element. +//! Can be combined with other flags by use of | operator. +//! Note that child data nodes of element node take precendence over its value when printing. +//! That is, if element has one or more child data nodes and a value, the value will be ignored. +//! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. +//!

+//! See xml_document::parse() function. +const int parse_no_element_values = 0x2; + +//! Parse flag instructing the parser to not place zero terminators after strings in the source text. +//! By default zero terminators are placed, modifying source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_string_terminators = 0x4; + +//! Parse flag instructing the parser to not translate entities in the source text. +//! By default entities are translated, modifying source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_entity_translation = 0x8; + +//! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. +//! By default, UTF-8 handling is enabled. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_utf8 = 0x10; + +//! Parse flag instructing the parser to create XML declaration node. +//! By default, declaration node is not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_declaration_node = 0x20; + +//! Parse flag instructing the parser to create comments nodes. +//! By default, comment nodes are not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_comment_nodes = 0x40; + +//! Parse flag instructing the parser to create DOCTYPE node. +//! By default, doctype node is not created. +//! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_doctype_node = 0x80; + +//! Parse flag instructing the parser to create PI nodes. +//! By default, PI nodes are not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_pi_nodes = 0x100; + +//! Parse flag instructing the parser to validate closing tag names. +//! If not set, name inside closing tag is irrelevant to the parser. +//! By default, closing tags are not validated. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_validate_closing_tags = 0x200; + +//! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. +//! By default, whitespace is not trimmed. +//! This flag does not cause the parser to modify source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_trim_whitespace = 0x400; + +//! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. +//! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. +//! By default, whitespace is not normalized. +//! If this flag is specified, source text will be modified. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_normalize_whitespace = 0x800; + +// Compound flags + +//! Parse flags which represent default behaviour of the parser. +//! This is always equal to 0, so that all other flags can be simply ored together. +//! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. +//! This also means that meaning of each flag is a negation of the default setting. +//! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, +//! and using the flag will disable it. +//!

+//! See xml_document::parse() function. +const int parse_default = 0; + +//! A combination of parse flags that forbids any modifications of the source text. +//! This also results in faster parsing. However, note that the following will occur: +//!
    +//!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • +//!
  • entities will not be translated
  • +//!
  • whitespace will not be normalized
  • +//!
+//! See xml_document::parse() function. +const int parse_non_destructive = parse_no_string_terminators + | parse_no_entity_translation; + +//! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. +//!

+//! See xml_document::parse() function. +const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + +//! A combination of parse flags resulting in largest amount of data being extracted. +//! This usually results in slowest parsing. +//!

+//! See xml_document::parse() function. +const int parse_full = parse_declaration_node | parse_comment_nodes + | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + +/////////////////////////////////////////////////////////////////////// +// Internals + +//! \cond internal +namespace internal { + +// Struct that contains lookup tables for the parser +// It must be a template to allow correct linking (because it has static data members, which are defined in a header file). +template +struct lookup_tables { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters +}; + +// Find length of the string +template +inline std::size_t measure(const Ch *p) { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; +} + +// Compare strings for equality +template +inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, + std::size_t size2, bool case_sensitive) { + if (size1 != size2) return false; + if (case_sensitive) { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) return false; + } else { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] + != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) + return false; + } + return true; +} +} +//! \endcond + +/////////////////////////////////////////////////////////////////////// +// Memory pool + +//! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. +//! In most cases, you will not need to use this class directly. +//! However, if you need to create nodes manually or modify names/values of nodes, +//! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. +//! Not only is this faster than allocating them by using new operator, +//! but also their lifetime will be tied to the lifetime of document, +//! possibly simplyfing memory management. +//!

+//! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. +//! You can also call allocate_string() function to allocate strings. +//! Such strings can then be used as names or values of nodes without worrying about their lifetime. +//! Note that there is no free() function -- all allocations are freed at once when clear() function is called, +//! or when the pool is destroyed. +//!

+//! It is also possible to create a standalone memory_pool, and use it +//! to allocate nodes, whose lifetime will not be tied to any document. +//!

+//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. +//! Until static memory is exhausted, no dynamic memory allocations are done. +//! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, +//! by using global new[] and delete[] operators. +//! This behaviour can be changed by setting custom allocation routines. +//! Use set_allocator() function to set them. +//!

+//! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. +//! This value defaults to the size of pointer on target architecture. +//!

+//! To obtain absolutely top performance from the parser, +//! it is important that all nodes are allocated from a single, contiguous block of memory. +//! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. +//! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT +//! to obtain best wasted memory to performance compromise. +//! To do it, define their values before rapidxml.hpp file is included. +//! \param Ch Character type of created nodes. +template +class memory_pool { + +public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() : + m_alloc_func(0), m_free_func(0) { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node *allocate_node(node_type type, const Ch *name = 0, + const Ch *value = 0, std::size_t name_size = 0, + std::size_t value_size = 0) { + void *memory = allocate_aligned(sizeof(xml_node )); + xml_node *node = new (memory) xml_node(type); + if (name) { + if (name_size > 0) + node->name(name, name_size); + else node->name(name); + } + if (value) { + if (value_size > 0) + node->value(value, value_size); + else node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) { + void *memory = allocate_aligned(sizeof(xml_attribute )); + xml_attribute *attribute = new (memory) xml_attribute; + if (name) { + if (name_size > 0) + attribute->name(name, name_size); + else attribute->name(name); + } + if (value) { + if (value_size > 0) + attribute->value(value, value_size); + else attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) size = internal::measure(source) + 1; + Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); + if (source) for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node *clone_node(const xml_node *source, + xml_node *result = 0) { + // Prepare result node + if (result) { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } else result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node *child = source->first_node(); child; + child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute *attr = source->first_attribute(); attr; + attr = attr->next_attribute()) + result->append_attribute( + allocate_attribute(attr->name(), attr->value(), attr->name_size(), + attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() { + while (m_begin != m_static_memory) { + char *previous_begin = reinterpret_cast
(align(m_begin)) + ->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use longjmp() function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //!

+ //! User defined allocation functions must have the following forms: + //!
+ //!
void *allocate(std::size_t size); + //!
void free(void *pointer); + //!

+ //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + +private: + + struct header { + char *previous_begin; + }; + + void init() { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) { + std::size_t alignment = ((RAPIDXML_ALIGNMENT + - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) + & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } else { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast(memory); + } + + void *allocate_aligned(std::size_t size) { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast
(pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used +}; + +/////////////////////////////////////////////////////////////////////////// +// XML base + +//! Base class for xml_node and xml_attribute implementing common functions: +//! name(), name_size(), value(), value_size() and parent(). +//! \param Ch Character type to use +template +class xml_base { + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() : + m_name(0), m_value(0), m_parent(0) { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) { + m_name = const_cast(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //!

+ //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) { + m_value = const_cast(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node *parent() const { + return m_parent; + } + +protected: + + // Return empty string + static Ch *nullstr() { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node *m_parent; // Pointer to parent node, or 0 if none + +}; + +//! Class representing attribute node of XML document. +//! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). +//! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. +//! Thus, this text must persist in memory for the lifetime of attribute. +//! \param Ch Character type to use. +template +class xml_attribute: + public xml_base { + + friend class xml_node ; + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document *document() const { + if (xml_node *node = this->parent()) { + while (node->parent()) + node = node->parent(); + return + node->type() == node_document ? + static_cast *>(node) : 0; + } else return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *previous_attribute(const Ch *name = 0, + std::size_t name_size = 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_prev_attribute; attribute; + attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_next_attribute; attribute; + attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return this->m_parent ? m_next_attribute : 0; + } + +private: + + xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + +}; + +/////////////////////////////////////////////////////////////////////////// +// XML node + +//! Class representing a node of XML document. +//! Each node may have associated name and value strings, which are available through name() and value() functions. +//! Interpretation of name and value depends on type of the node. +//! Type of node can be determined by using type() function. +//!

+//! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. +//! Thus, this text must persist in the memory for the lifetime of node. +//! \param Ch Character type to use. +template +class xml_node: + public xml_base { + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) : + m_type(type), m_first_node(0), m_first_attribute(0) { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document *document() const { + xml_node *node = const_cast *>(this); + while (node->parent()) + node = node->parent(); + return + node->type() == node_document ? static_cast *>(node) : + 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *child = m_first_node; child; + child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, + name_size, case_sensitive)) return child; + return 0; + } else return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *child = m_last_node; child; + child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, + name_size, case_sensitive)) return child; + return 0; + } else return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *sibling = m_prev_sibling; sibling; + sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, + name_size, case_sensitive)) return sibling; + return 0; + } else return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *sibling = m_next_sibling; sibling; + sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, + name_size, case_sensitive)) return sibling; + return 0; + } else return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_first_attribute; attribute; + attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_last_attribute; attribute; + attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node *child) { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } else { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node *child) { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } else { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node *where, xml_node *child) { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() { + assert(first_node()); + xml_node *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() { + assert(first_node()); + xml_node *child = m_last_node; + if (child->m_prev_sibling) { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } else m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node *where) { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() { + for (xml_node *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute *attribute) { + assert(attribute && !attribute->parent()); + if (first_attribute()) { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } else { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute *attribute) { + assert(attribute && !attribute->parent()); + if (first_attribute()) { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } else { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute *where, + xml_attribute *attribute) { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() { + assert(first_attribute()); + xml_attribute *attribute = m_first_attribute; + if (attribute->m_next_attribute) { + attribute->m_next_attribute->m_prev_attribute = 0; + } else m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() { + assert(first_attribute()); + xml_attribute *attribute = m_last_attribute; + if (attribute->m_prev_attribute) { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } else m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute *where) { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() { + for (xml_attribute *attribute = first_attribute(); attribute; + attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + +private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + +}; + +/////////////////////////////////////////////////////////////////////////// +// XML document + +//! This class represents root of the DOM hierarchy. +//! It is also an xml_node and a memory_pool through public inheritance. +//! Use parse() function to build a DOM tree from a zero-terminated XML text string. +//! parse() function allocates memory for nodes and attributes by using functions of xml_document, +//! which are inherited from memory_pool. +//! To access root node of the document, use the document itself, as if it was an xml_node. +//! \param Ch Character type to use. +template +class xml_document: + public xml_node, public memory_pool { + +public: + + //! Constructs empty XML document + xml_document() : + xml_node(node_document) { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //!

+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //!

+ //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template + void parse(Ch *text) { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom(text); + + // Parse children + while (1) { + // Skip whitespace before node + skip(text); + if (*text == 0) break; + + // Parse and append new child + if (*text == Ch('<')) { + ++text; // Skip '<' + if (xml_node *node = parse_node(text)) + this->append_node(node); + } else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool::clear(); + } + +private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + } + }; + + // Detect node name character + struct node_name_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + } + }; + + // Detect attribute value character + template + struct attribute_value_pred { + static unsigned char test(Ch ch) { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template + struct attribute_value_pure_pred { + static unsigned char test(Ch ch) { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template + static void insert_coded_character(Ch *&text, unsigned long code) { + if (Flags & parse_no_utf8) { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast(code); + text += 1; + } else { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + text += 1; + } else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xC0); + text += 2; + } else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xE0); + text += 3; + } else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xF0); + text += 4; + } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template + static void skip(Ch *&text) { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template + static Ch *skip_and_expand_character_refs(Ch *&text) { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation + && !(Flags & parse_normalize_whitespace) + && !(Flags & parse_trim_whitespace)) { + skip(text); + return text; + } + + // Use simple skip until first modification is detected + skip(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) { + // Test if replacement is needed + if (src[0] == Ch('&')) { + switch (src[1]) { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') + && src[5] == Ch(';')) { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') + && src[5] == Ch(';')) { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) { + unsigned char digit = + internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) break; + code = code * 16 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } else { + unsigned long code = 0; + src += 2; // Skip &# + while (1) { + unsigned char digit = + internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) break; + code = code * 10 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) { + // Test if condensing is needed + if (whitespace_pred::test(*src)) { + *dest = Ch(' '); + ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template + void parse_bom(Ch *&text) { + // UTF-8? + if (static_cast(text[0]) == 0xEF + && static_cast(text[1]) == 0xBB + && static_cast(text[2]) == 0xBF) { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration ( + xml_node *parse_xml_declaration(Ch *&text) { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip(text); + + // Parse declaration attributes + parse_node_attributes(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template + xml_node *parse_doctype(Ch *&text) { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) { + // Determine character type + switch (*text) { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) { + switch (*text) { + case Ch('['): + ++depth; + break; + case Ch(']'): + --depth; + break; + case 0: + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) { + // Create a new doctype node + xml_node *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } else { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template + xml_node *parse_pi(Ch *&text) { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) { + // Create pi node + xml_node *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } else { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template + Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs(text); + else end = skip_and_expand_character_refs(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) { + if (Flags & parse_normalize_whitespace) { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) --end; + } else { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) { + xml_node *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template + xml_node *parse_cdata(Ch *&text) { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template + xml_node *parse_element(Ch *&text) { + // Create element node + xml_node *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip(text); + + // Parse attributes, if any + parse_node_attributes(text, element); + + // Determine ending type + if (*text == Ch('>')) { + ++text; + parse_node_contents(text, element); + } else if (*text == Ch('/')) { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template + xml_node *parse_node(Ch *&text) { + // Parse proper node type + switch (text[0]) { + + // <... + default: + // Parse and append element node + return parse_element(text); + + // (text); + } else { + // Parse PI + return parse_pi(text); + } + + // (text); + } + break; + + // (text); + } + break; + + // (text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with ')) { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template + void parse_node_contents(Ch *&text, xml_node *node) { + // For all children and text + while (1) { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) { + // Node closing + text += 2; // Skip '(text); + if (!internal::compare(node->name(), node->name_size(), + closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } else { + // No validation, just skip name + skip(text); + } + // Skip remaining whitespace after node name + skip(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } else { + // Child node + ++text; // Skip '<' + if (xml_node *child = parse_node(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data(node, text, contents_start); + goto after_data_node; + // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template + void parse_node_attributes(Ch *&text, xml_node *node) { + // For all attributes + while (attribute_name_pred::test(*text)) { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs, + attribute_value_pure_pred, AttFlags>(text); + else end = skip_and_expand_character_refs, + attribute_value_pure_pred, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip(text); + } + } + +}; + +//! \cond internal +namespace internal { + +// Whitespace (space \n \r \t) +template +const unsigned char lookup_tables::lookup_whitespace[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + +// Node name (anything but space \n \r \t / > ? \0) +template +const unsigned char lookup_tables::lookup_node_name[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) (anything but < \0) +template +const unsigned char lookup_tables::lookup_text[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled +// (anything but < \0 &) +template +const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled +// (anything but < \0 & space \n \r \t) +template +const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute name (anything but space \n \r \t / < > = ? ! \0) +template +const unsigned char lookup_tables::lookup_attribute_name[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with single quote (anything but ' \0) +template +const unsigned char lookup_tables::lookup_attribute_data_1[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with single quote that does not require processing (anything but ' \0 &) +template +const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with double quote (anything but " \0) +template +const unsigned char lookup_tables::lookup_attribute_data_2[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with double quote that does not require processing (anything but " \0 &) +template +const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Digits (dec and hex, 255 denotes end of numeric character reference) +template +const unsigned char lookup_tables::lookup_digits[256] = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 0 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 1 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, + 255, // 3 + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 4 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 5 + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 6 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 7 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 8 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 9 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // A + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // B + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // C + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // D + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // E + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255 // F + }; + +// Upper case conversion +template +const unsigned char lookup_tables::lookup_upcase[256] = { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, + 127, // 7 + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, // 8 + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, // 9 + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, // A + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, // B + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, // C + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, // D + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, // E + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 // F + }; +} +//! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp new file mode 100755 index 0000000..379dcf7 --- /dev/null +++ b/TEEStub/PropertyAccess/rapidxml/rapidxml_iterators.hpp @@ -0,0 +1,151 @@ +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include "rapidxml.hpp" + +namespace rapidxml { + +//! Iterator of child nodes of xml_node +template +class node_iterator { + +public: + + typedef typename xml_node value_type; + typedef typename xml_node &reference; + typedef typename xml_node *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + node_iterator() : + m_node(0) { + } + + node_iterator(xml_node *node) : + m_node(node->first_node()) { + } + + reference operator *() const { + assert(m_node); + return *m_node; + } + + pointer operator->() const { + assert(m_node); + return m_node; + } + + node_iterator& operator++() { + assert(m_node); + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) { + node_iterator tmp = *this; + ++this; + return tmp; + } + + node_iterator& operator--() { + assert(m_node && m_node->previous_sibling()); + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) { + node_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const node_iterator &rhs) { + return m_node == rhs.m_node; + } + + bool operator !=(const node_iterator &rhs) { + return m_node != rhs.m_node; + } + +private: + + xml_node *m_node; + +}; + +//! Iterator of child attributes of xml_node +template +class attribute_iterator { + +public: + + typedef typename xml_attribute value_type; + typedef typename xml_attribute &reference; + typedef typename xml_attribute *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + attribute_iterator() : + m_attribute(0) { + } + + attribute_iterator(xml_node *node) : + m_attribute(node->first_attribute()) { + } + + reference operator *() const { + assert(m_attribute); + return *m_attribute; + } + + pointer operator->() const { + assert(m_attribute); + return m_attribute; + } + + attribute_iterator& operator++() { + assert(m_attribute); + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + attribute_iterator& operator--() { + assert(m_attribute && m_attribute->previous_attribute()); + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const attribute_iterator &rhs) { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator &rhs) { + return m_attribute != rhs.m_attribute; + } + +private: + + xml_attribute *m_attribute; + +}; + +} + +#endif diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp new file mode 100755 index 0000000..8a627e5 --- /dev/null +++ b/TEEStub/PropertyAccess/rapidxml/rapidxml_print.hpp @@ -0,0 +1,426 @@ +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include "rapidxml.hpp" + +// Only include streams if not disabled +#ifndef RAPIDXML_NO_STREAMS +#include +#include +#endif + +namespace rapidxml { + +/////////////////////////////////////////////////////////////////////// +// Printing flags + +const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + +/////////////////////////////////////////////////////////////////////// +// Internal + +//! \cond internal +namespace internal { + +/////////////////////////////////////////////////////////////////////////// +// Internal character operations + +// Copy characters from given range to given output iterator +template +inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) { + while (begin != end) + *out++ = *begin++; + return out; +} + +// Copy characters from given range to given output iterator and expand +// characters into references (< > ' " &) +template +inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, + OutIt out) { + while (begin != end) { + if (*begin == noexpand) { + *out++ = *begin; // No expansion, copy character + } else { + switch (*begin) { + case Ch('<'): + *out++ = Ch('&'); + *out++ = Ch('l'); + *out++ = Ch('t'); + *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); + *out++ = Ch('g'); + *out++ = Ch('t'); + *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); + *out++ = Ch('a'); + *out++ = Ch('p'); + *out++ = Ch('o'); + *out++ = Ch('s'); + *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); + *out++ = Ch('q'); + *out++ = Ch('u'); + *out++ = Ch('o'); + *out++ = Ch('t'); + *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); + *out++ = Ch('a'); + *out++ = Ch('m'); + *out++ = Ch('p'); + *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; +} + +// Fill given output iterator with repetitions of the same character +template +inline OutIt fill_chars(OutIt out, int n, Ch ch) { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; +} + +// Find character +template +inline bool find_char(const Ch *begin, const Ch *end) { + while (begin != end) + if (*begin++ == ch) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////// +// Internal printing operations + +// Print node +template +inline OutIt print_node(OutIt out, const xml_node *node, int flags, + int indent) { + // Print proper node type + switch (node->type()) { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; + + // Return modified iterator + return out; +} + +// Print children of the node +template +inline OutIt print_children(OutIt out, const xml_node *node, int flags, + int indent) { + for (xml_node *child = node->first_node(); child; + child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; +} + +// Print attributes of the node +template +inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) { + for (xml_attribute *attribute = node->first_attribute(); attribute; + attribute = attribute->next_attribute()) { + if (attribute->name() && attribute->value()) { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), + attribute->name() + attribute->name_size(), out); + *out = Ch('='), ++out; + // Print attribute value using appropriate quote type + if (find_char(attribute->value(), + attribute->value() + attribute->value_size())) { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), + attribute->value() + attribute->value_size(), Ch('"'), out); + *out = Ch('\''), ++out; + } else { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), + attribute->value() + attribute->value_size(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + return out; +} + +// Print data node +template +inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_data); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), + Ch(0), out); + return out; +} + +// Print data node +template +inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_cdata); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); + ++out; + *out = Ch('!'); + ++out; + *out = Ch('['); + ++out; + *out = Ch('C'); + ++out; + *out = Ch('D'); + ++out; + *out = Ch('A'); + ++out; + *out = Ch('T'); + ++out; + *out = Ch('A'); + ++out; + *out = Ch('['); + ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch(']'); + ++out; + *out = Ch(']'); + ++out; + *out = Ch('>'); + ++out; + return out; +} + +// Print element node +template +inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value_size() == 0 && !node->first_node()) { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } else { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // Test if node contains a single data node only (and no other nodes) + xml_node *child = node->first_node(); + if (!child) { + // If node has no children, only print its value without indenting + out = copy_and_expand_chars(node->value(), + node->value() + node->value_size(), Ch(0), out); + } else if (child->next_sibling() == 0 && child->type() == node_data) { + // If node has a sole data child, only print its value without indenting + out = copy_and_expand_chars(child->value(), + child->value() + child->value_size(), Ch(0), out); + } else { + // Print all children with full indenting + if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch('>'), ++out; + } + return out; +} + +// Print declaration node +template +inline OutIt print_declaration_node(OutIt out, const xml_node *node, + int flags, int indent) { + // Print declaration start + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; +} + +// Print comment node +template +inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_comment); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; +} + +// Print doctype node +template +inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_doctype); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('>'), ++out; + return out; +} + +// Print pi node +template +inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_pi); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; +} + +} +//! \endcond + +/////////////////////////////////////////////////////////////////////////// +// Printing + +//! Prints XML to given output iterator. +//! \param out Output iterator to print to. +//! \param node Node to be printed. Pass xml_document to print entire document. +//! \param flags Flags controlling how XML is printed. +//! \return Output iterator pointing to position immediately after last character of printed text. +template +inline OutIt print(OutIt out, const xml_node &node, int flags = 0) { + return internal::print_node(out, &node, flags, 0); +} + +#ifndef RAPIDXML_NO_STREAMS + +//! Prints XML to given output stream. +//! \param out Output stream to print to. +//! \param node Node to be printed. Pass xml_document to print entire document. +//! \param flags Flags controlling how XML is printed. +//! \return Output stream. +template +inline std::basic_ostream &print(std::basic_ostream &out, + const xml_node &node, int flags = 0) { + print(std::ostream_iterator < Ch > (out), node, flags); + return out; +} + +//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. +//! \param out Output stream to print to. +//! \param node Node to be printed. +//! \return Output stream. +template +inline std::basic_ostream &operator <<(std::basic_ostream &out, + const xml_node &node) { + return print(out, node); +} + +#endif + +} + +#endif diff --git a/TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp b/TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp new file mode 100755 index 0000000..c95e1e5 --- /dev/null +++ b/TEEStub/PropertyAccess/rapidxml/rapidxml_utils.hpp @@ -0,0 +1,111 @@ +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include "rapidxml.hpp" +#include +#include +#include +#include + +namespace rapidxml { + +//! Represents data loaded from a file +template +class file { + +public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) { + using namespace std; + + // Open stream + basic_ifstream stream(filename, ios::binary); + if (!stream) throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream &stream) { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator < Ch > (stream), + istreambuf_iterator()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const { + return m_data.size(); + } + +private: + + std::vector m_data; // File data + +}; + +//! Counts children of node. Time complexity is O(n). +//! \return Number of children of node +template +inline std::size_t count_children(xml_node *node) { + xml_node *child = node->first_node(); + std::size_t count = 0; + while (child) { + ++count; + child = child->next_sibling(); + } + return count; +} + +//! Counts attributes of node. Time complexity is O(n). +//! \return Number of attributes of node +template +inline std::size_t count_attributes(xml_node *node) { + xml_attribute *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) { + ++count; + attr = attr->next_attribute(); + } + return count; +} + +} + +#endif diff --git a/TEEStub/TACommands/CommandBase.cpp b/TEEStub/TACommands/CommandBase.cpp new file mode 100755 index 0000000..3ededa4 --- /dev/null +++ b/TEEStub/TACommands/CommandBase.cpp @@ -0,0 +1,63 @@ +/* + * ===================================================================================== + * + * Filename: BaseCommand.cpp + * + * Description: BaseCommand class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +unsigned int CommandBase::sessionContextContainer = 0; +void *CommandBase::sessionContext = &CommandBase::sessionContextContainer; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor for Base command class where command gets initialized + * @param acommand[in] command enum value + */ +CommandBase::CommandBase(SIM_COMMAND acommand) : + command(acommand), sessionID(0) { +} + +/** + * Destructor + */ +CommandBase::~CommandBase() { +} + +/** + * + * @return returns command ID of the derived command class. + */ +SIM_COMMAND CommandBase::getCommandID() const { + return command; +} + +/** + * Overridden by CommandRequestCancel only which returns true. + * Else, all other derived classes shall NOT override this function. + * @return true if derived class is CommandRequestCancel and when overridden. + * Else false by default. + */ +bool CommandBase::isCancelCommand() const { + return false; +} diff --git a/TEEStub/TACommands/CommandBase.h b/TEEStub/TACommands/CommandBase.h new file mode 100755 index 0000000..d7048d3 --- /dev/null +++ b/TEEStub/TACommands/CommandBase.h @@ -0,0 +1,87 @@ +/* + * ===================================================================================== + * + * Filename: BaseCommand.h + * + * Description: BaseCommand header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef BASECOMMAND_H_ +#define BASECOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_sim_command.h" +#include "tee_internal_api.h" +#include "log.h" +#include "boost/shared_ptr.hpp" +#include +#include + +extern void* sessionContext; +extern bool _allowPropertyAccess; + +#ifndef TOGGLE_PROPERTY_ACCESS +#define TOGGLE_PROPERTY_ACCESS {_allowPropertyAccess = !_allowPropertyAccess;} +#endif +/** + * @class CommandBase + * Base class for all commands. + */ + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandBase { +protected: + SIM_COMMAND command; +public: + /** + * TODO: remove sessionID, this is redundant but session = 0 is + * used for commands which do not use session id, like CREATE and DESTROY + * Use a special slot for them + * + */ + uint32_t sessionID; +private: + /** + * The Trusted Application instance can register a session data pointer by + * setting *sessionContext. The value of this pointer is not interpreted by + * the Framework, and is simply passed back to other TA_ functions within + * this session. Note that *sessionContext may be set with a pointer to a + * memory allocated by the Trusted Application instance or with anything + * else, such as an integer, a handle, etc. The Framework will not automatically + * free *sessionContext when the session is closed; the Trusted Application + * instance is responsible for freeing memory if required. + * + */ + static unsigned int sessionContextContainer; +public: + CommandBase(SIM_COMMAND acommand); + virtual std::string getCommandUID() const = 0; + virtual TEE_Result execute() = 0; + virtual void getSerializedData(unsigned char *data, unsigned int &size) = 0; + virtual ~CommandBase(); + virtual bool isCancelCommand() const; + SIM_COMMAND getCommandID() const; + /** + * sessionContext: A pointer to a variable that can be filled by the + * Trusted Application instance with an opaque void* data pointer + */ + static void *sessionContext; +}; +typedef boost::shared_ptr CommandBasePtr; +typedef std::string CommandUID; + +#endif /* BASECOMMAND_H_ */ diff --git a/TEEStub/TACommands/CommandCloseSession.cpp b/TEEStub/TACommands/CommandCloseSession.cpp new file mode 100755 index 0000000..5f9cf27 --- /dev/null +++ b/TEEStub/TACommands/CommandCloseSession.cpp @@ -0,0 +1,80 @@ +/* + * ===================================================================================== + * + * Filename: CommandCloseSession.cpp + * + * Description: CommandCloseSession class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandCloseSession.h" +#include + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor + * @param data[in] Initialization data + */ +CommandCloseSession::CommandCloseSession(CloseTASessionData data) : + CommandBase(CLOSESESSION) { + this->data = data; + sessionID = data.sessionID; +} + +/** + * Executes command close session + * @return TEE_SUCCESS + */ +TEE_Result CommandCloseSession::execute() { + TOGGLE_PROPERTY_ACCESS; + TA_CloseSessionEntryPoint(&sessionContext); + LOGD(TEE_STUB, "TA_CloseSessionEntryPoint done"); + TOGGLE_PROPERTY_ACCESS; + return TEE_SUCCESS; +} + +/** + * Returns this command's UID in the format "sessionID:commandID". + * If commandID is not relevant for this command, it is set to 0. + * For create and destroy commands, it is "0:0". SessionID 0 is reserved. + * @return this command's UID + */ +std::string CommandCloseSession::getCommandUID() const { + std::stringstream ss; + ss << data.sessionID; + ss << ":"; + ss << "0"; + return ss.str(); +} + +/** + * Destructor + */ +CommandCloseSession::~CommandCloseSession() { +} + +/** + * Serializes this object data of CommandCloseSession + * @param data[out] serialized object data + * @param size[out] size in bytes + */ +void CommandCloseSession::getSerializedData(unsigned char *data, + unsigned int &size) { + data[0] = command; + memcpy(&data[1], (unsigned char*)&this->data, sizeof(CloseTASessionData)); + size = sizeof(CloseTASessionData); +} diff --git a/TEEStub/TACommands/CommandCloseSession.h b/TEEStub/TACommands/CommandCloseSession.h new file mode 100755 index 0000000..a8d9186 --- /dev/null +++ b/TEEStub/TACommands/CommandCloseSession.h @@ -0,0 +1,45 @@ +/* + * ===================================================================================== + * + * Filename: CommandCloseSession.h + * + * Description: CommandCloseSession header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDCLOSESESSION_H_ +#define COMMANDCLOSESESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class CommandCloseSession + * Implements command to close a session + */ +class CommandCloseSession: + public CommandBase { +public: + CloseTASessionData data; + void getSerializedData(unsigned char *data, unsigned int &size); + CommandCloseSession(CloseTASessionData data); + TEE_Result execute(); + std::string getCommandUID() const; + virtual ~CommandCloseSession(); +}; + +#endif /* COMMANDCLOSESESSION_H_ */ diff --git a/TEEStub/TACommands/CommandCreateEntryPoint.cpp b/TEEStub/TACommands/CommandCreateEntryPoint.cpp new file mode 100755 index 0000000..a411a93 --- /dev/null +++ b/TEEStub/TACommands/CommandCreateEntryPoint.cpp @@ -0,0 +1,71 @@ +/* + * ===================================================================================== + * + * Filename: CommandCreateEntryPoint.cpp + * + * Description: CommandCreateEntryPoint class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandCreateEntryPoint.h" +#include + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +CommandCreateEntryPoint::CommandCreateEntryPoint(CreateTAEntryPointData data) : + CommandBase(CREATE) { + this->data = data; + sessionID = data.sessionID; +} + +/** + * Execute this command by calling TA_CreateEntryPoint + * @return return value from TA_CreateEntryPoint + */ +TEE_Result CommandCreateEntryPoint::execute() { + data.returnValue = TA_CreateEntryPoint(); + LOGD(TEE_STUB, "TA_CreateEntryPoint done"); + return data.returnValue; +} + +/** + * Returns this command's UID in the format "sessionID:commandID". + * If commandID is not relevant for this command, it is set to 0. + * For create and destroy commands, it is "0:0". SessionID 0 is reserved. + * @return this command's UID + */ +std::string CommandCreateEntryPoint::getCommandUID() const { + std::stringstream ss; + ss << "0"; + ss << ":"; + ss << "0"; + return ss.str(); +} + +CommandCreateEntryPoint::~CommandCreateEntryPoint() { +} + +/** + * Serializes this object data of CommandCreateEntryPoint + * @param data[out] serialized object data + * @param size[out] size in bytes + */ +void CommandCreateEntryPoint::getSerializedData(unsigned char *data, + unsigned int &size) { + data[0] = command; + memcpy(&data[1], (unsigned char*)&this->data, sizeof(CreateTAEntryPointData)); + size = sizeof(CreateTAEntryPointData); +} diff --git a/TEEStub/TACommands/CommandCreateEntryPoint.h b/TEEStub/TACommands/CommandCreateEntryPoint.h new file mode 100755 index 0000000..e1ae0b0 --- /dev/null +++ b/TEEStub/TACommands/CommandCreateEntryPoint.h @@ -0,0 +1,45 @@ +/* + * ===================================================================================== + * + * Filename: CommandCreateEntryPoint.h + * + * Description: CommandCreateEntryPoint header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef COMMANDCREATEENTRYPOINT_H_ +#define COMMANDCREATEENTRYPOINT_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" +#include "tee_sim_command.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class CommandCreateEntryPoint + * Implements command to call TA_CreateEntryPoint() of TA + */ +class CommandCreateEntryPoint: + public CommandBase { +public: + CreateTAEntryPointData data; + TEE_Result execute(); + std::string getCommandUID() const; + void getSerializedData(unsigned char *data, unsigned int &size); + CommandCreateEntryPoint(CreateTAEntryPointData data); + virtual ~CommandCreateEntryPoint(); +}; + +#endif /* COMMANDCREATEENTRYPOINT_H_ */ diff --git a/TEEStub/TACommands/CommandDestroyEntryPoint.cpp b/TEEStub/TACommands/CommandDestroyEntryPoint.cpp new file mode 100755 index 0000000..998ff32 --- /dev/null +++ b/TEEStub/TACommands/CommandDestroyEntryPoint.cpp @@ -0,0 +1,74 @@ +/* + * ===================================================================================== + * + * Filename: CommandDestroyEntryPoint.cpp + * + * Description: CommandDestroyEntryPoint class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandDestroyEntryPoint.h" +#include + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +CommandDestroyEntryPoint::CommandDestroyEntryPoint(DestroyTAEntryPointData data) : + CommandBase(DESTROY) { + this->data = data; + sessionID = data.sessionID; +} + +//TODO: Handle exit of TA instance in a clean way +/** + * Execute this command by calling TA_DestroyEntryPoint + * @return Does not return, directly exits this TA instance. + */ +TEE_Result CommandDestroyEntryPoint::execute() { + TA_DestroyEntryPoint(); + LOGD(TEE_STUB, "TA_DestroyEntryPoint done"); + exit(0); + return TEE_SUCCESS; +} + +/** + * Returns this command's UID in the format "sessionID:commandID". + * If commandID is not relevant for this command, it is set to 0. + * For create and destroy commands, it is "0:0". SessionID 0 is reserved. + * @return this command's UID + */ +std::string CommandDestroyEntryPoint::getCommandUID() const { + std::stringstream ss; + ss << "0"; + ss << ":"; + ss << "0"; + return ss.str(); +} + +CommandDestroyEntryPoint::~CommandDestroyEntryPoint() { +} + +/** + * Serializes this object data of CommandDestroyEntryPoint + * @param data[out] serialized object data + * @param size[out] size in bytes + */ +void CommandDestroyEntryPoint::getSerializedData(unsigned char *data, + unsigned int &size) { + data[0] = command; + memcpy(&data[1], (unsigned char*)&this->data, + sizeof(DestroyTAEntryPointData)); + size = sizeof(DestroyTAEntryPointData); +} diff --git a/TEEStub/TACommands/CommandDestroyEntryPoint.h b/TEEStub/TACommands/CommandDestroyEntryPoint.h new file mode 100755 index 0000000..5f1d48a --- /dev/null +++ b/TEEStub/TACommands/CommandDestroyEntryPoint.h @@ -0,0 +1,44 @@ +/* + * ===================================================================================== + * + * Filename: CommandDestroyEntryPoint.h + * + * Description: CommandDestroyEntryPoint header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef COMMANDDESTROYENTRYPOINT_H_ +#define COMMANDDESTROYENTRYPOINT_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class CommandDestroyEntryPoint + * Implements command to call TA_DestroyEntryPoint() of TA + */ +class CommandDestroyEntryPoint: + public CommandBase { +public: + TEE_Result execute(); + DestroyTAEntryPointData data; + void getSerializedData(unsigned char *data, unsigned int &size); + std::string getCommandUID() const; + CommandDestroyEntryPoint(DestroyTAEntryPointData data); + virtual ~CommandDestroyEntryPoint(); +}; + +#endif /* COMMANDDESTROYENTRYPOINT_H_ */ diff --git a/TEEStub/TACommands/CommandInvoke.cpp b/TEEStub/TACommands/CommandInvoke.cpp new file mode 100755 index 0000000..86a22cb --- /dev/null +++ b/TEEStub/TACommands/CommandInvoke.cpp @@ -0,0 +1,99 @@ +/* + * ===================================================================================== + * + * Filename: CommandOperation.cpp + * + * Description: CommandOperation class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandInvoke.h" +#include "SharedMemoryMap.h" +#include +#include +#include +#include +using namespace std; + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define PAGE_SIZE 0x1000 +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +CommandInvoke::CommandInvoke(InvokeTACommandData data) : + CommandBase(INVOKECOMMAND) { + this->data = data; + sessionID = data.sessionID; +} + +/** + * Execute command by calling TA_InvokeCommandEntryPoint() + * @return return value from TA_InvokeCommandEntryPoint() or TEE_ERROR_OUT_OF_MEMORY + * when shared memory cannot be allocated. + */ +TEE_Result CommandInvoke::execute() { + bool sharedResult = true; + + TOGGLE_PROPERTY_ACCESS; + sharedResult = SharedMemoryMap::allocateSharedMemory(data.op); + if (sharedResult) { + data.returnValue = TA_InvokeCommandEntryPoint(&sessionContext, + data.commandID, data.op.paramTypes, data.op.params); + LOGD(TEE_STUB, "TA_InvokeCommandEntryPoint done"); + } else { + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; + data.returnValue = TEE_ERROR_OUT_OF_MEMORY; + } + sharedResult = SharedMemoryMap::deleteSharedMemory(data.op); + if (!sharedResult) { + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; + data.returnValue = TEE_ERROR_OUT_OF_MEMORY; + } + + TOGGLE_PROPERTY_ACCESS; + return data.returnValue; +} + +/** + * Returns this command's UID in the format "sessionID:commandID". + * If commandID is not relevant for this command, it is set to 0. + * For create and destroy commands, it is "0:0". SessionID 0 is reserved. + * @return this command's UID + */ +std::string CommandInvoke::getCommandUID() const { + std::stringstream ss; + ss << data.sessionID; + ss << ":"; + ss << data.op.operationID; + return ss.str(); +} + +CommandInvoke::~CommandInvoke() { +} + +/** + * Serializes this object data of CommandInvoke + * @param data[out] serialized object data + * @param size[out] size in bytes + */ +void CommandInvoke::getSerializedData(unsigned char *data, unsigned int &size) { + data[0] = command; + memcpy(&data[1], (unsigned char*)&this->data, sizeof(InvokeTACommandData)); + size = sizeof(InvokeTACommandData); +} diff --git a/TEEStub/TACommands/CommandInvoke.h b/TEEStub/TACommands/CommandInvoke.h new file mode 100755 index 0000000..29d0a01 --- /dev/null +++ b/TEEStub/TACommands/CommandInvoke.h @@ -0,0 +1,44 @@ +/* + * ===================================================================================== + * + * Filename: CommandOperation.h + * + * Description: CommandOperation header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef COMMANDOPERATION_H_ +#define COMMANDOPERATION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class CommandInvoke + * Implements command to call TA_InvokeCommandEntryPoint() of TA + */ +class CommandInvoke: + public CommandBase { +public: + InvokeTACommandData data; + CommandInvoke(InvokeTACommandData data); + TEE_Result execute(); + std::string getCommandUID() const; + void getSerializedData(unsigned char *data, unsigned int &size); + virtual ~CommandInvoke(); +}; + +#endif /* COMMANDOPERATION_H_ */ diff --git a/TEEStub/TACommands/CommandOpenSession.cpp b/TEEStub/TACommands/CommandOpenSession.cpp new file mode 100755 index 0000000..468066e --- /dev/null +++ b/TEEStub/TACommands/CommandOpenSession.cpp @@ -0,0 +1,91 @@ +/* + * ===================================================================================== + * + * Filename: CommandOpenSession.cpp + * + * Description: CommandOpenSession class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandOpenSession.h" +#include "SharedMemoryMap.h" +#include +#include + +using namespace std; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +CommandOpenSession::CommandOpenSession(OpenTASessionData data) : + CommandBase(OPENSESSION) { + this->data = data; + sessionID = data.sessionID; +} + +CommandOpenSession::~CommandOpenSession() { +} + +/** + * Calls API TA_OpenSessionEntryPoint + * @return result returned from TA_OpenSessionEntryPoint + */ +TEE_Result CommandOpenSession::execute() { + // If param. type is of memory reference type then allocate shared memory + bool sharedResult = true; + TOGGLE_PROPERTY_ACCESS; + sharedResult = SharedMemoryMap::allocateSharedMemory(data.op); + if (sharedResult) { + data.returnValue = TA_OpenSessionEntryPoint(data.op.paramTypes, + data.op.params, &sessionContext); + LOGD(TEE_STUB, "TA_OpenSessionEntryPoint done"); + } else { + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; + data.returnValue = TEE_ERROR_OUT_OF_MEMORY; + } + sharedResult = SharedMemoryMap::deleteSharedMemory(data.op); + if (!sharedResult) { + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; + data.returnValue = TEE_ERROR_OUT_OF_MEMORY; + } + TOGGLE_PROPERTY_ACCESS; + return data.returnValue; +} + +/** + * Returns this command's UID in the format "sessionID:commandID". + * If commandID is not relevant for this command, it is set to 0. + * For create and destroy commands, it is "0:0". SessionID 0 is reserved. + * @return this command's UID + */ +std::string CommandOpenSession::getCommandUID() const { + std::stringstream ss; + ss << data.sessionID; + ss << ":"; + ss << data.op.operationID; + return ss.str(); +} + +/** + * Serializes this object data of CommandOpenSession + * @param data[out] serialized object data + * @param size[out] size in bytes + */ +void CommandOpenSession::getSerializedData(unsigned char *data, + unsigned int &size) { + data[0] = command; + memcpy(&data[1], (unsigned char*)&this->data, sizeof(OpenTASessionData)); + size = sizeof(OpenTASessionData); +} diff --git a/TEEStub/TACommands/CommandOpenSession.h b/TEEStub/TACommands/CommandOpenSession.h new file mode 100755 index 0000000..0ff0cd0 --- /dev/null +++ b/TEEStub/TACommands/CommandOpenSession.h @@ -0,0 +1,44 @@ +/* + * ===================================================================================== + * + * Filename: CommandOpenSession.h + * + * Description: CommandOpenSession header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef COMMANDOPENSESSION_H_ +#define COMMANDOPENSESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class CommandOpenSession + * Implements command to call TA_OpenSessionEntryPoint() of TA + */ +class CommandOpenSession: + public CommandBase { +public: + OpenTASessionData data; + CommandOpenSession(OpenTASessionData data); + virtual ~CommandOpenSession(); + TEE_Result execute(); + std::string getCommandUID() const; + void getSerializedData(unsigned char *data, unsigned int &size); +}; + +#endif /* COMMANDOPENSESSION_H_ */ diff --git a/TEEStub/TACommands/CommandRequestCancel.cpp b/TEEStub/TACommands/CommandRequestCancel.cpp new file mode 100755 index 0000000..63291a4 --- /dev/null +++ b/TEEStub/TACommands/CommandRequestCancel.cpp @@ -0,0 +1,112 @@ +/* + * ===================================================================================== + * + * Filename: CommandRequestCancel.cpp + * + * Description: CommandRequestCancel class + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +//Cancellation vector which holds the cancellation requests +std::vector CommandRequestCancel::cancelVector; +boost::mutex CommandRequestCancel::vectorMutex; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor + * @param data + */ +CommandRequestCancel::CommandRequestCancel(RequestTACancelData data) : + CommandBase(REQCANCEL) { + this->data = data; + sessionID = data.sessionID; +} + +/** + * Adds this request of cancellation of a command to cancellation vector. + * @return TEE_SUCCESS + */ +TEE_Result CommandRequestCancel::execute() { + // Set return values + data.returnValue = TEE_ERROR_CANCEL; + data.returnOrigin = TEE_ORIGIN_TEE; + // Push the cancel request into cancellation vector + vectorMutex.lock(); + cancelVector.push_back(shared_from_this()); + vectorMutex.unlock(); + return TEE_SUCCESS; +} + +CommandRequestCancel::~CommandRequestCancel() { +} + +/** + * Serializes this object data of CommandRequestCancel + * @param data[out] serialized object data + * @param size[out] size in bytes + */ +void CommandRequestCancel::getSerializedData(unsigned char *data, + unsigned int &size) { + data[0] = command; + memcpy(&data[1], (unsigned char*)&this->data, sizeof(RequestTACancelData)); + size = sizeof(RequestTACancelData); +} + +/** + * Returns UID of command to be cancelled in the format "sessionID:commandID". + * @return this command's UID + */ +std::string CommandRequestCancel::getCommandUID() const { + std::stringstream ss; + ss << data.sessionID; + ss << ":"; + ss << data.operationID; + return ss.str(); +} + +/** + * Checks if a given task identified by sessionID and operationID. + * When a given task is found, it is removed from cancellation vector. + * @param sessionID Session ID + * @param operationID Operation ID + * @return shared_ptr to CommandRequestCancelPtr + */ +CommandRequestCancelPtr CommandRequestCancel::isCancelled(CommandUID uid) { + bool found = false; + CommandRequestCancelPtr ptr; // Uninitialized shared pointer + std::vector::iterator itr; + vectorMutex.lock(); + for (itr = cancelVector.begin(); cancelVector.end() != itr; itr++) { + if (itr->get()->getCommandUID() == uid) { + found = true; + break; + } + } + vectorMutex.unlock(); + if (found) { + ptr = *itr; + // If cancellation request has come then remove the entry from vector + cancelVector.erase(itr); + } + return ptr; +} diff --git a/TEEStub/TACommands/CommandRequestCancel.h b/TEEStub/TACommands/CommandRequestCancel.h new file mode 100755 index 0000000..797911e --- /dev/null +++ b/TEEStub/TACommands/CommandRequestCancel.h @@ -0,0 +1,63 @@ +/* + * ===================================================================================== + * + * Filename: CommandRequestCancel.h + * + * Description: CommandRequestCancel header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TACOMMANDS_COMMANDREQUESTCANCEL_H_ +#define TACOMMANDS_COMMANDREQUESTCANCEL_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandRequestCancel; +typedef boost::shared_ptr CommandRequestCancelPtr; + +/** + * @class CommandRequestCancel + * Implements command to cancel pending TA entry points in the task execution queue + * (Open session and invoke command only) OR set cancellation flag for running task. + * This is the only class to override function "isCancelCommand" which returns true. + */ +class CommandRequestCancel: + public CommandBase, public boost::enable_shared_from_this< + CommandRequestCancel> { +private: + static std::vector cancelVector; + static boost::mutex vectorMutex; +public: + RequestTACancelData data; + CommandRequestCancel(RequestTACancelData data); + TEE_Result execute(); + std::string getCommandUID() const; + void getSerializedData(unsigned char *data, unsigned int &size); + virtual ~CommandRequestCancel(); +public: + static CommandRequestCancelPtr isCancelled(CommandUID); + bool isCancelCommand() const { + return true; + } +}; + +#endif /* TACOMMANDS_COMMANDREQUESTCANCEL_H_ */ diff --git a/TEEStub/TACommands/MakeCommand.cpp b/TEEStub/TACommands/MakeCommand.cpp new file mode 100755 index 0000000..e206c36 --- /dev/null +++ b/TEEStub/TACommands/MakeCommand.cpp @@ -0,0 +1,119 @@ +/* + * ===================================================================================== + * + * Filename: MakeCommand.cpp + * + * Description: MakeCommand class + * + * Version: 1.0 + * Created: 14 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "MakeCommand.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Creates a command object based on the type of command passed in + * @param command name of command from enum SIM_COMMAND + * @param data pointer to structure defining the command in SIM_COMMAND + */ +CommandBasePtr MakeCommand::getCommand(SIM_COMMAND simcommand, void* simdata) { + + CommandBasePtr command; + switch (simcommand) { + case CREATE: { + CreateTAEntryPointData data; + data = *(reinterpret_cast(simdata)); + command = CommandBasePtr(new CommandCreateEntryPoint(data)); + break; + } + case OPENSESSION: { + OpenTASessionData data; + data = *(reinterpret_cast(simdata)); + command = CommandBasePtr(new CommandOpenSession(data)); + break; + } + case INVOKECOMMAND: { + InvokeTACommandData data; + data = *(reinterpret_cast(simdata)); + command = CommandBasePtr(new CommandInvoke(data)); + break; + } + case CLOSESESSION: { + CloseTASessionData data; + data = *(reinterpret_cast(simdata)); + command = CommandBasePtr(new CommandCloseSession(data)); + break; + } + case DESTROY: { + DestroyTAEntryPointData data; + data = *(reinterpret_cast(simdata)); + command = CommandBasePtr(new CommandDestroyEntryPoint(data)); + break; + } + case REQCANCEL: { + RequestTACancelData data; + data = *(reinterpret_cast(simdata)); + command = CommandBasePtr(new CommandRequestCancel(data)); + break; + } + default: { + command.reset(); + break; + } + } + return command; +} + +MakeCommand::~MakeCommand() { + +} + +/** + * Calculates size of payload expected based on command received + * @param command SIM_COMMAND to be executed on TA + * @return size of payload in bytes based on command. + * A return size of zero means invalid command. For a valid command + * return size will always be positive integer. + * + */ +int MakeCommand::getCommandPayloadSize(SIM_COMMAND command) { + + int size = -1; + switch (command) { + case CREATE: + size = sizeof(CreateTAEntryPointData); + break; + case OPENSESSION: + size = sizeof(OpenTASessionData); + break; + case INVOKECOMMAND: + size = sizeof(InvokeTACommandData); + break; + case CLOSESESSION: + size = sizeof(CloseTASessionData); + break; + case DESTROY: + size = sizeof(DestroyTAEntryPointData); + break; + case REQCANCEL: + size = sizeof(RequestTACancelData); + break; + default: + size = -1; + break; + } + return size; +} diff --git a/TEEStub/TACommands/MakeCommand.h b/TEEStub/TACommands/MakeCommand.h new file mode 100755 index 0000000..ce735dd --- /dev/null +++ b/TEEStub/TACommands/MakeCommand.h @@ -0,0 +1,53 @@ +/* + * ===================================================================================== + * + * Filename: MakeCommand.h + * + * Description: MakeCommand header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef MAKECOMMAND_H_ +#define MAKECOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandCloseSession.h" +#include "CommandCreateEntryPoint.h" +#include "CommandDestroyEntryPoint.h" +#include "CommandInvoke.h" +#include "CommandOpenSession.h" +#include "CommandRequestCancel.h" +#include "tee_sim_command.h" +#include "boost/shared_ptr.hpp" +#include + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class MakeCommand + * Creates instances of all available commands based on parsing of socket stream + * done by TaskQueuedStrategy. Commands are sent by Simulator daemon. + * This class just creates instances of commands and does not parse socket stream. + */ +class MakeCommand { +private: + MakeCommand(); +public: + static CommandBasePtr getCommand(SIM_COMMAND command, void* data); + static int getCommandPayloadSize(SIM_COMMAND command); + virtual ~MakeCommand(); +}; + +#endif /* MAKECOMMAND_H_ */ diff --git a/TEEStub/TACommands/SharedMemoryMap.cpp b/TEEStub/TACommands/SharedMemoryMap.cpp new file mode 100755 index 0000000..0122085 --- /dev/null +++ b/TEEStub/TACommands/SharedMemoryMap.cpp @@ -0,0 +1,160 @@ +/* + * ===================================================================================== + * + * Filename: SharedMemoryMap.cpp + * + * Description: SharedMemoryMap class + * + * Version: 1.0 + * Created: 28 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "SharedMemoryMap.h" +#include +#include +#include +using namespace std; + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define PAGE_SIZE 0x1000 +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +map SharedMemoryMap::shmMap; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Adds a key to a map + * @param key[in] Shared memory key + * @param pBuffer[in] Pointer to shared memory + */ +void SharedMemoryMap::addToMap(const uint32_t key, void* pBuffer) { + shmMap[key] = pBuffer; +} + +/** + * Deletes a key from map thereby detaching shared memory. + * @param key Shared memory key to be deleted + * @return true if successfully detached else false. + */ +bool SharedMemoryMap::deleteFromMap(uint32_t key) { + map::iterator it = shmMap.find(key); + if (it != shmMap.end()) { + if (-1 != shmdt(it->second)) { + shmMap.erase(it); + return true; + } else return false; + } + return false; +} + +/** + * Allocates shared memory from a pre-shared key + * @param op Operation values which contain param types and params. + * @return true if shared memory was successfully created else false. + */ +bool SharedMemoryMap::allocateSharedMemory(Operation &op) { + bool sharedResult = true; + for (int i = 0; i < 4; i++) { + uint32_t type = ((op.paramTypes) >> (8 * i)) & 0x7f; + // If not of value type, then has to be of memory reference type. + if ((type != TEE_PARAM_TYPE_VALUE_INPUT) + && (type != TEE_PARAM_TYPE_VALUE_OUTPUT) + && (type != TEE_PARAM_TYPE_VALUE_INOUT) + && (type != TEE_PARAM_TYPE_NONE)) { + uint32_t size = op.params[i].memref.size; + uint32_t shmid = shmget(op.shmID[i], size, 0666); + + //LOGD(TEE_STUB, "SHM KEY: %d SHM ID: %d", op.shmID[i], shmid); + /* Allocate page aligned buffer */ + if (size < PAGE_SIZE) { + size = PAGE_SIZE; + } else if (size & (PAGE_SIZE - 1)) { + size = (size & ~(PAGE_SIZE - 1)) + PAGE_SIZE; + } + size = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + op.params[i].memref.buffer = (void*)shmat(shmid, NULL, 0); + if (op.params[i].memref.buffer == (void*)-1) { + LOGE(TEE_STUB, "shmat failed"); + sharedResult = false; + } + if (!op.params[i].memref.buffer) { + LOGE(TEE_STUB, "allocate failed"); + sharedResult = false; + } + //memset(op.params[i].memref.buffer, 0x00, size); + + // Add shared memory allocated to shared memory map so that + // it can be detached on closing the sessions or exiting the TA + SharedMemoryMap::addToMap(op.shmID[i], op.params[i].memref.buffer); + } + } + return sharedResult; +} + +/** + * De-allocates shared memory from a pre-shared key + * @param op Operation values which contain param types and params. + * @return true if shared memory was successfully created else false. + */ +bool SharedMemoryMap::deleteSharedMemory(Operation &op) { + bool sharedResult = true; + for (int i = 0; i < 4; i++) { + uint32_t type = ((op.paramTypes) >> (8 * i)) & 0x7f; + // If not of value type, then has to be of memory reference type. + if ((type != TEE_PARAM_TYPE_VALUE_INPUT) + && (type != TEE_PARAM_TYPE_VALUE_OUTPUT) + && (type != TEE_PARAM_TYPE_VALUE_INOUT) + && (type != TEE_PARAM_TYPE_NONE)) { + if (!op.params[i].memref.buffer) { + LOGE(TEE_STUB, "de-allocate failed"); + sharedResult = false; + } + // Add shared memory allocated to shared memory map so that + // it can be detached on closing the sessions or exiting the TA + SharedMemoryMap::deleteFromMap(op.shmID[i]); + } + } + return sharedResult; +} + +/** + * Deletes all allocated shared memory for this TA + * @return true if all shared memories allocated were successfully + * deleted, else false. + */ +bool SharedMemoryMap::deleteAllSharedMemory() { + bool sharedResult = true; + for (map::iterator it = shmMap.begin(); it != shmMap.end(); + it++) { + if (-1 == shmdt(it->second)) { + sharedResult = false; + } + } + return sharedResult; +} + +bool deleteAllSharedMemory() { + return SharedMemoryMap::deleteAllSharedMemory(); +} + +bool allocateSharedMemory(Operation &op) { + return SharedMemoryMap::allocateSharedMemory(op); +} + +bool deleteSharedMemory(Operation &op) { + return SharedMemoryMap::deleteSharedMemory(op); +} diff --git a/TEEStub/TACommands/SharedMemoryMap.h b/TEEStub/TACommands/SharedMemoryMap.h new file mode 100755 index 0000000..098768f --- /dev/null +++ b/TEEStub/TACommands/SharedMemoryMap.h @@ -0,0 +1,60 @@ +/* + * ===================================================================================== + * + * Filename: SharedMemoryMap.h + * + * Description: SharedMemoryMap header file + * + * Version: 1.0 + * Created: 28 May 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TACOMMANDS_SHAREDMEMORYMAP_H_ +#define TACOMMANDS_SHAREDMEMORYMAP_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include "log.h" +#include "tee_internal_api.h" +#include "tee_sim_command.h" + +using namespace std; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * SharedMemoryMap class provides API to allocate and attach to shared + * memory and detach them finally during cleanup of TA. + * Here shared memory key is expected from Simulator daemon. + * + * This is a no instance class with static methods. + */ +class SharedMemoryMap { +private: + // map + static map shmMap; + static void addToMap(const uint32_t key, void* shmid); + static bool deleteFromMap(uint32_t key); +public: + static bool allocateSharedMemory(Operation &op); + static bool deleteSharedMemory(Operation &op); + static bool deleteAllSharedMemory(); +}; + +extern "C" { +bool allocateSharedMemory(Operation &op); +bool deleteSharedMemory(Operation &op); +bool deleteAllSharedMemory(); +} + +#endif /* TACOMMANDS_SHAREDMEMORYMAP_H_ */ diff --git a/TEEStub/TEEStubServer/ConnectionSession.cpp b/TEEStub/TEEStubServer/ConnectionSession.cpp new file mode 100755 index 0000000..ca7d3cb --- /dev/null +++ b/TEEStub/TEEStubServer/ConnectionSession.cpp @@ -0,0 +1,162 @@ +/* + * ===================================================================================== + * + * Filename: ConnectionSession.cpp + * + * Description: ConnectionSession class + * + * Version: 1.0 + * Created: 09 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ConnectionSession.h" +#include "TaskStrategy/TaskStrategy.h" +#include "TaskStrategy/TaskQueuedStrategy.h" +#include "TACommands/MakeCommand.h" +#include + +using namespace std; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * On starting the server and accepting a connection, read some data from the socket. + */ +void ConnectionSession::start() { + taskThread = new TaskQueuedStrategy(socket()); + taskThread->startThread(); + // read exactly 1 byte to identify the command and execute callback when + // command is received + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(1), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); +} + +/** + * On asynchronously reading from socket, this call back is executed. + * @param error[in] Boost error code and error message object + * @param bytes_transferred[in] Number of bytes read from the socket + */ +void ConnectionSession::handleRead(const boost::system::error_code& error, + size_t bytes_transferred) { + + typedef enum { + READ_PAYLOAD, PAYLOAD_COMPLETE, + } states; + static states currentState = READ_PAYLOAD; + LOGD(TEE_STUB, "Entry"); + if (!error) { + /** + * A simple small state machine to parse command and handle its + * call back to TA interface + * The state machine identifies the command. If valid, finds out how + * many bytes of payload to be read further else if invalid, exits the stub. + * + * Later, exact number of identified size of payload is read from + * stream and stored. Task strategy is invoked with the command and payload. + */ + switch (currentState) { + case READ_PAYLOAD: { + // Identify command + command = (SIM_COMMAND)clientData.at(0); + LOGD(TEE_STUB, "Command received: %d", (int )command); + + // Calculate pending numbers of bytes pending to be read only for commands + // OPENSESSION, INVOKECOMMAND, CLOSESESSION + int payload_size = MakeCommand::getCommandPayloadSize(command); + + if (payload_size > 0) { + currentState = PAYLOAD_COMPLETE; + // read remaining bytes related to received valid command + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(payload_size), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + else if (-1 == payload_size) { + // else case is invalid command + // TODO: Identify the correct behaviour; what to do when invalid command is received? + LOGE(TEE_STUB, "Invalid command received!"); + } else if (0 == payload_size) { + // Call the TaskStrategy object to handle commands + taskThread->handleCommand(MakeCommand::getCommand(command, (void*)0)); + + // reset state to read new command + currentState = READ_PAYLOAD; + // read command and register callback to read payload + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(1), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + break; + } //case + case PAYLOAD_COMPLETE: { + // At this point payload is completely read + // clear the vector for the first time and copy client data received + commandPayload.clear(); + for (unsigned int i = 0; i < clientData.size(); i++) { + commandPayload.push_back(clientData.at(i)); + } + string tempData(commandPayload.begin(), commandPayload.end()); + // Call the TaskStrategy object to handle commands + taskThread->handleCommand( + MakeCommand::getCommand(command, (void*)tempData.c_str())); + // reset state to read new command + currentState = READ_PAYLOAD; + if (command != DESTROY) { + // read command and register callback to read payload + boost::asio::async_read(clientSocket, + boost::asio::buffer(clientData), + boost::asio::transfer_exactly(1), + boost::bind(&ConnectionSession::handleRead, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + break; + } //case + } //switch + } + // On error + else { + LOGE(TEE_STUB, "error code %s", error.category().name()); + if (boost::asio::error::eof == error.value()) { + LOGE(TEE_STUB, "Simulator daemon is down! Exiting this TA instance."); + taskThread->stopThread(); + } + } +} +/** + * On asynchronously writing to socket, this call back is executed. + * @param error[in] Boost error code and error message object + */ +void ConnectionSession::handleWrite(const boost::system::error_code& error) { + if (!error) { + // Write to socket +// clientSocket.async_write_some(boost::asio::buffer(serverData), +// boost::bind(&ConnectionSession::handleWrite, shared_from_this(), +// boost::asio::placeholders::error, +// boost::asio::placeholders::bytes_transferred)); + } +} + +ConnectionSession::~ConnectionSession() { + //TODO: Before deleting task strategy object, check how to stop thread and then delete it + //delete taskThread; +} diff --git a/TEEStub/TEEStubServer/ConnectionSession.h b/TEEStub/TEEStubServer/ConnectionSession.h new file mode 100755 index 0000000..51a75ad --- /dev/null +++ b/TEEStub/TEEStubServer/ConnectionSession.h @@ -0,0 +1,75 @@ +/* + * ===================================================================================== + * + * Filename: ConnectionSession.h + * + * Description: ConnectionSession header file + * + * Version: 1.0 + * Created: 09 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef CONNECTIONSESSION_H_ +#define CONNECTIONSESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "tee_sim_command.h" +#include "TaskStrategy/TaskStrategy.h" +#include + +using namespace std; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +// COMPILE TIME CHECK TO SEE IF UNIX DOMAIN SOCKETS ARE AVAILABLE ON SYSTEM +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +using boost::asio::local::stream_protocol; +/** + * @class ConnectionSession + * Represents a socket for a session. USes unix domain sockets from communication + */ +class ConnectionSession: public boost::enable_shared_from_this +{ +public: + ConnectionSession(boost::asio::io_service& io_service) : + clientSocket(io_service), command((SIM_COMMAND) -1), taskThread(0) + { + } + stream_protocol::socket& socket() + { + return clientSocket; + } + void start(); + void handleRead(const boost::system::error_code& error, + size_t bytes_transferred); + void handleWrite(const boost::system::error_code& error); + virtual ~ConnectionSession(); +private: + // The socket used to communicate with the client. + stream_protocol::socket clientSocket; + // Buffer used to store data received from the client. + boost::array clientData; + vector commandPayload; + SIM_COMMAND command; + TaskStrategy *taskThread; +}; +#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +# error Unix domain/local sockets not available on this platform. +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +#endif /* CONNECTIONSESSION_H_ */ + diff --git a/TEEStub/TEEStubServer/TAProperty.cpp b/TEEStub/TEEStubServer/TAProperty.cpp new file mode 100755 index 0000000..acab173 --- /dev/null +++ b/TEEStub/TEEStubServer/TAProperty.cpp @@ -0,0 +1,85 @@ +/* + * ===================================================================================== + * + * Filename: ConnectionSession.cpp + * + * Description: ConnectionSession class + * + * Version: 1.0 + * Created: 09 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TAProperty.h" +#include +#include + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +TAProperty::TAProperty() { + singleInstance = false; + multipleSession = false; + uuid.timeLow = 0x0; + uuid.timeMid = 0x0; + uuid.timeHiAndVersion = 0x0; + uuid.clockSeqAndNode[0] = 0x0; + uuid.clockSeqAndNode[1] = 0x0; + uuid.clockSeqAndNode[2] = 0x0; + uuid.clockSeqAndNode[3] = 0x0; + uuid.clockSeqAndNode[4] = 0x0; + uuid.clockSeqAndNode[5] = 0x0; + uuid.clockSeqAndNode[6] = 0x0; + uuid.clockSeqAndNode[7] = 0x0; +} +/** + * Read TA properties from the TA header + */ +void TAProperty::readProperty() { + //TODO: Read property from TA + // Test Code + // Hardcoding the read values + // UUID 79B77788-9789-4a7a-A2BE-B60155EEF5F3 + uuid.timeLow = 0x79b77788; + uuid.timeMid = 0x9789; + uuid.timeHiAndVersion = 0x4a7a; + uuid.clockSeqAndNode[0] = 0xa2; + uuid.clockSeqAndNode[1] = 0xbe; + uuid.clockSeqAndNode[2] = 0xb6; + uuid.clockSeqAndNode[3] = 0x01; + uuid.clockSeqAndNode[4] = 0x55; + uuid.clockSeqAndNode[5] = 0xee; + uuid.clockSeqAndNode[6] = 0xf5; + uuid.clockSeqAndNode[7] = 0xf3; +} + +/** + * Converts UUID from TEE_UUID to a string + * @return string of TEE_UUID + */ +string TAProperty::getUUID(void) { + // E.g. returns a string in the format 79B77788-9789-4a7a-A2BE-B60155EEF5F3 + std::stringstream strStream; + strStream << IntToHex(uuid.timeLow) << "-"; + strStream << IntToHex(uuid.timeMid) << "-"; + strStream << IntToHex(uuid.timeHiAndVersion) << "-"; + strStream << IntToHex((short)uuid.clockSeqAndNode[0], 2); + strStream << IntToHex((short)uuid.clockSeqAndNode[1], 2); + strStream << "-"; + for (int i = 2; i < 8; i++) { + strStream << IntToHex((short)uuid.clockSeqAndNode[i], 2); + } + return strStream.str(); +} + +TAProperty::~TAProperty() { +} diff --git a/TEEStub/TEEStubServer/TAProperty.h b/TEEStub/TEEStubServer/TAProperty.h new file mode 100755 index 0000000..b9c7e93 --- /dev/null +++ b/TEEStub/TEEStubServer/TAProperty.h @@ -0,0 +1,60 @@ +/* + * ===================================================================================== + * + * Filename: TAProperty.h + * + * Description: TAProperty header file + * + * Version: 1.0 + * Created: 09 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TAPROPERTY_H_ +#define TAPROPERTY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_internal_api.h" +#include +#include +#include + +using namespace std; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TAProperty { +private: + TEE_UUID uuid; + bool singleInstance; + bool multipleSession; +public: + TAProperty(); + void readProperty(void); + string getUUID(void); + bool isSingleInstance() { + return singleInstance; + } + bool isMultipleSession() { + return multipleSession; + } + virtual ~TAProperty(); +private: + template + std::string IntToHex(T i, int width = sizeof(T) * 2) { + std::stringstream stream; + stream << std::setfill('0') << std::setw(width) << std::hex << i; + return stream.str(); + } +}; + +#endif /* TAPROPERTY_H_ */ diff --git a/TEEStub/TEEStubServer/TEEStubServer.cpp b/TEEStub/TEEStubServer/TEEStubServer.cpp new file mode 100755 index 0000000..8c6ff1a --- /dev/null +++ b/TEEStub/TEEStubServer/TEEStubServer.cpp @@ -0,0 +1,61 @@ +/* + * ===================================================================================== + * + * Filename: TEEStubServer.cpp + * + * Description: TEEStubServer class + * + * Version: 1.0 + * Created: 09 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TEEStubServer.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Accepts a new connection from local machine on a UDS + * @param io_service[in] provides OS abstraction for async communication + * @param file[in] path to Unix Domain Socket represented by a local file + */ +TEEStubServer::TEEStubServer(boost::asio::io_service& io_service, + const std::string& file) : + mem_io_service(io_service), + acceptor(io_service, stream_protocol::endpoint(file)) { + LOGD(TEE_STUB, "Waiting for connection from Simulator daemon"); + session_ptr new_session(new ConnectionSession(mem_io_service)); + acceptor.async_accept(new_session->socket(), + boost::bind(&TEEStubServer::handleAccept, this, new_session, + boost::asio::placeholders::error)); +} + +/** + * Call back for boost acceptor.async_accept() to handle a new connection + * @param new_session[in] a pointer to a session + * @param error[in] error code if any occurred + */ +void TEEStubServer::handleAccept(session_ptr new_session, + const boost::system::error_code& error) { + if (!error) { + new_session->start(); + } + // Below is test code to handle multiple concurrent connections + // Disabled as it is a test feature here + //LOGD(TEE_STUB, "Shared ptr ref count (before reset): %d", new_session.use_count()); + new_session.reset(new ConnectionSession(mem_io_service)); + //LOGD(TEE_STUB, "Shared ptr ref count (after reset): %d", new_session.use_count()); + acceptor.async_accept(new_session->socket(), + boost::bind(&TEEStubServer::handleAccept, this, new_session, + boost::asio::placeholders::error)); +} diff --git a/TEEStub/TEEStubServer/TEEStubServer.h b/TEEStub/TEEStubServer/TEEStubServer.h new file mode 100755 index 0000000..599633b --- /dev/null +++ b/TEEStub/TEEStubServer/TEEStubServer.h @@ -0,0 +1,47 @@ +/* + * ===================================================================================== + * + * Filename: ConnectionSession.h + * + * Description: ConnectionSession header file + * + * Version: 1.0 + * Created: 09 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TEESTUBSERVER_H_ +#define TEESTUBSERVER_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ConnectionSession.h" + +typedef boost::shared_ptr session_ptr; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class TEEStubServer + * Starts a server to accept connection from simulator daemon. + * Accepts only a single connection. + */ +class TEEStubServer { +public: + TEEStubServer(boost::asio::io_service& io_service, const std::string& file); + void handleAccept(session_ptr new_session, + const boost::system::error_code& error); +private: + boost::asio::io_service& mem_io_service; + stream_protocol::acceptor acceptor; +}; + +#endif /* TEESTUBSERVER_H_ */ diff --git a/TEEStub/TaskStrategy/SessionState.cpp b/TEEStub/TaskStrategy/SessionState.cpp new file mode 100755 index 0000000..a1fbfd7 --- /dev/null +++ b/TEEStub/TaskStrategy/SessionState.cpp @@ -0,0 +1,74 @@ +/* + * ===================================================================================== + * + * Filename: SessionState.cpp + * + * Description: SessionState class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "SessionState.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor of SessionState + * @param sID[in] session ID for this SessionState + */ +SessionState::SessionState(uint32_t sID) { + sessionID = sID; +} + +/** + * Ass a task to session task queue + * @param command[in] a task to be queued in session + */ +void SessionState::addTask(CommandBasePtr command) { + queuedTasks.push(command); +} + +/** + * Gets next task in queue for this session + * @return Task in queue + */ +CommandBasePtr SessionState::getNextTask() { + if (!queuedTasks.empty()) { + CommandBasePtr ptr(queuedTasks.front()); + queuedTasks.pop(); + return ptr; + } else { + CommandBasePtr ptr; + return ptr; + } +} + +/** + * Constructor of SessionState + */ +SessionState::SessionState() { + sessionID = 0; +} + +/** + * Is task queue in this session is empty + * @return true if task queue in this session is empty else false + */ +bool SessionState::empty() { + return queuedTasks.empty(); +} + +SessionState::~SessionState() { +} diff --git a/TEEStub/TaskStrategy/SessionState.h b/TEEStub/TaskStrategy/SessionState.h new file mode 100755 index 0000000..0ef0694 --- /dev/null +++ b/TEEStub/TaskStrategy/SessionState.h @@ -0,0 +1,52 @@ +/* + * ===================================================================================== + * + * Filename: SessionState.h + * + * Description: SessionState header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef SESSIONSTATE_H_ +#define SESSIONSTATE_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_sim_command.h" +#include "TACommands/CommandBase.h" +#include + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class SessionState + * Represents a set of commands within a session. + * This class encapsulates all commands of same session that + * are received from CA into a queue. Later this queue is dequeued by + * TaskQueuedStrategy to execute the commands. + */ +class SessionState { +private: + std::queue queuedTasks; + uint32_t sessionID; +public: + SessionState(); + SessionState(uint32_t sID); + void addTask(CommandBasePtr command); + bool empty(); + CommandBasePtr getNextTask(); + virtual ~SessionState(); +}; + +#endif /* SESSIONSTATE_H_ */ diff --git a/TEEStub/TaskStrategy/TaskQueuedStrategy.cpp b/TEEStub/TaskStrategy/TaskQueuedStrategy.cpp new file mode 100755 index 0000000..9587203 --- /dev/null +++ b/TEEStub/TaskStrategy/TaskQueuedStrategy.cpp @@ -0,0 +1,181 @@ +/* + * ===================================================================================== + * + * Filename: TaskQueuedStrategy.cpp + * + * Description: TaskQueuedStrategy class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TaskQueuedStrategy.h" +#include +#include "ssf_lib.h" +#include +#include + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Constructor + * @param msocket[in] Initializes socket to be used. Used to write back reply. + */ +TaskQueuedStrategy::TaskQueuedStrategy(stream_protocol::socket &msocket) : + clientSocket(msocket) { + runThread = false; +} + +/** + * Adds given task (command) to queue based on session ID with which a + * command is associated with. Default session ID is 0 for commands + * like CreateTA Entry/Destroy Point which do not have session IDs. + * @param command[in] task/command to be queued for execution + */ +void TaskQueuedStrategy::handleCommand(CommandBasePtr command) { + LOGD(TEE_STUB, "Entry"); + if (command->isCancelCommand()) { + LOGD(TEE_STUB, "A Cancel command has been received!"); + executeCancellation(command); + } else { + map_mutex.lock(); + //If new session ID, just add to map + if (sessionTaskMap.find(command->sessionID) == sessionTaskMap.end()) { + SessionState ss(command->sessionID); + ss.addTask(command); + sessionTaskMap[command->sessionID] = ss; + LOGD(TEE_STUB, "New Session ID"); + } + // Else, the session ID exists in map, so append to list in session + else { + LOGD(TEE_STUB, "Session ID Exists, adding tasks"); + sessionTaskMap[command->sessionID].addTask(command); + } + LOGD(TEE_STUB, "MapSize: %d", sessionTaskMap.size()); + map_mutex.unlock(); + } +} + +/** + * Sets requested command to be cancelled from task execution queue + * @param cancelCommand[in] command to be cancelled + */ +void TaskQueuedStrategy::executeCancellation(CommandBasePtr cancelCommand) { + // If cancel command is the first command and no history of other commands + // exist, just return + if (true == !currentCommand) { + return; + } + + // check if the currently executing task needs to be cancelled. + // If so set the shared data flag to communicate that the + // current task should be cancelled. + //LOGD(TEE_STUB, "Current Command UID: %s", currentCommand->getCommandUID()); + //LOGD(TEE_STUB, "Cancel Command UID: %s", cancelCommand->getCommandUID()); + if (currentCommand->getCommandUID() == cancelCommand->getCommandUID()) { + LOGD(TEE_STUB, "Cancel command matched with current task"); + sharedData.thisTaskCancel = true; + } + // If the task to be cancelled is not the current task + // then the task must be in execution queue, yet to be executed. + // Just push the request to cancellation vector using + // cancel commands execute + else { + LOGD(TEE_STUB, "Cancel command queued"); + cancelCommand->execute(); + } +} + +/** + * Execute all tasks inside a session + */ +void TaskQueuedStrategy::executeCommands() { + LOGD(TEE_STUB, "Entry"); + /** + * Iterate the map for all SessionStates and dequeue all + * the Tasks from the queue. Execute the dequeued tasks. + */ + unsigned char writeData[1024]; + while (runThread) { + map_mutex.lock(); + + if (sessionTaskMap.size() > 0) { + for (std::map::iterator itr = + sessionTaskMap.begin(); itr != sessionTaskMap.end(); itr++) { + if (!itr->second.empty()) { + /** + * Dequeue the entries in task queue + */ + CommandBasePtr task; + task = itr->second.getNextTask(); + while (false == !task) // execute as long as task is not invalid. + { + currentCommand = task; + // Before execution of task check if the task is set for cancellation + CommandRequestCancelPtr ptr = CommandRequestCancel::isCancelled( + task->getCommandUID()); + if (false == !ptr) { + unsigned int size; + ptr->getSerializedData(writeData, size); + boost::asio::write(clientSocket, + boost::asio::buffer(writeData, size)); + // CAUTION: after this the while loop should continue with next task. + // Be careful while changing the code after else part + } else { + task->execute(); + // Invalidate the shared pointer + currentCommand = CommandBasePtr(); + // reset cancel flag for this task + sharedData.thisTaskCancel = false; + // write reply back + unsigned int size; + task->getSerializedData(writeData, size); + boost::system::error_code ec; + boost::asio::write(clientSocket, + boost::asio::buffer(writeData, size + 1), ec); + if (!ec) + LOGD(TEE_STUB, "Reply written back"); + else + LOGE(TEE_STUB, "Reply write failed!"); + task = itr->second.getNextTask(); + } //if-else + } //while + } //if queue + } //for + } //if map + map_mutex.unlock(); + + // TODO: check how to reduce cycles from while(1) + // boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } //while(1) +} + +/** + * Start the executor thread which executes task queue in all sessions. + */ +void TaskQueuedStrategy::startThread() { + LOGD(TEE_STUB, "Entry"); + runThread = true; + executorThread = boost::thread(&TaskQueuedStrategy::executeCommands, this); +} + +TaskQueuedStrategy::~TaskQueuedStrategy() { +} + +/** + * Stops thread and exits to thread caller + */ +void TaskQueuedStrategy::stopThread() { + runThread = false; +} diff --git a/TEEStub/TaskStrategy/TaskQueuedStrategy.h b/TEEStub/TaskStrategy/TaskQueuedStrategy.h new file mode 100755 index 0000000..a38da7a --- /dev/null +++ b/TEEStub/TaskStrategy/TaskQueuedStrategy.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * This software is the confidential and proprietary information + * of Samsung Electronics Co., Ltd. ("Confidential Information"). + * you shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + * TaskQueuedStrategy.h + * + * Created on: 13-Apr-2015 + * Author: Krishna Devale + */ + +#ifndef TASKQUEUEDSTRATEGY_H_ +#define TASKQUEUEDSTRATEGY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TaskStrategy.h" +#include "SessionState.h" +#include "TACommands/CommandBase.h" +#include "TACommands/CommandRequestCancel.h" +#include +#include +#include +#include +#include +#include +#include + +using boost::asio::local::stream_protocol; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class TaskQueuedStrategy + * Implements TaskStategy. Here, commands are added to session map where + * internally, each session has a queue of tasks a.k.a commands. + * The executor thread later picks up each of these commands and + * serves the command request. + * + * Cancellation of command is also possible in two ways as per + * GP specification: + * 1. Command is still in queue then directly discard the command. + * 2. The current command in execution is to be cancelled, raise a flag + * which reached the current command, where TA developer needs to take + * action. + */ +class TaskQueuedStrategy: + public TaskStrategy { +private: + std::map sessionTaskMap; + std::vector cancelVector; + boost::thread executorThread; + boost::mutex map_mutex; + + // The socket used to communicate with the client. + stream_protocol::socket &clientSocket; + CommandBasePtr currentCommand; + bool runThread; + void executeCancellation(CommandBasePtr cancelCommand); + void executeCommands(); +public: + TaskQueuedStrategy(stream_protocol::socket &msocket); + virtual void handleCommand(CommandBasePtr command); + virtual ~TaskQueuedStrategy(); + virtual void startThread(); + virtual void stopThread(); +}; + +#endif /* TASKQUEUEDSTRATEGY_H_ */ diff --git a/TEEStub/TaskStrategy/TaskStrategy.cpp b/TEEStub/TaskStrategy/TaskStrategy.cpp new file mode 100755 index 0000000..79aa4d3 --- /dev/null +++ b/TEEStub/TaskStrategy/TaskStrategy.cpp @@ -0,0 +1,31 @@ +/* + * ===================================================================================== + * + * Filename: TaskStrategy.cpp + * + * Description: TaskStrategy class + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TaskStrategy.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +TaskStrategy::TaskStrategy() { +} + +TaskStrategy::~TaskStrategy() { +} diff --git a/TEEStub/TaskStrategy/TaskStrategy.h b/TEEStub/TaskStrategy/TaskStrategy.h new file mode 100755 index 0000000..f9c2c31 --- /dev/null +++ b/TEEStub/TaskStrategy/TaskStrategy.h @@ -0,0 +1,45 @@ +/* + * ===================================================================================== + * + * Filename: TaskStrategy.h + * + * Description: TaskStrategy header file + * + * Version: 1.0 + * Created: 13 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TASKSTRATEGY_H_ +#define TASKSTRATEGY_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_sim_command.h" +#include "TACommands/CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +/** + * @class TaskStrategy + * Abstract class to provide interface to queue up commands and execute them. + */ +class TaskStrategy { +public: + TaskStrategy(); + virtual void handleCommand(CommandBasePtr command) = 0; + virtual void startThread() = 0; + virtual void stopThread() = 0; + virtual void executeCommands() = 0; + virtual ~TaskStrategy(); +}; + +#endif /* TASKSTRATEGY_H_ */ diff --git a/TEEStub/teestubmain.cpp b/TEEStub/teestubmain.cpp new file mode 100755 index 0000000..9f1a9b6 --- /dev/null +++ b/TEEStub/teestubmain.cpp @@ -0,0 +1,105 @@ +/* + * ===================================================================================== + * + * Filename: main.cpp + * + * Description: main + * + * Version: 1.0 + * Created: 08 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include "TACommands/SharedMemoryMap.h" +#include "TEEStubServer/TEEStubServer.h" +#include +#include + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +extern TEE_UUID ssf_sharedthisTAUUID; +boost::asio::io_service io_service; ///< io_service provides OS abstraction for async communication + +/*----------------------------------------------------------------------------- + * Local functions + *-----------------------------------------------------------------------------*/ +/** + * Starts the TEEStub as server which listens for connection from + * Simulator Daemon. + * @param socketName + */ +void StartServer(string socketName) { + try { + ::unlink(socketName.c_str()); + LOGD(TEE_STUB, "Waiting on socket"); + TEEStubServer s(io_service, socketName.c_str()); + io_service.run(); + } catch (std::exception& e) { + LOGE(TEE_STUB, "Exception: %s", e.what()); + } +} + +/** + * Stops the TEEStub server + */ +void StopServer() { + io_service.stop(); +} + +/** + * Entry point for a TA. TEEStub supplies the main function where + * as the TA Interface is implemented by TA developer + * @param argc Number of arguments to main function + * @param argv Arguments passed to TA + * @return + */ +int main(int argc, char* argv[]) { + + if (argc < 2) { + LOGE(TEE_STUB, "Invalid arguments to TEE Stub"); + } + // Initialize Properties module + // TODO: fetch login method from Context, not to be hardcoded + TEE_Result initStatus; + char uuid[100]; + int uuidlen = strlen(argv[0]); + printf("argv[0]: %s\n", argv[0]); + // fetch uuid from argv[0] + int i, j; + for (i = uuidlen - 38, j = 0; i < uuidlen - 6; j++, i++) { + uuid[j] = argv[0][i]; + } + uuid[j] = '\0'; + // Inititalize the property module + initStatus = InitPropertyModule(uuid, TEE_LOGIN_PUBLIC); + // Pass UUID to SSF + TEE_UUID out; + PropertyValue pv; + pv.type = "uuid"; + pv.value = string(uuid); + PropertyUtility::convertToUUID(pv, out); + ssf_sharedthisTAUUID = out; + + // Once the server is started, it exits only after the + // connection is lost or gracefully disconnected. + StartServer(string("/tmp/") + string(argv[1])); + LOGD(TEE_STUB, "Exiting TEEStub\n"); + // Deallocate property objects + if (TEE_SUCCESS == initStatus) DeInitPropertyModule(); + + // Cleanup by deleting all shared memory + deleteAllSharedMemory(); + return 0; +} diff --git a/build/TEECLib/makefile b/build/TEECLib/makefile new file mode 100755 index 0000000..7c44a62 --- /dev/null +++ b/build/TEECLib/makefile @@ -0,0 +1,51 @@ +# Directory where Simulator code is placed + +GIT_SDK = ../../.. +TOOLCHAIN_PATH = $(GIT_SDK)/toolchain/linux +TOOLCHAIN = $(TOOLCHAIN_PATH)/i386-linux-gnueabi-gcc-4.6/bin/i386-linux-gnueabi- +INCLUDE = $(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr/include/ +SYSROOT = --sysroot=$(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/ + +HOME = $(GIT_SDK)/simulator +TEECLIB_SOURCE = $(HOME)/TEECLib + +-include ../makefile.init + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: libteec2.so + +# Tool invocations +libteec2.so: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C Linker' + $(TOOLCHAIN)g++ -L"../osal" -L"../log" -shared -o "libteec2.so" $(OBJS) $(USER_OBJS) $(LIBS) $(SYSROOT) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(OBJS)$(C_DEPS)$(LIBRARIES) libteec2.so + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/build/TEECLib/objects.mk b/build/TEECLib/objects.mk new file mode 100755 index 0000000..9422d85 --- /dev/null +++ b/build/TEECLib/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := -losal -lrt -llog + diff --git a/build/TEECLib/sources.mk b/build/TEECLib/sources.mk new file mode 100755 index 0000000..1ba014d --- /dev/null +++ b/build/TEECLib/sources.mk @@ -0,0 +1,17 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +OBJS := +C_DEPS := +LIBRARIES := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src \ + diff --git a/build/TEECLib/src/subdir.mk b/build/TEECLib/src/subdir.mk new file mode 100755 index 0000000..1af650e --- /dev/null +++ b/build/TEECLib/src/subdir.mk @@ -0,0 +1,23 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(TEECLIB_SOURCE)/src/teec_api.c \ +$(TEECLIB_SOURCE)/src/teec_connection.c + +OBJS += \ +./src/teec_api.o \ +./src/teec_connection.o + +C_DEPS += \ +./src/teec_api.d \ +./src/teec_connection.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: $(TEECLIB_SOURCE)/src/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/TEECLib/inc" -I"../../osal" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/TEEStub/PropertyAccess/subdir.mk b/build/TEEStub/PropertyAccess/subdir.mk new file mode 100755 index 0000000..89bc675 --- /dev/null +++ b/build/TEEStub/PropertyAccess/subdir.mk @@ -0,0 +1,32 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(TEESTUB_SOURCE)/PropertyAccess/ClientProperty.cpp \ +$(TEESTUB_SOURCE)/PropertyAccess/PropertyApi.cpp \ +$(TEESTUB_SOURCE)/PropertyAccess/PropertyUtility.cpp \ +$(TEESTUB_SOURCE)/PropertyAccess/TAProperty.cpp \ +$(TEESTUB_SOURCE)/PropertyAccess/TEEProperty.cpp + +OBJS += \ +./PropertyAccess/ClientProperty.o \ +./PropertyAccess/PropertyApi.o \ +./PropertyAccess/PropertyUtility.o \ +./PropertyAccess/TAProperty.o \ +./PropertyAccess/TEEProperty.o + +CPP_DEPS += \ +./PropertyAccess/ClientProperty.d \ +./PropertyAccess/PropertyApi.d \ +./PropertyAccess/PropertyUtility.d \ +./PropertyAccess/TAProperty.d \ +./PropertyAccess/TEEProperty.d + + +# Each subdirectory must supply rules for building sources it contributes +PropertyAccess/%.o: $(TEESTUB_SOURCE)/PropertyAccess/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/TEEStub/../ssflib/inc" -I"$(HOME)/TEEStub" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/TEEStub/TACommands/subdir.mk b/build/TEEStub/TACommands/subdir.mk new file mode 100755 index 0000000..9648d87 --- /dev/null +++ b/build/TEEStub/TACommands/subdir.mk @@ -0,0 +1,44 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(TEESTUB_SOURCE)/TACommands/CommandBase.cpp \ +$(TEESTUB_SOURCE)/TACommands/CommandCloseSession.cpp \ +$(TEESTUB_SOURCE)/TACommands/CommandCreateEntryPoint.cpp \ +$(TEESTUB_SOURCE)/TACommands/CommandDestroyEntryPoint.cpp \ +$(TEESTUB_SOURCE)/TACommands/CommandInvoke.cpp \ +$(TEESTUB_SOURCE)/TACommands/CommandOpenSession.cpp \ +$(TEESTUB_SOURCE)/TACommands/CommandRequestCancel.cpp \ +$(TEESTUB_SOURCE)/TACommands/MakeCommand.cpp \ +$(TEESTUB_SOURCE)/TACommands/SharedMemoryMap.cpp + +OBJS += \ +./TACommands/CommandBase.o \ +./TACommands/CommandCloseSession.o \ +./TACommands/CommandCreateEntryPoint.o \ +./TACommands/CommandDestroyEntryPoint.o \ +./TACommands/CommandInvoke.o \ +./TACommands/CommandOpenSession.o \ +./TACommands/CommandRequestCancel.o \ +./TACommands/MakeCommand.o \ +./TACommands/SharedMemoryMap.o + +CPP_DEPS += \ +./TACommands/CommandBase.d \ +./TACommands/CommandCloseSession.d \ +./TACommands/CommandCreateEntryPoint.d \ +./TACommands/CommandDestroyEntryPoint.d \ +./TACommands/CommandInvoke.d \ +./TACommands/CommandOpenSession.d \ +./TACommands/CommandRequestCancel.d \ +./TACommands/MakeCommand.d \ +./TACommands/SharedMemoryMap.d + + +# Each subdirectory must supply rules for building sources it contributes +TACommands/%.o: $(TEESTUB_SOURCE)/TACommands/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/TEEStub/../ssflib/inc" -I"$(HOME)/TEEStub" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/TEEStub/TEEStubServer/subdir.mk b/build/TEEStub/TEEStubServer/subdir.mk new file mode 100755 index 0000000..4e40be9 --- /dev/null +++ b/build/TEEStub/TEEStubServer/subdir.mk @@ -0,0 +1,26 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(TEESTUB_SOURCE)/TEEStubServer/ConnectionSession.cpp \ +$(TEESTUB_SOURCE)/TEEStubServer/TAProperty.cpp \ +$(TEESTUB_SOURCE)/TEEStubServer/TEEStubServer.cpp + +OBJS += \ +./TEEStubServer/ConnectionSession.o \ +./TEEStubServer/TAProperty.o \ +./TEEStubServer/TEEStubServer.o + +CPP_DEPS += \ +./TEEStubServer/ConnectionSession.d \ +./TEEStubServer/TAProperty.d \ +./TEEStubServer/TEEStubServer.d + + +# Each subdirectory must supply rules for building sources it contributes +TEEStubServer/%.o: $(TEESTUB_SOURCE)/TEEStubServer/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/TEEStub/../ssflib/inc" -I"$(HOME)/TEEStub" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/TEEStub/TaskStrategy/subdir.mk b/build/TEEStub/TaskStrategy/subdir.mk new file mode 100755 index 0000000..711898d --- /dev/null +++ b/build/TEEStub/TaskStrategy/subdir.mk @@ -0,0 +1,26 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(TEESTUB_SOURCE)/TaskStrategy/SessionState.cpp \ +$(TEESTUB_SOURCE)/TaskStrategy/TaskQueuedStrategy.cpp \ +$(TEESTUB_SOURCE)/TaskStrategy/TaskStrategy.cpp + +OBJS += \ +./TaskStrategy/SessionState.o \ +./TaskStrategy/TaskQueuedStrategy.o \ +./TaskStrategy/TaskStrategy.o + +CPP_DEPS += \ +./TaskStrategy/SessionState.d \ +./TaskStrategy/TaskQueuedStrategy.d \ +./TaskStrategy/TaskStrategy.d + + +# Each subdirectory must supply rules for building sources it contributes +TaskStrategy/%.o: $(TEESTUB_SOURCE)/TaskStrategy/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/TEEStub/../ssflib/inc" -I"$(HOME)/TEEStub" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/TEEStub/makefile b/build/TEEStub/makefile new file mode 100755 index 0000000..e21018c --- /dev/null +++ b/build/TEEStub/makefile @@ -0,0 +1,69 @@ +# Directory where Simulator code is placed + +GIT_SDK = ../../.. +TOOLCHAIN_PATH = $(GIT_SDK)/toolchain/linux +TOOLCHAIN = $(TOOLCHAIN_PATH)/i386-linux-gnueabi-gcc-4.6/bin/i386-linux-gnueabi- +INCLUDE = $(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr/include/ +SYSROOT = --sysroot=$(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr + +HOME = $(GIT_SDK)/simulator +TEESTUB_SOURCE = $(HOME)/TEEStub + +-include ../makefile.init + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include TaskStrategy/subdir.mk +-include TEEStubServer/subdir.mk +-include TACommands/subdir.mk +-include PropertyAccess/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C++_DEPS)),) +-include $(C++_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +ifneq ($(strip $(CC_DEPS)),) +-include $(CC_DEPS) +endif +ifneq ($(strip $(CPP_DEPS)),) +-include $(CPP_DEPS) +endif +ifneq ($(strip $(CXX_DEPS)),) +-include $(CXX_DEPS) +endif +ifneq ($(strip $(C_UPPER_DEPS)),) +-include $(C_UPPER_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: libTEEStub.a + +# Tool invocations +libTEEStub.a: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC Archiver' + $(TOOLCHAIN)ar -r "libTEEStub.a" $(OBJS) $(USER_OBJS) $(LIBS) ../log/log.o + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(OBJS)$(C++_DEPS)$(C_DEPS)$(CC_DEPS)$(ARCHIVES)$(CPP_DEPS)$(CXX_DEPS)$(C_UPPER_DEPS) libTEEStub.a + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/build/TEEStub/objects.mk b/build/TEEStub/objects.mk new file mode 100755 index 0000000..742c2da --- /dev/null +++ b/build/TEEStub/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := + diff --git a/build/TEEStub/sources.mk b/build/TEEStub/sources.mk new file mode 100755 index 0000000..dc0c730 --- /dev/null +++ b/build/TEEStub/sources.mk @@ -0,0 +1,31 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +CPP_SRCS := +C_UPPER_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +CXX_SRCS := +C++_SRCS := +CC_SRCS := +OBJS := +C++_DEPS := +C_DEPS := +CC_DEPS := +ARCHIVES := +CPP_DEPS := +CXX_DEPS := +C_UPPER_DEPS := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +. \ +TaskStrategy \ +TEEStubServer \ +TACommands \ +PropertyAccess \ + diff --git a/build/TEEStub/subdir.mk b/build/TEEStub/subdir.mk new file mode 100755 index 0000000..0502a59 --- /dev/null +++ b/build/TEEStub/subdir.mk @@ -0,0 +1,20 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(TEESTUB_SOURCE)/teestubmain.cpp + +OBJS += \ +./teestubmain.o + +CPP_DEPS += \ +./teestubmain.d + + +# Each subdirectory must supply rules for building sources it contributes +%.o: $(TEESTUB_SOURCE)/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/TEEStub/../ssflib/inc" -I"$(HOME)/TEEStub" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/build.sh b/build/build.sh new file mode 100755 index 0000000..4eac26d --- /dev/null +++ b/build/build.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# +# This script builds all modules in TA SDK Simulator and copies the binaries +# in the package +# +# Written by Cheryl Bansal +# Samsung R & D Institute, Bangalore +# Samsung Electronics +# 7 July, 2015 +# + +# Paths + +# build.sh path +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# Module Paths + +LOG_PATH=$DIR/log +OSAL_PATH=$DIR/osal +TEECLIB_PATH=$DIR/TEECLib +SSFLIB_PATH=$DIR/ssflib +TEESTUB_PATH=$DIR/TEEStub +SIMDAEMON_PATH=$DIR/simulatordaemon +Package=$2 + +#check error case +check_make_error() +{ + if [ "$?" != "0" ]; then + echo "BUILD ERROR! BUILD TERMINATED." + exit 1 + fi +} + +# Clean all modules +clean_all() +{ +cd $LOG_PATH +make clean +check_make_error +cd $OSAL_PATH +make clean +check_make_error +cd $TEECLIB_PATH +make clean +check_make_error +cd $SSFLIB_PATH +make clean +check_make_error +cd $TEESTUB_PATH +make clean +check_make_error +cd $SIMDAEMON_PATH +make clean +check_make_error +cd $DIR +} + +# Build functions for each module + +build_log() +{ +cd $LOG_PATH +make clean +check_make_error +make +check_make_error +cd $DIR +} + +build_osal() +{ +cd $OSAL_PATH +make clean +check_make_error +make +check_make_error +cd $DIR +} + +build_libteec() +{ +cd $TEECLIB_PATH +make clean +check_make_error +make +check_make_error +echo "Copying libteec.so in Package" +cp libteec2.so $Package/CA/simulator/usr/lib/ +check_make_error +cd $DIR +} + +build_ssflib() +{ +cd $SSFLIB_PATH +make clean +check_make_error +make +check_make_error +echo "Copying libssflib.so in Package" +cp libssflib.so $Package/TA/simulator/usr/lib/ +check_make_error +cd $DIR +} + +build_teestub() +{ +cd $TEESTUB_PATH +make clean +check_make_error +make +check_make_error +echo "Copying libTEEStub.a in Package" +cp libTEEStub.a $Package/TA/simulator/usr/lib/ +check_make_error +cd $DIR +} + +build_simdaemon() +{ +cd $SIMDAEMON_PATH +make clean +check_make_error +make +check_make_error +echo "Copying SimulatorDaemon in Package" +cp SimulatorDaemon $Package/CA/simulator/usr/lib/ +check_make_error +cd $DIR +} + +# User help + +echo_invalid() { +echo "Simulator Build script +Invalid arguments +Format: ./build.sh +Example:./build.sh buildall ~/Package + + + log : Build Logger module + osal : Build OSAL module + TEECLib : Build TEE Client Library module + SSFLib : Build SSF Library module + TEEStub : Build TEE Stub module + SimDaemon : Build Simulator Daemon module + buildall : Build all modules + clean : Clean all modules + Exit : To exit this Program" +} + +# Verify number of arguments to build.sh +if [[ "$#" -ne 2 ]]; then + echo "Illegal number of arguments" + echo_invalid + exit 0 +fi + +case $1 in + 'log') build_log ;; + 'osal') build_osal ;; + 'TEECLib') build_log ; build_osal ; build_libteec ;; + 'SSFLib') build_log ; build_osal ; build_ssflib ;; + 'TEEStub') build_log ; build_osal ; build_ssflib ; build_teestub ;; + 'SimDaemon') build_log ; build_osal ; build_simdaemon ;; + 'buildall') build_log ; build_osal ; build_libteec ; build_ssflib ; build_teestub ; build_simdaemon ;; + 'clean') clean_all ;; + 'Exit') exit 0 ;; + *) echo_invalid ;; +esac + diff --git a/build/log/makefile b/build/log/makefile new file mode 100755 index 0000000..c351a93 --- /dev/null +++ b/build/log/makefile @@ -0,0 +1,46 @@ +-include ../makefile.init + +GIT_SDK = ../../.. +TOOLCHAIN_PATH = $(GIT_SDK)/toolchain/linux +TOOLCHAIN = $(TOOLCHAIN_PATH)/i386-linux-gnueabi-gcc-4.6/bin/i386-linux-gnueabi- +INCLUDE = $(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr/include/ + +LOG_SOURCE = ../../log + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: liblog.a + +# Tool invocations +liblog.a: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC Archiver' + $(TOOLCHAIN)ar -r "liblog.a" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(OBJS)$(C_DEPS)$(ARCHIVES) liblog.a + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/build/log/objects.mk b/build/log/objects.mk new file mode 100755 index 0000000..742c2da --- /dev/null +++ b/build/log/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := + diff --git a/build/log/sources.mk b/build/log/sources.mk new file mode 100755 index 0000000..3e7cfef --- /dev/null +++ b/build/log/sources.mk @@ -0,0 +1,17 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +OBJS := +C_DEPS := +ARCHIVES := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +. \ + diff --git a/build/log/subdir.mk b/build/log/subdir.mk new file mode 100755 index 0000000..354843c --- /dev/null +++ b/build/log/subdir.mk @@ -0,0 +1,19 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(LOG_SOURCE)/log.c + +OBJS += \ +./log.o + +C_DEPS += \ +./log.d + +# Each subdirectory must supply rules for building sources it contributes +%.o: $(LOG_SOURCE)/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -I$(INCLUDE) -O0 -g3 -Wall -c $(SYSROOT) -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/osal/makefile b/build/osal/makefile new file mode 100755 index 0000000..af05f50 --- /dev/null +++ b/build/osal/makefile @@ -0,0 +1,46 @@ +-include ../makefile.init + +GIT_SDK = ../../.. +TOOLCHAIN_PATH = $(GIT_SDK)/toolchain/linux +TOOLCHAIN = $(TOOLCHAIN_PATH)/i386-linux-gnueabi-gcc-4.6/bin/i386-linux-gnueabi- +INCLUDE = $(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr/include/ + +OSAL_SOURCE = ../../osal + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: libosal.a + +# Tool invocations +libosal.a: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC Archiver' + $(TOOLCHAIN)ar -r "libosal.a" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(OBJS)$(C_DEPS)$(ARCHIVES) libosal.a + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/build/osal/objects.mk b/build/osal/objects.mk new file mode 100755 index 0000000..742c2da --- /dev/null +++ b/build/osal/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := + diff --git a/build/osal/sources.mk b/build/osal/sources.mk new file mode 100755 index 0000000..3e7cfef --- /dev/null +++ b/build/osal/sources.mk @@ -0,0 +1,17 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +OBJS := +C_DEPS := +ARCHIVES := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +. \ + diff --git a/build/osal/subdir.mk b/build/osal/subdir.mk new file mode 100755 index 0000000..4f05c36 --- /dev/null +++ b/build/osal/subdir.mk @@ -0,0 +1,35 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(OSAL_SOURCE)/OsaCommon.c \ +$(OSAL_SOURCE)/OsaIpc.c \ +$(OSAL_SOURCE)/OsaQueue.c \ +$(OSAL_SOURCE)/OsaSem.c \ +$(OSAL_SOURCE)/OsaSignal.c \ +$(OSAL_SOURCE)/OsaTask.c + +OBJS += \ +./OsaCommon.o \ +./OsaIpc.o \ +./OsaQueue.o \ +./OsaSem.o \ +./OsaSignal.o \ +./OsaTask.o + +C_DEPS += \ +./OsaCommon.d \ +./OsaIpc.d \ +./OsaQueue.d \ +./OsaSem.d \ +./OsaSignal.d \ +./OsaTask.d + + +# Each subdirectory must supply rules for building sources it contributes +%.o: $(OSAL_SOURCE)/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -lrt -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/simulatordaemon/makefile b/build/simulatordaemon/makefile new file mode 100755 index 0000000..7e56eaa --- /dev/null +++ b/build/simulatordaemon/makefile @@ -0,0 +1,69 @@ +# Directory where Simulator code is placed + +GIT_SDK = ../../.. +TOOLCHAIN_PATH = $(GIT_SDK)/toolchain/linux +TOOLCHAIN = $(TOOLCHAIN_PATH)/i386-linux-gnueabi-gcc-4.6/bin/i386-linux-gnueabi- +INCLUDE = $(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr/include/ +SYSROOT = --sysroot=$(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/ + +HOME = $(GIT_SDK)/simulator +SIMDAEMON_SOURCE = $(HOME)/simulatordaemon + +-include ../makefile.init + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/TABinaryManager/subdir.mk +-include src/ResponseCommands/subdir.mk +-include src/ClientCommands/subdir.mk +-include src/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C++_DEPS)),) +-include $(C++_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +ifneq ($(strip $(CC_DEPS)),) +-include $(CC_DEPS) +endif +ifneq ($(strip $(CPP_DEPS)),) +-include $(CPP_DEPS) +endif +ifneq ($(strip $(CXX_DEPS)),) +-include $(CXX_DEPS) +endif +ifneq ($(strip $(C_UPPER_DEPS)),) +-include $(C_UPPER_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: SimulatorDaemon + +# Tool invocations +SimulatorDaemon: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + $(TOOLCHAIN)g++ -L"../log" -L"../osal" -o "SimulatorDaemon" $(SYSROOT) $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(OBJS)$(C++_DEPS)$(C_DEPS)$(CC_DEPS)$(CPP_DEPS)$(EXECUTABLES)$(CXX_DEPS)$(C_UPPER_DEPS) SimulatorDaemon + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/build/simulatordaemon/objects.mk b/build/simulatordaemon/objects.mk new file mode 100755 index 0000000..f8a3a8b --- /dev/null +++ b/build/simulatordaemon/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := -lrt -llog -losal -lpthread -lboost_system -lboost_thread + diff --git a/build/simulatordaemon/sources.mk b/build/simulatordaemon/sources.mk new file mode 100755 index 0000000..e2a915a --- /dev/null +++ b/build/simulatordaemon/sources.mk @@ -0,0 +1,30 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +CPP_SRCS := +C_UPPER_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +CXX_SRCS := +C++_SRCS := +CC_SRCS := +OBJS := +C++_DEPS := +C_DEPS := +CC_DEPS := +CPP_DEPS := +EXECUTABLES := +CXX_DEPS := +C_UPPER_DEPS := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src \ +src/TABinaryManager \ +src/ResponseCommands \ +src/ClientCommands \ + diff --git a/build/simulatordaemon/src/ClientCommands/subdir.mk b/build/simulatordaemon/src/ClientCommands/subdir.mk new file mode 100755 index 0000000..a099059 --- /dev/null +++ b/build/simulatordaemon/src/ClientCommands/subdir.mk @@ -0,0 +1,55 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandCloseSession.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandCloseTASession.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandFinContext.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandInitContext.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandInvokeCommand.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandInvokeTACommand.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandOpenSession.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandOpenTASession.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandPanic.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandRegSharedMem.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandRelSharedMem.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/CommandReqCancellation.cpp \ +$(SIMDAEMON_SOURCE)/src/ClientCommands/MakeCommand.cpp + +OBJS += \ +./src/ClientCommands/CommandCloseSession.o \ +./src/ClientCommands/CommandCloseTASession.o \ +./src/ClientCommands/CommandFinContext.o \ +./src/ClientCommands/CommandInitContext.o \ +./src/ClientCommands/CommandInvokeCommand.o \ +./src/ClientCommands/CommandInvokeTACommand.o \ +./src/ClientCommands/CommandOpenSession.o \ +./src/ClientCommands/CommandOpenTASession.o \ +./src/ClientCommands/CommandPanic.o \ +./src/ClientCommands/CommandRegSharedMem.o \ +./src/ClientCommands/CommandRelSharedMem.o \ +./src/ClientCommands/CommandReqCancellation.o \ +./src/ClientCommands/MakeCommand.o + +CPP_DEPS += \ +./src/ClientCommands/CommandCloseSession.d \ +./src/ClientCommands/CommandCloseTASession.d \ +./src/ClientCommands/CommandFinContext.d \ +./src/ClientCommands/CommandInitContext.d \ +./src/ClientCommands/CommandInvokeCommand.d \ +./src/ClientCommands/CommandInvokeTACommand.d \ +./src/ClientCommands/CommandOpenSession.d \ +./src/ClientCommands/CommandOpenTASession.d \ +./src/ClientCommands/CommandPanic.d \ +./src/ClientCommands/CommandRegSharedMem.d \ +./src/ClientCommands/CommandRelSharedMem.d \ +./src/ClientCommands/CommandReqCancellation.d \ +./src/ClientCommands/MakeCommand.d + +# Each subdirectory must supply rules for building sources it contributes +src/ClientCommands/%.o: $(SIMDAEMON_SOURCE)/src/ClientCommands/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/simulatordaemon/src/TABinaryManager" -I"$(HOME)/simulatordaemon/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/simulatordaemon/src/ResponseCommands/subdir.mk b/build/simulatordaemon/src/ResponseCommands/subdir.mk new file mode 100755 index 0000000..be7554c --- /dev/null +++ b/build/simulatordaemon/src/ResponseCommands/subdir.mk @@ -0,0 +1,32 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(SIMDAEMON_SOURCE)/src/ResponseCommands/ResCommandCloseSession.cpp \ +$(SIMDAEMON_SOURCE)/src/ResponseCommands/ResCommandInvokeCommand.cpp \ +$(SIMDAEMON_SOURCE)/src/ResponseCommands/ResCommandOpenSession.cpp \ +$(SIMDAEMON_SOURCE)/src/ResponseCommands/ResCommandReqCancellation.cpp \ +$(SIMDAEMON_SOURCE)/src/ResponseCommands/ResMakeCommand.cpp + +OBJS += \ +./src/ResponseCommands/ResCommandCloseSession.o \ +./src/ResponseCommands/ResCommandInvokeCommand.o \ +./src/ResponseCommands/ResCommandOpenSession.o \ +./src/ResponseCommands/ResCommandReqCancellation.o \ +./src/ResponseCommands/ResMakeCommand.o + +CPP_DEPS += \ +./src/ResponseCommands/ResCommandCloseSession.d \ +./src/ResponseCommands/ResCommandInvokeCommand.d \ +./src/ResponseCommands/ResCommandOpenSession.d \ +./src/ResponseCommands/ResCommandReqCancellation.d \ +./src/ResponseCommands/ResMakeCommand.d + + +# Each subdirectory must supply rules for building sources it contributes +src/ResponseCommands/%.o: $(SIMDAEMON_SOURCE)/src/ResponseCommands/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/simulatordaemon/src/TABinaryManager" -I"$(HOME)/simulatordaemon/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/simulatordaemon/src/TABinaryManager/subdir.mk b/build/simulatordaemon/src/TABinaryManager/subdir.mk new file mode 100755 index 0000000..de7446e --- /dev/null +++ b/build/simulatordaemon/src/TABinaryManager/subdir.mk @@ -0,0 +1,29 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(SIMDAEMON_SOURCE)/src/TABinaryManager/TABinaryManager.cpp \ +$(SIMDAEMON_SOURCE)/src/TABinaryManager/TAManifest.cpp \ +$(SIMDAEMON_SOURCE)/src/TABinaryManager/TAUnpack.cpp \ +$(SIMDAEMON_SOURCE)/src/TABinaryManager/TestMain.cpp + +OBJS += \ +./src/TABinaryManager/TABinaryManager.o \ +./src/TABinaryManager/TAManifest.o \ +./src/TABinaryManager/TAUnpack.o \ +./src/TABinaryManager/TestMain.o + +CPP_DEPS += \ +./src/TABinaryManager/TABinaryManager.d \ +./src/TABinaryManager/TAManifest.d \ +./src/TABinaryManager/TAUnpack.d \ +./src/TABinaryManager/TestMain.d + + +# Each subdirectory must supply rules for building sources it contributes +src/TABinaryManager/%.o: $(SIMDAEMON_SOURCE)/src/TABinaryManager/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/simulatordaemon/src/TABinaryManager" -I"$(HOME)/simulatordaemon/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/simulatordaemon/src/subdir.mk b/build/simulatordaemon/src/subdir.mk new file mode 100755 index 0000000..f2c0e3c --- /dev/null +++ b/build/simulatordaemon/src/subdir.mk @@ -0,0 +1,41 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(SIMDAEMON_SOURCE)/src/ConnectionSession.cpp \ +$(SIMDAEMON_SOURCE)/src/Session.cpp \ +$(SIMDAEMON_SOURCE)/src/SimulatorDaemon.cpp \ +$(SIMDAEMON_SOURCE)/src/SimulatorDaemonServer.cpp \ +$(SIMDAEMON_SOURCE)/src/TAFactory.cpp \ +$(SIMDAEMON_SOURCE)/src/TAInstance.cpp \ +$(SIMDAEMON_SOURCE)/src/TEEContext.cpp \ +$(SIMDAEMON_SOURCE)/src/ioService.cpp + +OBJS += \ +./src/ConnectionSession.o \ +./src/Session.o \ +./src/SimulatorDaemon.o \ +./src/SimulatorDaemonServer.o \ +./src/TAFactory.o \ +./src/TAInstance.o \ +./src/TEEContext.o \ +./src/ioService.o + +CPP_DEPS += \ +./src/ConnectionSession.d \ +./src/Session.d \ +./src/SimulatorDaemon.d \ +./src/SimulatorDaemonServer.d \ +./src/TAFactory.d \ +./src/TAInstance.d \ +./src/TEEContext.d \ +./src/ioService.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: $(SIMDAEMON_SOURCE)/src/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -I"$(HOME)/include/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/simulatordaemon/src/TABinaryManager" -I"$(HOME)/simulatordaemon/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/dep/cryptocore/source/base/subdir.mk b/build/ssflib/dep/cryptocore/source/base/subdir.mk new file mode 100755 index 0000000..5f01c31 --- /dev/null +++ b/build/ssflib/dep/cryptocore/source/base/subdir.mk @@ -0,0 +1,59 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_ANSI_x931.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_aes.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_bignum.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_des.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_ecc.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_fast_math.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_hash.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_md5.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_moo.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_pkcs1_v21.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_rc4.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_sha1.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_sha2.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/base/cc_snow2.c + +OBJS += \ +./dep/cryptocore/source/base/cc_ANSI_x931.o \ +./dep/cryptocore/source/base/cc_aes.o \ +./dep/cryptocore/source/base/cc_bignum.o \ +./dep/cryptocore/source/base/cc_des.o \ +./dep/cryptocore/source/base/cc_ecc.o \ +./dep/cryptocore/source/base/cc_fast_math.o \ +./dep/cryptocore/source/base/cc_hash.o \ +./dep/cryptocore/source/base/cc_md5.o \ +./dep/cryptocore/source/base/cc_moo.o \ +./dep/cryptocore/source/base/cc_pkcs1_v21.o \ +./dep/cryptocore/source/base/cc_rc4.o \ +./dep/cryptocore/source/base/cc_sha1.o \ +./dep/cryptocore/source/base/cc_sha2.o \ +./dep/cryptocore/source/base/cc_snow2.o + +C_DEPS += \ +./dep/cryptocore/source/base/cc_ANSI_x931.d \ +./dep/cryptocore/source/base/cc_aes.d \ +./dep/cryptocore/source/base/cc_bignum.d \ +./dep/cryptocore/source/base/cc_des.d \ +./dep/cryptocore/source/base/cc_ecc.d \ +./dep/cryptocore/source/base/cc_fast_math.d \ +./dep/cryptocore/source/base/cc_hash.d \ +./dep/cryptocore/source/base/cc_md5.d \ +./dep/cryptocore/source/base/cc_moo.d \ +./dep/cryptocore/source/base/cc_pkcs1_v21.d \ +./dep/cryptocore/source/base/cc_rc4.d \ +./dep/cryptocore/source/base/cc_sha1.d \ +./dep/cryptocore/source/base/cc_sha2.d \ +./dep/cryptocore/source/base/cc_snow2.d + + +# Each subdirectory must supply rules for building sources it contributes +dep/cryptocore/source/base/%.o: $(SSFLIB_SOURCE)/dep/cryptocore/source/base/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/dep/cryptocore/source/middle/subdir.mk b/build/ssflib/dep/cryptocore/source/middle/subdir.mk new file mode 100755 index 0000000..73d96ca --- /dev/null +++ b/build/ssflib/dep/cryptocore/source/middle/subdir.mk @@ -0,0 +1,47 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_cmac.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_dh.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_dsa.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_ecdh.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_ecdsa.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_hmac.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_rng.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_rsa.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_symmetric.c \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/middle/cc_tdes.c + +OBJS += \ +./dep/cryptocore/source/middle/cc_cmac.o \ +./dep/cryptocore/source/middle/cc_dh.o \ +./dep/cryptocore/source/middle/cc_dsa.o \ +./dep/cryptocore/source/middle/cc_ecdh.o \ +./dep/cryptocore/source/middle/cc_ecdsa.o \ +./dep/cryptocore/source/middle/cc_hmac.o \ +./dep/cryptocore/source/middle/cc_rng.o \ +./dep/cryptocore/source/middle/cc_rsa.o \ +./dep/cryptocore/source/middle/cc_symmetric.o \ +./dep/cryptocore/source/middle/cc_tdes.o + +C_DEPS += \ +./dep/cryptocore/source/middle/cc_cmac.d \ +./dep/cryptocore/source/middle/cc_dh.d \ +./dep/cryptocore/source/middle/cc_dsa.d \ +./dep/cryptocore/source/middle/cc_ecdh.d \ +./dep/cryptocore/source/middle/cc_ecdsa.d \ +./dep/cryptocore/source/middle/cc_hmac.d \ +./dep/cryptocore/source/middle/cc_rng.d \ +./dep/cryptocore/source/middle/cc_rsa.d \ +./dep/cryptocore/source/middle/cc_symmetric.d \ +./dep/cryptocore/source/middle/cc_tdes.d + + +# Each subdirectory must supply rules for building sources it contributes +dep/cryptocore/source/middle/%.o: $(SSFLIB_SOURCE)/dep/cryptocore/source/middle/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/dep/cryptocore/source/subdir.mk b/build/ssflib/dep/cryptocore/source/subdir.mk new file mode 100755 index 0000000..0b82019 --- /dev/null +++ b/build/ssflib/dep/cryptocore/source/subdir.mk @@ -0,0 +1,20 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(SSFLIB_SOURCE)/dep/cryptocore/source/CC_API.c + +OBJS += \ +./dep/cryptocore/source/CC_API.o + +C_DEPS += \ +./dep/cryptocore/source/CC_API.d + + +# Each subdirectory must supply rules for building sources it contributes +dep/cryptocore/source/%.o: $(SSFLIB_SOURCE)/dep/cryptocore/source/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/dep/swdss/source/subdir.mk b/build/ssflib/dep/swdss/source/subdir.mk new file mode 100755 index 0000000..fd93294 --- /dev/null +++ b/build/ssflib/dep/swdss/source/subdir.mk @@ -0,0 +1,35 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(SSFLIB_SOURCE)/dep/swdss/source/file_op.cpp \ +$(SSFLIB_SOURCE)/dep/swdss/source/secure_file.cpp \ +$(SSFLIB_SOURCE)/dep/swdss/source/ss_api.cpp \ +$(SSFLIB_SOURCE)/dep/swdss/source/ss_crypto.cpp \ +$(SSFLIB_SOURCE)/dep/swdss/source/ss_misc.cpp \ +$(SSFLIB_SOURCE)/dep/swdss/source/ss_temp_store.cpp + +OBJS += \ +./dep/swdss/source/file_op.o \ +./dep/swdss/source/secure_file.o \ +./dep/swdss/source/ss_api.o \ +./dep/swdss/source/ss_crypto.o \ +./dep/swdss/source/ss_misc.o \ +./dep/swdss/source/ss_temp_store.o + +CPP_DEPS += \ +./dep/swdss/source/file_op.d \ +./dep/swdss/source/secure_file.d \ +./dep/swdss/source/ss_api.d \ +./dep/swdss/source/ss_crypto.d \ +./dep/swdss/source/ss_misc.d \ +./dep/swdss/source/ss_temp_store.d + + +# Each subdirectory must supply rules for building sources it contributes +dep/swdss/source/%.o: $(SSFLIB_SOURCE)/dep/swdss/source/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/dep/time/subdir.mk b/build/ssflib/dep/time/subdir.mk new file mode 100755 index 0000000..58955f9 --- /dev/null +++ b/build/ssflib/dep/time/subdir.mk @@ -0,0 +1,20 @@ +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +$(SSFLIB_SOURCE)/dep/time/ssf_time.cpp + +OBJS += \ +./dep/time/ssf_time.o + +CPP_DEPS += \ +./dep/time/ssf_time.d + + +# Each subdirectory must supply rules for building sources it contributes +dep/time/%.o: $(SSFLIB_SOURCE)/dep/time/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/dep/uci/source/subdir.mk b/build/ssflib/dep/uci/source/subdir.mk new file mode 100755 index 0000000..e103ce3 --- /dev/null +++ b/build/ssflib/dep/uci/source/subdir.mk @@ -0,0 +1,29 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(SSFLIB_SOURCE)/dep/uci/source/uci_aes_xcbc_mac.c \ +$(SSFLIB_SOURCE)/dep/uci/source/uci_api.c \ +$(SSFLIB_SOURCE)/dep/uci/source/uci_cryptocore.c \ +$(SSFLIB_SOURCE)/dep/uci/source/uci_hwcrypto.c + +OBJS += \ +./dep/uci/source/uci_aes_xcbc_mac.o \ +./dep/uci/source/uci_api.o \ +./dep/uci/source/uci_cryptocore.o \ +./dep/uci/source/uci_hwcrypto.o + +C_DEPS += \ +./dep/uci/source/uci_aes_xcbc_mac.d \ +./dep/uci/source/uci_api.d \ +./dep/uci/source/uci_cryptocore.d \ +./dep/uci/source/uci_hwcrypto.d + + +# Each subdirectory must supply rules for building sources it contributes +dep/uci/source/%.o: $(SSFLIB_SOURCE)/dep/uci/source/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/build/ssflib/makefile b/build/ssflib/makefile new file mode 100755 index 0000000..d979fa5 --- /dev/null +++ b/build/ssflib/makefile @@ -0,0 +1,72 @@ +# Directory where Simulator code is placed + +GIT_SDK = ../../.. +TOOLCHAIN_PATH = $(GIT_SDK)/toolchain/linux +TOOLCHAIN = $(TOOLCHAIN_PATH)/i386-linux-gnueabi-gcc-4.6/bin/i386-linux-gnueabi- +INCLUDE = $(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/usr/include/ +SYSROOT = --sysroot=$(TOOLCHAIN_PATH)/rootstraps/mobile-2.3-emulator.core/ + +HOME = $(GIT_SDK)/simulator +SSFLIB_SOURCE = $(HOME)/ssflib + +-include ../makefile.init + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include src/subdir.mk +-include dep/uci/source/subdir.mk +-include dep/time/subdir.mk +-include dep/swdss/source/subdir.mk +-include dep/cryptocore/source/middle/subdir.mk +-include dep/cryptocore/source/base/subdir.mk +-include dep/cryptocore/source/subdir.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C++_DEPS)),) +-include $(C++_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +ifneq ($(strip $(CC_DEPS)),) +-include $(CC_DEPS) +endif +ifneq ($(strip $(CPP_DEPS)),) +-include $(CPP_DEPS) +endif +ifneq ($(strip $(CXX_DEPS)),) +-include $(CXX_DEPS) +endif +ifneq ($(strip $(C_UPPER_DEPS)),) +-include $(C_UPPER_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: libssflib.so + +# Tool invocations +libssflib.so: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + $(TOOLCHAIN)g++ -L"../log" -L"../osal" $(SYSROOT) -fmessage-length=0 -shared -o "libssflib.so" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(OBJS)$(C++_DEPS)$(C_DEPS)$(CC_DEPS)$(LIBRARIES)$(CPP_DEPS)$(CXX_DEPS)$(C_UPPER_DEPS) libssflib.so + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/build/ssflib/objects.mk b/build/ssflib/objects.mk new file mode 100755 index 0000000..cc72611 --- /dev/null +++ b/build/ssflib/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := -lboost_thread -llog -losal -lrt + diff --git a/build/ssflib/sources.mk b/build/ssflib/sources.mk new file mode 100755 index 0000000..7ed1286 --- /dev/null +++ b/build/ssflib/sources.mk @@ -0,0 +1,33 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +O_SRCS := +CPP_SRCS := +C_UPPER_SRCS := +C_SRCS := +S_UPPER_SRCS := +OBJ_SRCS := +ASM_SRCS := +CXX_SRCS := +C++_SRCS := +CC_SRCS := +OBJS := +C++_DEPS := +C_DEPS := +CC_DEPS := +LIBRARIES := +CPP_DEPS := +CXX_DEPS := +C_UPPER_DEPS := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +src \ +dep/uci/source \ +dep/time \ +dep/swdss/source \ +dep/cryptocore/source/middle \ +dep/cryptocore/source/base \ +dep/cryptocore/source \ + diff --git a/build/ssflib/src/subdir.mk b/build/ssflib/src/subdir.mk new file mode 100755 index 0000000..6a5a5b6 --- /dev/null +++ b/build/ssflib/src/subdir.mk @@ -0,0 +1,44 @@ +# Add inputs and outputs from these tool invocations to the build variables +C_SRCS += \ +$(SSFLIB_SOURCE)/src/ssf_arithmetic.c \ +$(SSFLIB_SOURCE)/src/ssf_client.c \ +$(SSFLIB_SOURCE)/src/ssf_crypto.c \ +$(SSFLIB_SOURCE)/src/ssf_lib.c \ +$(SSFLIB_SOURCE)/src/ssf_malloc.c \ +$(SSFLIB_SOURCE)/src/ssf_panic.c \ +$(SSFLIB_SOURCE)/src/ssf_storage.c \ +$(SSFLIB_SOURCE)/src/ssf_taentrypoint.c \ +$(SSFLIB_SOURCE)/src/app_debug.c + +OBJS += \ +./src/ssf_arithmetic.o \ +./src/ssf_client.o \ +./src/ssf_crypto.o \ +./src/ssf_lib.o \ +./src/ssf_malloc.o \ +./src/ssf_panic.o \ +./src/ssf_storage.o \ +./src/ssf_taentrypoint.o \ +./src/app_debug.o + +C_DEPS += \ +./src/ssf_arithmetic.d \ +./src/ssf_client.d \ +./src/ssf_crypto.d \ +./src/ssf_lib.d \ +./src/ssf_malloc.d \ +./src/ssf_panic.d \ +./src/ssf_storage.d \ +./src/ssf_taentrypoint.d \ +./src/app_debug.d + + +# Each subdirectory must supply rules for building sources it contributes +src/%.o: $(SSFLIB_SOURCE)/src/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + $(TOOLCHAIN)g++ -D_SECOS_SIM_ -D__DEBUG__ -I"$(HOME)/ssflib/dep/cryptocore/include" -I"$(HOME)/log" -I"$(HOME)/osal" -I"$(HOME)/include/include" -I"$(HOME)/ssflib/dep/cryptocore/include/base" -I"$(HOME)/ssflib/dep/cryptocore/include/middle" -I"$(HOME)/ssflib/dep/swdss/include" -I"$(HOME)/ssflib/dep/uci/include" -I"$(HOME)/ssflib/inc" -I$(INCLUDE) -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/include/.cproject b/include/.cproject new file mode 100755 index 0000000..abef4a7 --- /dev/null +++ b/include/.cproject @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/.project b/include/.project new file mode 100755 index 0000000..5b839e7 --- /dev/null +++ b/include/.project @@ -0,0 +1,26 @@ + + + include + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/include/.settings/language.settings.xml b/include/.settings/language.settings.xml new file mode 100755 index 0000000..1408bef --- /dev/null +++ b/include/.settings/language.settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/.settings/org.eclipse.cdt.core.prefs b/include/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..ecae8d3 --- /dev/null +++ b/include/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.624722712/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.624722712/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.624722712/PATH/value=D\:\\eclipse\\eclipse-rcp-luna-SR1-win32-x86_64;C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x64;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files (x86)\\GitExtensions\\;D\:\\Tizen\\tizen-sdk\\tools;D\:\\Android\\android-sdk\\platform-tools;D\:\\Android\\android-ndk-r10c;C\:\\Program Files\\Perforce; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.624722712/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.624722712/appendContributed=true diff --git a/include/include/config.h b/include/include/config.h new file mode 100755 index 0000000..b4428d7 --- /dev/null +++ b/include/include/config.h @@ -0,0 +1,15 @@ +/* + * config.h + * + * Created on: May 20, 2015 + * Author: krishna.r + */ + +#ifndef INCLUDE_CONFIG_H_ +#define INCLUDE_CONFIG_H_ + +#define TEE_PROP_FILE "/usr/bin/GPD_TEE_PROP" +#define TA_ROOT "/tmp/" +#define TEE_TASTORE_ROOT "/tmp/tastore/" + +#endif /* INCLUDE_CONFIG_H_ */ diff --git a/include/include/tee_client_api.h b/include/include/tee_client_api.h new file mode 100755 index 0000000..c002367 --- /dev/null +++ b/include/include/tee_client_api.h @@ -0,0 +1,197 @@ +/* + * ===================================================================================== + * + * Filename: tee_client_api.h + * + * Description: TEEC API Header file + * + * Version: 1.0 + * Created: Thursday 26 March 2015 12:42:45 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef __TEE_CLIENT_API_H__ +#define __TEE_CLIENT_API_H__ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------------- + * TEE Client API types and constants definitions + *-----------------------------------------------------------------------------*/ +#define TEEC_SUCCESS 0x00000000 // The operation was successful +#define TEEC_ERROR_GENERIC 0xFFFF0000 // Non-specific cause +#define TEEC_ERROR_ACCESS_DENIED 0xFFFF0001 // Access privileges are not sufficient +#define TEEC_ERROR_CANCEL 0xFFFF0002 // The operation was cancelled +#define TEEC_ERROR_ACCESS_CONFLICT 0xFFFF0003 // Concurrent accesses caused conflict +#define TEEC_ERROR_EXCESS_DATA 0xFFFF0004 // Too much data for the requested operation was passed +#define TEEC_ERROR_BAD_FORMAT 0xFFFF0005 // Input data was of invalid format +#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 // Input parameters were invalid +#define TEEC_ERROR_BAD_STATE 0xFFFF0007 // Operation is not valid in the current state +#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008 // The requested data item is not found +#define TEEC_ERROR_NOT_IMPLEMENTED 0xFFFF0009 // The requested operation should exist but is not yet implemented +#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A // The requested operation is valid but is not supported in this Implementation +#define TEEC_ERROR_NO_DATA 0xFFFF000B // Expected data was missing +#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C // System ran out of resources +#define TEEC_ERROR_BUSY 0xFFFF000D // The system is busy working on something else. +#define TEEC_ERROR_COMMUNICATION 0xFFFF000E // Communication with a remote party failed. +#define TEEC_ERROR_SECURITY 0xFFFF000F // A security fault was detected. +#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 // The supplied buffer is too short for the generated output. +#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 // Targed TA panic'ed +#define TEEC_IMP_MIN 0x00000001 +#define TEEC_IMP_MAX 0xFFFEFFFF +#define TEEC_RFU_MIN 0xFFFF0011 +#define TEEC_RFU_MAX 0xFFFFFFFF + +#define TEEC_ORIGIN_API 0x1 +#define TEEC_ORIGIN_COMMS 0x2 +#define TEEC_ORIGIN_TEE 0x3 +#define TEEC_ORIGIN_TRUSTED_APP 0x4 + +#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE 0x800000 + +#define TEEC_MEM_INPUT (1 << 0) +#define TEEC_MEM_OUTPUT (1 << 1) + +#define TEEC_NONE 0x00000000 +#define TEEC_VALUE_INPUT 0x00000001 +#define TEEC_VALUE_OUTPUT 0x00000002 +#define TEEC_VALUE_INOUT 0x00000003 +#define TEEC_MEMREF_TEMP_INPUT 0x00000005 +#define TEEC_MEMREF_TEMP_OUTPUT 0x00000006 +#define TEEC_MEMREF_TEMP_INOUT 0x00000007 +#define TEEC_MEMREF_WHOLE 0x0000000C +#define TEEC_MEMREF_PARTIAL_INPUT 0x0000000D +#define TEEC_MEMREF_PARTIAL_OUTPUT 0x0000000E +#define TEEC_MEMREF_PARTIAL_INOUT 0x0000000F + +#define TEE_PARAM_TYPE_NONE 0x00000000 +#define TEE_PARAM_TYPE_VALUE_INPUT 0x00000001 +#define TEE_PARAM_TYPE_VALUE_OUTPUT 0x00000002 +#define TEE_PARAM_TYPE_VALUE_INOUT 0x00000003 +#define TEE_PARAM_TYPE_MEMREF_INPUT 0x00000005 +#define TEE_PARAM_TYPE_MEMREF_OUTPUT 0x00000006 +#define TEE_PARAM_TYPE_MEMREF_INOUT 0x00000007 + +#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 MAX_CONTEXT_NAME_LEN 128 + +typedef uint32_t TEEC_Result; + +typedef struct { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint8_t clockSeqAndNode[8]; +} TEEC_UUID; + +typedef struct { + void* imp; +} TEEC_Context; + +typedef struct { + void *imp; +} TEEC_Session; + +typedef struct { + void *buffer; + size_t size; + uint32_t flags; + void *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 struct { + uint32_t a; + uint32_t b; +} TEEC_Value; + +typedef union { + TEEC_TempMemoryReference tmpref; + TEEC_RegisteredMemoryReference memref; + TEEC_Value value; +} TEEC_Parameter; + +typedef struct { + uint32_t started; + uint32_t paramTypes; + TEEC_Parameter params[4]; + void *imp; +} TEEC_Operation; + +/*----------------------------------------------------------------------------- + * TEE Client API functions and macros definitions + *-----------------------------------------------------------------------------*/ +TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context); + +void TEEC_FinalizeContext(TEEC_Context *context); + +TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, + TEEC_SharedMemory *sharedMem); + +TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, + TEEC_SharedMemory *sharedMem); + +void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMem); + +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); + +void TEEC_CloseSession(TEEC_Session *session); + +TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, + uint32_t commandID, + TEEC_Operation *operation, + uint32_t *returnOrigin); + +void TEEC_RequestCancellation(TEEC_Operation *operation); + +#define TEEC_PARAM_TYPES(param0Type, param1Type, param2Type, param3Type) \ + (uint32_t)(((param0Type) & 0x7f) | \ + (((param1Type) & 0x7f) << 8) | \ + (((param2Type) & 0x7f) << 16) | \ + (((param3Type) & 0x7f) << 24)) + +#ifdef __cplusplus +} +#endif + +#endif /* __TEE_CLIENT_API_H__ */ diff --git a/include/include/tee_command.h b/include/include/tee_command.h new file mode 100755 index 0000000..2f1426a --- /dev/null +++ b/include/include/tee_command.h @@ -0,0 +1,38 @@ +/* + * ===================================================================================== + * + * Filename: tee_command.h + * + * Description: TEEC Connection Header file + * + * Version: 1.0 + * Created: 26 March 2015 12:43:30 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef __TEE_COMMAND_H__ +#define __TEE_COMMAND_H__ + +typedef enum { + INVALID = -1, + INITIALIZE_CONTEXT = 0, + OPEN_SESSION, + REGISTER_SHARED_MEMORY, + INVOKE_COMMAND, + RELEASE_SHARED_MEMORY, + REQUEST_CANCELLATION, + CLOSE_SESSION, + FINALIZE_CONTEXT, + OPEN_TA_SESSION, + INVOKE_TA_COMMAND, + CLOSE_TA_SESSION, + CHECK_MEMORY, + PANIC +} TEE_CMD; +#endif /* __TEE_COMMAND_H__ */ diff --git a/include/include/tee_internal_api.h b/include/include/tee_internal_api.h new file mode 100755 index 0000000..65025c5 --- /dev/null +++ b/include/include/tee_internal_api.h @@ -0,0 +1,2045 @@ +/* + * tee_internal_api.h + * + * This source file is proprietary property of Samsung Electronics Co., Ltd. + * + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Krishna Raghottam Devale + * + */ + +#ifndef __TEE_INTERNAL_API_H__ +#define __TEE_INTERNAL_API_H__ + +#ifndef ECC_IMPLEMENTATION +#define ECC_IMPLEMENTATION +#endif + +#include +#include +#include + +#define NON_GP_PADDING + +#ifndef CERTIFICATES_API +#define CERTIFICATES_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * 3 Common Definitions + ******************************************************************************/ + +//TEE_Result is the type used for return codes from the APIs. +typedef uint32_t TEE_Result; + +//TEE_UUID is the Universally Unique Resource Identifier +//This type is used to identify Trusted Applications and clients. +typedef struct { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint8_t clockSeqAndNode[8]; +} TEE_UUID; + +typedef enum { + TEE_SUCCESS = 0x00000000, + TEE_EXTERNAL_REQUEST = 0xEEEEEEEE, + TEE_ERROR_GENERIC = 0xFFFF0000, + TEE_ERROR_ACCESS_DENIED = 0xFFFF0001, + TEE_ERROR_CANCEL = 0xFFFF0002, + TEE_ERROR_ACCESS_CONFLICT = 0xFFFF0003, + TEE_ERROR_EXCESS_DATA = 0xFFFF0004, + TEE_ERROR_BAD_FORMAT = 0xFFFF0005, + TEE_ERROR_BAD_PARAMETERS = 0xFFFF0006, + TEE_ERROR_BAD_STATE = 0xFFFF0007, + TEE_ERROR_ITEM_NOT_FOUND = 0xFFFF0008, + TEE_ERROR_NOT_IMPLEMENTED = 0xFFFF0009, + TEE_ERROR_NOT_SUPPORTED = 0xFFFF000A, + TEE_ERROR_NO_DATA = 0xFFFF000B, + TEE_ERROR_OUT_OF_MEMORY = 0xFFFF000C, + TEE_ERROR_BUSY = 0xFFFF000D, + TEE_ERROR_COMMUNICATION = 0xFFFF000E, + TEE_ERROR_SECURITY = 0xFFFF000F, + TEE_ERROR_SHORT_BUFFER = 0xFFFF0010, + TEE_ERROR_TASK_NOT_FOUND = 0xFFFF0011, + TEE_PENDING = 0xFFFF2000, + TEE_ERROR_TIMEOUT = 0xFFFF3001, + TEE_ERROR_OVERFLOW = 0xFFFF300F, + TEE_ERROR_TARGET_DEAD = 0xFFFF3024, + TEE_ERROR_STORAGE_NO_SPACE = 0xFFFF3041, + TEE_ERROR_MAC_INVALID = 0xFFFF3071, + TEE_ERROR_SIGNATURE_INVALID = 0xFFFF3072, + TEE_ERROR_TIME_NOT_SET = 0xFFFF5000, + TEE_ERROR_TIME_NEEDS_RESET = 0xFFFF5001, + TEE_ERROR_CERT_PARSING = 0xFFFF6000, + TEE_ERROR_CRL_PARSING = 0xFFFF6001, + TEE_ERROR_CERT_EXPIRED = 0xFFFF6002, + TEE_ERROR_CERT_VERIFICATION = 0xFFFF6003, + + TEE_RESULT_NOT_READY = 0xFFFF0FFF + +} TEE_Error_Codes; + +#define TEE_HANDLE_NULL 0 +#define TEE_TIMEOUT_INFINITE (0xFFFFFFFF) +/****************************************************************************** + * 4. Trusted Core Framework API */ + +/****************************************************************************** + * 4.1 Data Types + ******************************************************************************/ + +typedef struct { + uint32_t login; + TEE_UUID uuid; +} TEE_Identity; + +typedef union { + struct { + void *buffer; + size_t size; + int memid; + } memref; + struct { + uint32_t a, b; + } value; +} TEE_Param; + +#define TEE_PARAM_TYPES(t0,t1,t2,t3) \ + ((t0) | ((t1) << 8) | ((t2) << 16) | ((t3) << 24)) + +#define TEE_PARAM_TYPE_GET(t, i) (((t) >> (i*8)) & 0x7F) + +typedef struct __TEE_TASessionHandle* TEE_TASessionHandle; + +typedef struct __TEE_PropSetHandle* TEE_PropSetHandle; + +/****************************************************************************** + * 4.2 Constants + ******************************************************************************/ + +#define TEE_PARAM_TYPE_NONE 0x00000000 +#define TEE_PARAM_TYPE_VALUE_INPUT 0x00000001 +#define TEE_PARAM_TYPE_VALUE_OUTPUT 0x00000002 +#define TEE_PARAM_TYPE_VALUE_INOUT 0x00000003 +#define TEE_PARAM_TYPE_MEMREF_INPUT 0x00000005 +#define TEE_PARAM_TYPE_MEMREF_OUTPUT 0x00000006 +#define TEE_PARAM_TYPE_MEMREF_INOUT 0x00000007 + +#define TEE_MEM_INPUT 0x00000001 +#define TEE_MEM_OUTPUT 0x00000002 + +#define TEE_LOGIN_PUBLIC 0x00000000 +#define TEE_LOGIN_USER 0x00000001 +#define TEE_LOGIN_GROUP 0x00000002 +#define TEE_LOGIN_APPLICATION 0x00000004 +#define TEE_LOGIN_APPLICATION_USER 0x00000005 +#define TEE_LOGIN_APPLICATION_GROUP 0x00000006 +#define TEE_LOGIN_TRUSTED_APP 0xF0000000 + +#define TEE_ORIGIN_API 0x1 +#define TEE_ORIGIN_COMMS 0x2 +#define TEE_ORIGIN_TEE 0x3 +#define TEE_ORIGIN_TRUSTED_APP 0x4 + +#define TEE_ACCESS_READ 0x00000001 +#define TEE_ACCESS_WRITE 0x00000002 +#define TEE_ACCESS_ANY_OWNER 0x00000004 + +#define TEE_PROPSET_TEE_IMPLEMENTATION (0xFFFFFFFD) +#define TEE_PROPSET_CURRENT_CLIENT (0xFFFFFFFE) +#define TEE_PROPSET_CURRENT_TA (0xFFFFFFFF) + +/****************************************************************************** + * 4.3 TA Interface + ******************************************************************************/ + +#define TA_EXPORT + +/** + * Trusted Application's constructor + * + * The function TA_CreateEntryPoint is the Trusted Application's constructor, + * which the Framework calls when it creates a new instance of the Trusted + * Application. To register instance data, the implementation of this + * constructor can use either global variables or the function + * @ref TEE_SetInstanceData. + * + * @return TEE_SUCCESS if the instance is successfully created. Any other value + * if any other code is returned, then the instance is not created, and no other + * entry points of this instance will be called. The Framework reclaims all + * resources and dereference all objects related to the creation of the + * instance. If this entry point was called as a result of a client opening a + * session, the error code is returned to the client and the session is not + * opened. + */ +TEE_Result TA_EXPORT TA_CreateEntryPoint(void); + +/** + * Trusted Application's destructor + * + * The function TA_DestroyEntryPoint is the Trusted Application's destructor, + * which the Framework calls when the instance is being destroyed. + * When the function TA_DestroyEntryPoint is called, the Framework guarantees + * that no client session is currently open. Once the call to + * TA_DestroyEntryPoint has been completed, no other entry point of this + * instance will ever be called. Note that when this function is called, all + * resources opened by the instance are still available. It is only after the + * function returns that the Implementation MUST start automatically reclaiming + * resources left opened. + * + * @return his function can return no success or error code. After this + * unction returns the mplementation Monsider sthe instance destroyed and + *Meclaim sall resources left open by the instance. + */ +void TA_EXPORT TA_DestroyEntryPoint(void); + +/** + * Connects to the Trusted Application instance to open a new session + * + * This function is called whenever a client attempts to connect to the Trusted + * Application instance to open a new session. If this function returns an + * error, the connection is rejected and no new session is opened. In this + * function, the Trusted Application can attach an opaque void* context to the + * session. This context is recalled in all subsequent TA calls within the + * session. + * + * @param[in] paramTypes The types of the four parameters. + * @param[in,out] params A pointer to an array of four parameters. + * @param[out] sessionContext A pointer to a variable that can be filled by the + * Trusted Application instance with an opaque void* data pointer + * + * @return EE_SUCCESS:Ii the session is successfully opened , and any other + * value if the session could not be opened. The error code may be one of the + * pre-defined codes, or may be a new error code defined by the + * Trusted Application implementation itself. In any case, the Implementation + * reports the error code to the client with the origin + * @ref TEEC_ORIGIN_TRUSTED_APP. + */ +TEE_Result TA_EXPORT TA_OpenSessionEntryPoint(uint32_t paramTypes, + TEE_Param params[4], + void** sessionContext); + +/** + * Closes a client session + * + * The Framework calls the function TA_CloseSessionEntryPoint to close a client + * session. The Trusted Application implementation is responsible for freeing + * any resources consumed by the session being closed. Note that the Trusted + * Application cannot refuse to close a session, but can hold the closing until + * it returns from TA_CloseSessionEntryPoint. This is why this function cannot + * return an error code. + * + * @param[in] sessionContext The value of the void* opaque data pointer set by + * the Trusted Application in the function @ref TA_OpenSessionEntryPoint for + * this session. + * + * @return his function can return no success or error code. + * + */ +void TA_EXPORT TA_CloseSessionEntryPoint(const void* sessionContext); + +/** + * Invokes a command within the given sessionContext + * + * The Framework calls the function TA_InvokeCommandEntryPoint when the client + * invokes a command within the given session. The Trusted Application can + * access the parameters sent by the client through the paramTypes and params + * arguments. It can also use these arguments to transfer response data back to + * the client. During the call to TA_InvokeCommandEntryPoint the client may + * request to cancel the operation. A command is always invoked within the + * context of a client session. Thus, any session function can be called by the + * command implementation. + * + * @param[in] sessionContext The value of the void* opaque data pointer set by + * the rusted Application in the function @ref TA_OpenSessionEntryPoint + * @param[in] commandID A Trusted Application-specific code that identifies the + * command to be invoked + * @param[in] paramTypes The types of the four parameters. + * @param[in,out] params A pointer to an array of four parameters. + * + * @return TEE_SUCCESS if the command is successfully executed, the function + * must return this value, and any other value if the invocation of the command + * fails for any reason. The error code may be one of the pre-defined codes, or + * may be a new error code defined by the Trusted Application implementation + * itself. In any case, the Implementation reports the error code to the client + * with the origin @ref TEEC_ORIGIN_TRUSTED_APP. + */ +TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(const void* sessionContext, + uint32_t commandID, + uint32_t paramTypes, + TEE_Param params[4]); + +/****************************************************************************** + * 4.4 Property Access Functions + ******************************************************************************/ + +/** + * Retrieves an individual property + * + * The TEE_GetPropertyAsString function performs a lookup in a property set to + * retrieve an individual property and convert its value into a printable + * string. When the lookup succeeds, the implementation converts the property + * into a printable string and copy the result into the buffer described by + * valueBuffer and valueBufferLen. + * + * @param[in] name A pointer to the zero-terminated string containing the name + * of the property to retrieve. Its content is case-sensitive and it must be + * encoded in UTF-8. + * @param[out] valueBuffer Output buffer for the property value + * @param[in] valueBufferLen Size of output buffer for the property value + * + * @return EE_SUCCESS:In case of success , EE_ERROR_ITEM_NOT_FOUND: i the + *property is not found or if name is not a valid UTF-8 encoding , + *TEE_ERROR_SHORT_BUFFER: i the value buffer is not large enough to hold the + *whole property value . + */ +TEE_Result __TEE_SetProperty( +// TEE_UUID *uuid, +const char *name, + char *valueBuffer, + size_t valueBufferLen, + int type); + +/** + * Retrieves property and convert its value into a tring + * + * The TEE_GetPropertyAsString function performs a lookup in a property set to + * retrieve an individual property and convert its value into a printable + * string. When the lookup succeeds, the implementation converts the property + * into a printable string and copy the result into the buffer described by + * valueBuffer and valueBufferLen. + * + * @param[in] propsetOrEnumerator One of the TEE_PROPSET_XXX pseudo-handles or a + * handle on a property enumerator + * @param[in] name A pointer to the zero-terminated string containing the name + * of the property to retrieve. Its content is case-sensitive and it must be + * encoded in UTF-8. + * @param[out] valueBuffer Output buffer for the property value + * @param[in] valueBufferLen: Size of output buffer for the property value + * + * @return EE_SUCCESS:Ii case of success , TEE_ERROR_ITEM_NOT_FOUND if the + * property is not found or if name is not a valid UTF-8 encoding, + * TEE_ERROR_SHORT_BUFFER if the value buffer is not large enough to hold the + * whole property value. + */ +extern TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + const char* name, + char* valueBuffer, + size_t* valueBufferLen); + +/** + * Retrieves property and convert its value into a Boolean + * + * The TEE_GetPropertyAsBool function retrieves a single property in a property + * set and converts its value to a Boolean. If a property cannot be viewed as a + * Boolean, this function returns TEE_ERROR_BAD_FORMAT. Otherwise, if this + * function succeeds, then calling the function @ref TEE_GetPropertyAsString on + * the same name and with a sufficiently large output buffer also succeed and + * return a string equal to true or false case-insensitive, depending on the + * value of the Boolean. + * + * @param[in] propsetOrEnumerator One of the TEE_PROPSET_XXX pseudo-handles or a + * handle on a property enumerator + * @param[in] name A pointer to the zero-terminated string containing the name + * of the property to retrieve. Its content is case-sensitive and must be + * encoded in UTF-8. + * @param[out] value A pointer to the variable that will contain the value of + * the property on success or false on error. + * + * @return EE_SUCCESS:Ii case of success , TEE_ERROR_ITEM_NOT_FOUND if the + * property is not found or if name is not a valid UTF-8 encoding, + * TEE_ERROR_BAD_FORMAT if the property value cannot be converted to a Boolean. + */ +TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, + const char* name, + bool* value); // commented fix build error + +/** + * Retrieves property and convert its value to a 32-bit unsigned integer + * + * + * The TEE_GetPropertyAsU32 function retrieves a single property in a property + * set and converts its value to a 32-bit unsigned integer. If a property cannot + * be viewed as a 32-bit unsigned integer, this function returns + * TEE_ERROR_BAD_FORMAT. Otherwise, if this function succeeds, then calling the + * function @ref TEE_GetPropertyAsString on the same name and with a + * sufficiently large output buffer also succeed and return a string that is + * consistent with the following syntax: + * integer: decimal-integer | hexadecimal-integer | binary-integer + * decimal-integer: [0-9,_]+{K,M}? + * hexadecimal-integer: 0[x,X][0-9,a-f,A-F,_]+ + * binary-integer: 0[b,B][0,1,_]+ + * Note that the syntax allows returning the integer either in decimal, + * hexadecimal, or binary format, that the representation can mix cases and can + * include underscores to separate groups of digits, and finally that the + * decimal representation may use 'K' or 'M' to denote multiplication by 1024 or + * 1048576 respectively. For example, here are a few acceptable representations + * of the number 1024: "1K", "0X400", "0b100_0000_0000". + * + * @param[in] propsetOrEnumerator One of the TEE_PROPSET_XXX pseudo-handles or a + * handle on a property enumerator + * @param[in] name A pointer to the zero-terminated string containing the name of + * the property to retrieve. Its content is case-sensitive and must be encoded + * in UTF-8. + * @param[out] value: A pointer to the variable that will contain the value of + * the property on success, or zero on error. + * + * @return EE_SUCCESS:Ii case of success ,TEE_ERROR_ITEM_NOT_FOUND:Ii the + * roperty is not found or if name is not a valid UTF-8 encoding , + * EE_ERROR_BAD_FORMAT: i the property value cannot be converted to an unsigned + *32-bit integer + */ +TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, + const char* name, + uint32_t* value); + +/** + * Retrieves property and convert its value into a binary block + * + * The function TEE_GetPropertyAsBinaryBlock retrieves an individual property + * and converts its value into a binary block. If a property cannot be viewed as + * a binary block, this function returns TEE_ERROR_BAD_FORMAT. Otherwise, if + * this function succeeds, then calling the function + * @ref TEE_GetPropertyAsString on the same name and with a sufficiently large + * output buffer also succeed and return a string that is consistent with a + * Base64 encoding of the binary block as defined in RFC 2045 [6], section 6.8 + * but with the following tolerance: + * + An Implementation is allowed not to encode the final padding '=' + * characters. + * + An Implementation is allowed to insert characters that are not in the + * Base64 character set. + * + * @param[in] propsetOrEnumerator One of the TEE_PROPSET_XXX pseudo-handles or a + * handle on a property enumerator + * @param[in] name A pointer to the zero-terminated string containing the name + * of the property to retrieve. Its content is case-sensitive and must be + * encoded in UTF-8. + * @param[out] valueBuffer Output buffer for the binary block + * @param[in] valueBufferLen Size of output buffer for the binary block + * + * @return EE_SUCCESS:Ii case of success , TEE_ERROR_ITEM_NOT_FOUND if the + * property is not found or if name is not a valid UTF-8 encoding, + * TEE_ERROR_BAD_FORMAT if the property cannot be retrieved as a binary block, + * TEE_ERROR_SHORT_BUFFER: If the value buffer is not large enough to hold the + * whole property value + */ +TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + const char* name, + void* valueBuffer, + size_t* valueBufferLen); + +/** + * Retrieves property and convert its value into a UUID + * + * The function TEE_GetPropertyAsUUID retrieves an individual property and + * converts its value into a UUID. If a property cannot be viewed as a UUID, + * this function returns TEE_ERROR_BAD_FORMAT. Otherwise, if this function + * succeeds, then calling the function @ref TEE_GetPropertyAsString on the same + * name and with a sufficiently large output buffer MUST also succeed and return + * a string that is consistent with the concrete syntax of UUIDs defined in RFC + * 4122. Note that this string may mix character cases. + * + * @param[in] propsetOrEnumerator One of the TEE_PROPSET_XXX pseudo-handles or + * a handle on a property enumerator + * @param[in] name A pointer to the zero-terminated string containing the name + * of the property to retrieve. ts content is case-sensitive and must be + *encoded in UTF-8. + * @param[out] value A pointer filled with the UUID. Must not be NULL. + * + * @return EE_SUCCESS:Ii case of success, TEE_ERROR_ITEM_NOT_FOUND if the + * property is not found or if name is not a valid UTF-8 encoding, + * TEE_ERROR_BAD_FORMAT if the property cannot be converted into a UUID + */ +TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, + const char* name, + TEE_UUID* value); + +/** + * Retrieves property and convert its value into a into a TEE_Identity + * + * The function TEE_GetPropertyAsIdentity retrieves an individual property and + * converts its value into a TEE_Identity. If this function succeeds then + * retrieving the property as a printable string using + * @ref TEE_GetPropertyAsString must return a string consistent with the + * following syntax: identity: integer (':' uuid)? where: The integer is + * consistent with the integer syntax described in the specification of the + * function @ref TEE_GetPropertyAsU32. If the identity UUID is Nil, then it can + * be omitted from the string representation of the property. + * + * @param[in] propsetOrEnumerator One of the TEE_PROPSET_XXX pseudo-handles or a + * handle on a property enumerator + * @param[in] name A pointer to the zero-terminated string containing the name + * of the property to retrieve. Its content is case-sensitive and must be + * encoded in UTF-8. + * @param[in] value A pointer filled with the identity. Must not be NULL. + * @return EE_SUCCESS: i case of success , TEE_ERROR_ITEM_NOT_FOUND if the + * property is not found or if name is not a valid UTF-8 encoding, + * TEE_ERROR_BAD_FORMAT if the property value cannot be converted into an + * Identity + */ +TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, + const char* name, + TEE_Identity* value); + +/** + * Allocates a property enumerator object + * + * The function TEE_AllocatePropertyEnumerator allocates a property enumerator + * object. Once a handle on a property enumerator has been allocated, it can be + * used to enumerate properties in a property set using the function + * @ref TEE_StartPropertyEnumerator. + * + * @param[in] enumerator A pointer filled with an opaque handle on the property + * enumerator on success and with TEE_HANDLE_NULL on error + * @return EE_SUCCESS: In case of success ; TEE_ERROR_OUT_OF_MEMORY: If there + * are not enough resources to allocate the property enumerator + */ +TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle* enumerator); + +/** + * Deallocates a property enumerator object + * + * The function TEE_FreePropertyEnumerator deallocates a property enumerator + * object. + * @param[in] enumerator A handle on the enumerator to free + */ +void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator); + +/** + * Starts to enumerate the properties in an enumerator + * + * The function TEE_StartPropertyEnumerator starts to enumerate the properties + * in an enumerator. Once an enumerator is attached to a property set: + * + * + Properties can be retrieved using one of the TEE_GetPropertyAsXXX + * functions, passing the enumerator handle as the property set and NULL as the + * name. + * + * + The function @ref TEE_GetPropertyName can be used to retrieve the name of + * the current property in the enumerator. + * + * + The function @ref TEE_GetNextProperty can be used to advance the + * enumeration to the next property in the property set. + * + * @param[in] enumerator A handle on the enumerator + * @param[in] propSet A pseudo-handle on the property set to enumerate. Must be + * one of the TEE_PROPSET_XXX pseudo-handles. + */ +void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, + TEE_PropSetHandle propSet); + +/** + * Resets a property enumerate to its state + * + * The function TEE_ResetPropertyEnumerator resets a property enumerate to its + * state immediately after allocation. If an enumeration is currently started, + * it is abandoned. + * + * @param[in] enumerator A handle on the enumerator to reset + */ +void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator); + +/** + * Gets the name of the current property + * + * The function TEE_GetPropertyName gets the name of the current property in an + * enumerator. The property name must the valid UTF-8 encoding of a Unicode + * string containing no U+0000 code points. + * + * @param[in] enumerator A handle on the enumerator + * @param[out] nameBufferThe The buffer filled with the name + * @param[in] nameBufferLen: Length of the buffer allocated by user + * + * @return TEE_SUCCESS: In case of success , TEE_ERROR_ITEM_NOT_FOUND: If there + * is no current property either because the enumerator has not started or + * because it has reached the end of the property set, TEE_ERROR_SHORT_BUFFER: + * If the name buffer is not large enough to contain the property name + */ +TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, + void* nameBuffer, + size_t* nameBufferLen); + +/** + * Advances the enumerator to the next property + * + * The function TEE_GetNextProperty advances the enumerator to the next + * property. + * + * @param[in] enumerator A handle on the enumerator + * + * @return EE_SUCCESS: In case of success , TEE_ERROR_ITEM_NOT_FOUND: If the + * enumerator has reached the end of the property set or if it has not started + */ +TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator); + +/****************************************************************************** + * 4.5 Trusted Application Configuration Properties + ******************************************************************************/ + +/****************************************************************************** + * 4.6 Client Properties + ******************************************************************************/ + +/****************************************************************************** + * 4.7 Implementation Properties + ******************************************************************************/ + +/****************************************************************************** + * 4.8 Panics + ******************************************************************************/ +/** + * Raises a Panic in the Trusted Application instance + * + * The TEE_Panic function raises a Panic in the Trusted Application instance. + * When a Trusted Application calls the TEE_Panic function, the current instance + * is destroyed and all the resources opened by the instance are reclaimed. All + * sessions opened from the panicking instance on another TA must be gracefully + * closed and all cryptographic objects and operations must be closed properly. + * When an instance panics, its clients receive the error code + * TEE_ERROR_TARGET_DEAD of origin TEE_ORIGIN_TEE until they close their + * session. This applies to Rich Execution Environment clients calling through + * the TEE Client API and to Trusted Execution Environment clients calling + * through the Internal Client API. Once an instance is panicked, no TA entry + * point is ever called again for this instance, not even TA_DestroyEntryPoint. + * The caller cannot expect that the TEE_Panic function will return. + * + * @param[in] panicCode An informative panic code defined by the TA. May be + * displayed in traces if traces are available. + */ +void TEE_Panic(TEE_Result panicCode); + +/****************************************************************************** + * 4.9 Internal Client API + ******************************************************************************/ +/** + * Opens a new session with a Trusted Application. (Not implemented yet!) + * + * The function TEE_OpenTASession opens a new session with a Trusted Application. + * The destination Trusted Application is identified by its UUID passed in + * destination. This UUID can be hardcoded in the caller code. An initial set of + * four parameters can be passed during the operation. The result of this function + * is returned both in the return value and the return origin, stored in the + * variable pointed to by returnOrigin: + * + * + If the return origin is different from TEE_ORIGIN_TRUSTED_APP, + * then the function has failed before it could reach the target Trusted + * Application. The possible error codes are listed in "Return Value" below. + * + * + If the return origin is TEE_ORIGIN_TRUSTED_APP, then the meaning of the return + * value depends on the protocol exposed by the target Trusted Application. + * + * However, if TEE_SUCCESS is returned, it always means that the session was + * successfully opened and if the function returns a value different from + * TEE_SUCCESS, it means that the session opening failed. When the session is + * successfully opened, i.e., when the function returns TEE_SUCCESS, a valid + * session handle is written into *session. Otherwise, the value TEE_HANDLE_NULL is + * written into *session. When a session is to be closed, the client Trusted + * Application must call the function @ref TEE_CloseTASession with the session + * handle. + * + * @param[in] destination A pointer to a TEE_UUID structure containing the UUID of + * the destination Trusted Application + * @param[in] cancellationRequestTimeout Timeout in milliseconds or the special + * value TEE_TIMEOUT_INFINITE if there is no timeout. After the timeout expires, a + * cancellation request for the operation must be automatically sent. + * @param[in] paramTypes The types of all parameters passed in the operation. + * @param[in,out] params: The parameters passed in the operation. + * @param[out] session: A pointer to a variable that will receive the client + * session handle. The pointer must not be NULL. The value is set to + * TEE_HANDLE_NULL upon error. + * @param[out] returnOrigin A pointer to a variable which will contain the return + * origin. This field may be NULL if the return origin is not needed. + * + * @return f the return origin is different from TEE_ORIGIN_TRUSTED_APP, one of + * he following error codes can be returned: + * + * + TEE_ERROR_OUT_OF_MEMORY: If not enough resources are available to open the + * session + * + * + TEE_ERROR_ITEM_NOT_FOUND: If no Trusted Application matches the requested + * destination UUID + * + * + TEE_ERROR_ACCESS_DENIED: If access to the destination Trusted Application is + * denied + * + * + TEE_ERROR_BUSY: If the destination Trusted Application does not allow more + * than one session at a time and already has a session in progress + * + * + TEE_ERROR_TARGET_DEAD: If the destination Trusted Application has panicked + * during the operation + */ +TEE_Result TEE_OpenTASession(const TEE_UUID* destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, + TEE_Param params[4], + TEE_TASessionHandle* session, + uint32_t* returnOrigin); + +/** + * Closes a client session (Not implemented yet!) + * + * The function TEE_CloseTASession closes a client session. + * + * @param[in] session An opened session handle + */ +void TEE_CloseTASession(TEE_TASessionHandle session); + +/** + * Invokes a command within a session opened between the client (Not implemented + * yet!) + * + * The function TEE_InvokeTACommand invokes a command within a session opened + * between the client. Trusted Application instance and a destination Trusted + * Application instance. The parameter session must reference a valid session + * handle opened by @ref TEE_OpenTASession. Up to four parameters can be passed + * during the operation. The result of this function is returned both in the + * return value and the return origin, stored in the variable pointed to by + * returnOrigin: + * + * + If the return origin is different from TEE_ORIGIN_TRUSTED_APP, then the + * function has failed before it could reach the destination Trusted + * Application. The possible error codes are listed in "Return Value" below. + * + * + If the return origin is TEE_ORIGIN_TRUSTED_APP, then the meaning of the + * return value is determined by the protocol exposed by the destination Trusted + * Application. It is recommended that the Trusted Application developer choose + * TEE_SUCCESS (0) to indicate success in their protocol, as this makes it + * possible to determine success or failure without looking at the return + * origin. + * + * @param[in] session: An opened session handle + * @param[in] cancellationRequestTimeout: Timeout in milliseconds or the special + * value TEE_TIMEOUT_INFINITE if there is no timeout. After the timeout expires, + * a cancellation request for the operation must be automatically sent. + * @param[in] commandID: The identifier of the Command to invoke. The meaning of + * each Command Identifier must be defined in the protocol exposed by the target + * Trusted Application. + * @param[in] paramTypes: The types of all parameters passed in the operation. + * @param[in] params: The parameters passed in the operation. + * @param[out] returnOrigin: A pointer to a variable which will contain the + * return origin. This field may be NULL if the return origin is not needed. + * + * @return If the return origin is different from TEE_ORIGIN_TRUSTED_APP, one of + * the following error codes can be returned: TEE_ERROR_OUT_OF_MEMORY: If not + * enough resources are available to perform the operation; + * TEE_ERROR_TARGET_DEAD: If the destination Trusted Application has panicked + * during the operation + */ +TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, + uint32_t cancellationRequestTimeout, + uint32_t commandID, + uint32_t paramTypes, + TEE_Param params[4], + uint32_t* returnOrigin); + +/****************************************************************************** + * 4.10 Cancellation Functions + ******************************************************************************/ +/** + * Determines whether the current task's Cancellation Flag is set + * + * The TEE_GetCancellationFlag function determines whether the current task's + * Cancellation Flag is set. If cancellations are masked, this function must + * return false. + * + * @return 'false' if the cancellation flag is not set or if cancellations are + * masked; 'true' if the cancellation flag is set and cancellations are not + * masked + */ +bool TEE_GetCancellationFlag(void); + +/** + * Unmasks the effects of cancellation + * + * The TEE_UnmaskCancellation function unmasks the effects of cancellation for + * the current task. When cancellation requests are unmasked, the Cancellation + * Flag interrupts cancellable functions such as @ref TEE_Wait and requests the + * cancellation of operations started with @ref TEE_OpenTASession or + * @ref TEE_InvokeTACommand. By default, tasks created to handle a TA entry + * point have cancellation masked, so that a TA does not have to cope with the + * effects of cancellation requests. + * @return 'true' if cancellations were masked prior to calling this function; + * 'false' otherwise + */ +bool TEE_UnmaskCancellation(void); + +/** + * Masks the effects of cancellation + * + * The TEE_MaskCancellation function masks the effects of cancellation for the + * current task. When cancellation requests are masked, the Cancellation Flag + * does not have an effect on the cancellable functions and cannot be retrieved + * using @ref TEE_GetCancellationFlag. By default, tasks created to handle a TA + * entry point have cancellation masked, so that a TA does not have to cope with + * the effects of cancellation requests. + * + * @return 'true' if cancellations were masked prior to calling this function; + * 'false' otherwise + */ +bool TEE_MaskCancellation(void); + +/****************************************************************************** + * 4.11 Memory Management Functions + ******************************************************************************/ + +#define HINT_FILL_WITH_ZEROS 0 +#define HINT_DEFAULT 0xFFFFFFFF + +#define UUID_STRING_LEN 37 +extern char *uuid2string(char *str, const TEE_UUID *uuid); +extern int string2uuid(TEE_UUID *uu, const char *in); + +enum { + TEE_MEMORY_ACCESS_READ = 1, + TEE_MEMORY_ACCESS_WRITE = 2, + TEE_MEMORY_ACCESS_ANY_OWNER = 4 +}; + +/** + * Checks specified buffer for access rights + * + * The TEE_CheckMemoryAccessRights function causes the Implementation to examine + * a buffer of memory specified in the parameters buffer and size and to + * determine whether the current Trusted Application instance has the access + * rights requested in the parameter accessFlags. If the characteristics of the + * buffer are compatible with accessFlags, then the function returns + * TEE_SUCCESS. Otherwise, it returns TEE_ERROR_ACCESS_DENIED. Note that the + * buffer should not be accessed by the function, but the Implementation should + * check the access rights based on the address of the buffer and internal + * memory management information. + * This function MUST NOT panic for any reason. + * + * @param[in] buffer Pointer to the buffer to check + * @param[in] size Size of the buffer to check + * @param[in] accessFlags The access flags to check + * + * @return TEE_SUCCESS: If the entire buffer allows the requested accesses or + * TEE_ERROR_ACCESS_DENIED: If at least one byte in the buffer is not accessible + * with the requested accesses + */ +TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, + void* buffer, + size_t size); + +/** + * Provides an alternative to writable global data + * + * The TEE_SetInstanceData and TEE_GetInstanceData functions provide an + * alternative to writable global data (writable variables with global scope and + * writable static variables with global or function scope). While an + * Implementation supports C global variables, using these functions may be + * sometimes more efficient, especially if only a single instance data variable + * is required. + * + * @param[in] instanceData A pointer to the global Trusted Application instance + * data. This pointer may be NULL. + */ +void TEE_SetInstanceData(void* instanceData); + +/** + * Retrieves the instance data pointer + * + * The TEE_GetInstanceData function retrieves the instance data pointer set by + * the Trusted Application using the @ref TEE_GetInstanceData function. + * + * @return The value returned is the previously set pointer to the Trusted + * Application instance data, or NULL if no instance data pointer has yet been + * set. + */ +void* TEE_GetInstanceData(void); + +/** + * Allocates space for an object + * + * The TEE_Malloc function allocates space for an object whose size in bytes is + * specified in the parameter size. + * + * @param[in] size The size of the buffer to be allocated. + * @param[in] hint A hint to the allocator. Currently defined values are as + * follows: + * + * + The default value, 0, guarantees that the returned block of memory is + * filled with zeros. + * + * + Values in the range [0x00000001, 0x7FFFFFFF] are reserved for future + * version of this specification. + * + * + Values in the range [0x80000000, 0xFFFFFFFF] can be used for + * implementation-defined hints. + * + * @return Upon successful completion, with size not equal to zero, the function + * returns a pointer to the allocated space. If the space cannot be allocated, a + * NULL pointer is returned. + */ +extern void* TEE_Malloc(size_t size, uint32_t hint); + +/** + * Changes the size of the memory object + * + * The TEE_Realloc function changes the size of the memory object pointed to by + * buffer to the size specified by nNewSize. + * + * @param[in] buffer: The pointer to the object to be reallocated + * @param[in] newSize: The new size required for the object + * + * @return Upon successful completion, TEE_Realloc returns a pointer to the + * (possibly moved) allocated space. If there is not enough available memory, + * TEE_Realloc returns a NULL pointer. + */ +extern void* TEE_Realloc(const void* buffer, uint32_t newSize); + +/** + * Causes the space pointed to by buffer to be deallocated + * + * The TEE_Free function causes the space pointed to by buffer to be + * deallocated; that is, made available for further allocation. If buffer is a + * NULL pointer, TEE_Free does nothing. Otherwise, it is a Programmer Error + * if the argument does not match a pointer previously returned by the + * @ref TEE_Malloc or @ref TEE_Realloc, or if the space has been deallocated by + * a call to TEE_Free or @ref TEE_Realloc. + * + * @param[in] buffer The pointer to the memory block to be freed + */ +extern void TEE_Free(const void *buffer); + +/** + * Copies size bytes from one object to another + * + * The TEE_MemMove function copies size bytes from the object pointed to by src + * into the object pointed to by dest. Note that the buffers dest and src can + * reside in any kinds of memory, including shared memory. + * + * @param[in] dest A pointer to the destination buffer + * @param[in] src A pointer to the source buffer + * @param[in] size The number of bytes to be copied + */ +void TEE_MemMove(void* dest, const void* src, uint32_t size); + +/** + * Compares bytes of one object to another + * + * The TEE_MemCompare function compares the first size bytes of the object + * pointed to by buffer1 to the first size bytes of the object pointed to by + * buffer2. Note that buffer1 and buffer2 can reside in any kinds of memory, + * including shared memory. + * + * @param[in] buffer1 A pointer to the first buffer + * @param[in] buffer2 A pointer to the second buffer + * @param[in] size The number of bytes to be compared + * + * @return The sign of a non-zero return value is determined by the sign of the + * difference between the values of the first pair of bytes (both interpreted as + * type uint8_t) that differ in the objects being compared. + * + * + If the first byte that differs is higher in buffer1, then return an integer + * greater than zero. + * + * + If the first size bytes of the two buffers are identical, then return zero. + * + * + If the first byte that differs is higher in buffer2, then return an integer + * lower than zero. + */ +int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size); + +/** + * Writes the byte x into the object + * + * The TEE_MemFill function writes the byte x (converted to a uint8_t) into the + * first size bytes of the object pointed to by buffer. Note that buffer can + * reside in any kinds of memory, including shared memory. + * + * @param[in] buffer A pointer to the destination buffer + * @param[in] x The value to be set + * @param[in] size The number of bytes to be set + */ +void TEE_MemFill(void* buffer, uint32_t x, uint32_t size); + +/****************************************************************************** + * 5 Trusted Storage API for Data and Keys + ******************************************************************************/ + +/****************************************************************************** + * 5.2 Data Types + ******************************************************************************/ + +typedef struct { + uint32_t attributeID; + union { + struct { + const void* buffer; + size_t length; + } ref; + struct { + uint32_t a, b; + } value; + } content; +} TEE_Attribute; + +typedef struct { + uint32_t objectType; + uint32_t objectSize; + uint32_t maxObjectSize; + uint32_t objectUsage; + uint32_t dataSize; + uint32_t dataPosition; + uint32_t handleFlags; +} TEE_ObjectInfo; + +typedef enum { + TEE_DATA_SEEK_SET = 0, TEE_DATA_SEEK_CUR, TEE_DATA_SEEK_END +} TEE_Whence; + +typedef struct __TEE_ObjectHandle* TEE_ObjectHandle; + +typedef struct __TEE_ObjectEnumHandle* TEE_ObjectEnumHandle; + +/****************************************************************************** + * 5.3 Constants + ******************************************************************************/ + +#define TEE_STORAGE_PRIVATE 0x00000001 + +// Data Flag Constants +#define TEE_DATA_FLAG_ACCESS_READ 0x00000001 +#define TEE_DATA_FLAG_ACCESS_WRITE 0x00000002 +#define TEE_DATA_FLAG_ACCESS_WRITE_META 0x00000004 +#define TEE_DATA_FLAG_SHARE_READ 0x00000010 +#define TEE_DATA_FLAG_SHARE_WRITE 0x00000020 +#define TEE_DATA_FLAG_CREATE 0x00000200 +#define TEE_DATA_FLAG_EXCLUSIVE 0x00000400 + +// Usage Constants +#define TEE_USAGE_EXTRACTABLE 0x00000001 +#define TEE_USAGE_ENCRYPT 0x00000002 +#define TEE_USAGE_DECRYPT 0x00000004 +#define TEE_USAGE_MAC 0x00000008 +#define TEE_USAGE_SIGN 0x00000010 +#define TEE_USAGE_VERIFY 0x00000020 +#define TEE_USAGE_DERIVE 0x00000040 + +// Handle Flag Constants +#define TEE_HANDLE_FLAG_PERSISTENT 0x00010000 +#define TEE_HANDLE_FLAG_INITIALIZED 0x00020000 +#define TEE_HANDLE_FLAG_KEY_SET 0x00040000 +#define TEE_HANDLE_FLAG_EXPECT_TWO_KEYS 0x00080000 + +// Operation Constants +#define TEE_OPERATION_CIPHER 1 +#define TEE_OPERATION_MAC 3 +#define TEE_OPERATION_AE 4 +#define TEE_OPERATION_DIGEST 5 +#define TEE_OPERATION_ASYMMETRIC_CIPHER 6 +#define TEE_OPERATION_ASYMMETRIC_SIGNATURE 7 +#define TEE_OPERATION_KEY_DERIVATION 8 + +// Miscellaneous Constants +#define TEE_DATA_MAX_POSITION 0xFFFFFFFF +#define TEE_OBJECT_ID_MAX_LEN 64 + +/****************************************************************************** + * 5.4 Generic Object Functions + ******************************************************************************/ + +/** + * Returns the characteristics of an object + * + * The TEE_GetObjectInfo function returns the characteristics of an object. + * + * @param[in] object Handle of the object + * @param[in] objectInfo Pointer to a structure filled with the object + * information + */ +void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo* objectInfo); + +/** + * Restricts the object usage + * + * The TEE_RestrictObjectUsage function restricts the object usage flags of an + * object handle to contain at most the flags passed in the objectUsage + * parameter. + * + * @param[in] object: Handle on an object + * @param[in] objectUsage: New object usage, an OR combination of one or more of + * the TEE_USAGE_XXX constants + */ +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage); + +/** + * Extracts one buffer attribute from an object + * + * The TEE_GetObjectBufferAttribute function extracts one buffer attribute from + * an object. + * + * Panic Reasons + * + * + object is not a valid opened object handle. + * + * + The object is not initialized. + * + * + Bit [29] of attributeID is not set to 0, so the attribute is not a buffer + * attribute + * + * + Bit [28] of attributeID is set to 1, denoting a protected attribute, and + * the object usage does not contain the TEE_USAGE_EXTRACTABLE flag. + * + * @param[in] object: Handle of the object + * @param[in] attributeID: Identifier of the attribute to retrieve + * @param[in] buffer, size: Output buffer to get the content of the attribute + * + * @return TEE_SUCCESS: In case of success; TEE_ERROR_ITEM_NOT_FOUND: If the + * attribute is not found on this object or if the object is a transient + * uninitialized object; TEE_ERROR_SHORT_BUFFER: If buffer is NULL or too small + * to contain the key part + */ +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, + void* buffer, + size_t* size); + +/** + * Extracts a value attribute from an object + * + * The TEE_GetObjectValueAttribute function extracts a value attribute from an + * object. + * + * Panic Reasons + * + object is not a valid opened object handle. + * + * + The object is not initialized. + * + * + Bit [29] of attributeID is not set to 1, so the attribute is not a value + * attribute. + * + * + Bit [28] of attributeID is set to 1, denoting a protected attribute, and + * the object usage does not contain the TEE_USAGE_EXTRACTABLE flag. + * + * @param[in] object Handle of the object + * + * @param[in] attributeID Identifier of the attribute to retrieve + * + * @param[in] a, @param[in] b Pointers on the placeholders filled with the + * attribute field a and b. Each can be NULL if the corresponding field is not + * of interest to the caller. + * + * @return TEE_SUCCESS: In case of success; TEE_ERROR_ITEM_NOT_FOUND: If the + * attribute is not found on this object or if the object is a transient + * uninitialized object; TEE_ERROR_ACCESS_DENIED: For an attempt to extract a + * secret part of a non-extractable container + */ +TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, + uint32_t attributeID, + uint32_t* a, + uint32_t* b); + +/** + * closes an opened object handle + * + * The TEE_CloseObject function closes an opened object handle. The object can + * be persistent or transient. + * Panic Reasons object is not a valid opened object handle and is not equal to + * TEE_HANDLE_NULL. + * + * @param[in] object Handle on the object to close. If set to TEE_HANDLE_NULL, + * does nothing. + */ +void TEE_CloseObject(TEE_ObjectHandle object); + +/****************************************************************************** + * 5.5 Transient Object Functions + ******************************************************************************/ + +/** + * Allocates an uninitialized transient object + * + * The TEE_AllocateTransientObject function allocates an uninitialized transient + * object, i.e., a container for attributes. Transient objects are used to hold + * a cryptographic object (key or key-pair). The object type and the maximum + * object characteristic size must be specified so that all the container + * resources can be pre-allocated. Note that a compliant Implementation must + * implement all the object types, algorithms, and object sizes + * + * @param[in] objectType: Type of uninitialized object container to be created + * @param[in] maxObjectSize: Size of the object. The interpretation of this + * parameter depends on the object type. + * @param[out] object: Filled with a handle on the newly created key container + * + * @return TEE_SUCCESS: On success; TEE_ERROR_OUT_OF_MEMORY: If not enough + * resources are available to allocate the object handle; + * TEE_ERROR_NOT_SUPPORTED: If the object size is not supported. + */TEE_Result TEE_AllocateTransientObject(uint32_t objectType, + uint32_t maxObjectSize, + TEE_ObjectHandle* object); + +/* + * Description + * The TEE_FreeTransientObject function deallocates a transient object previously allocated with TEE_AllocateTransientObject. + * After this function has been called, the object handle is no longer valid and all resources associated with the transient object + * must have been reclaimed. + * If the object is initialized, the object attributes are cleared before the object is deallocated. + * This function cannot fail. It does nothing if object is TEE_HANDLE_NULL. + * Parameters + * + object: Handle on the object to free + * Panic Reasons + * + object is not a valid opened object handle and is not equal to TEE_HANDLE_NULL. + */ +void TEE_FreeTransientObject(TEE_ObjectHandle object); + +/* + * Description + * The TEE_ResetTransientObject function resets a transient object to its initial state after allocation. + * If the object is currently initialized, the function clears the object of all its material. + * The object is then uninitialized again. + * In any case, the function resets the key usage of the container to 0xFFFFFFFFF. + * This function does nothing if object is set to TEE_HANDLE_NULL. + * Parameters + * + object: Handle on a transient object to reset + * Panic Reasons + * + object is not a valid opened object handle and is not equal to TEE_HANDLE_NULL. + */ +void TEE_ResetTransientObject(TEE_ObjectHandle object); + +/* + * Description + * The TEE_PopulateTransientObject function populates an uninitialized object container + * with object attributes passed by the TA in the attrs parameter. + * Parameters + * + object: Handle on an already created transient and uninitialized object + * + attrs, attrCount: Array of object attributes + * Return Value + * + TEE_SUCCESS: In case of success. In this case, the content of the object MUST be initialized. + * + TEE_ERROR_BAD_PARAMETERS: If an incorrect or inconsistent attribute value is detected. + * In this case, the content of the object container MUST remain uninitialized. + * Panic Reasons + * + object is not a valid opened object handle that is transient and uninitialized. + * + Some mandatory attribute is missing. + */ +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + const TEE_Attribute* attrs, + uint32_t attrCount); + +/* + * Description + * The TEE_InitRefAttribute and TEE_InitValueAttribute helper functions can be used to populate a single + * attribute either with a reference to a buffer or with integer values. + * + */ + +void TEE_InitRefAttribute(TEE_Attribute* attr, + uint32_t attributeID, + const void* buffer, + size_t length); + +void TEE_InitValueAttribute(TEE_Attribute* attr, + uint32_t attributeID, + uint32_t a, + uint32_t b); + +/* + * Description + * The TEE_CopyObjectAttributes function populates an uninitialized object handle with the attributes of another object handle; + * that is, it populates the attributes of destObject with the attributes of srcObject. It is most useful in the following situations: + * Parameters + * + destObject: Handle on an uninitialized transient object + * + srcObject: Handle on an initialized object + * Panic Reasons + * + srcObject is not initialized. + * + destObject is not uninitialized. + * + The type and size of srcObject and destObject are not compatible. + * */ +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject); + +/* + * Description + * The TEE_GenerateKey function generates a random key or a key-pair and populates a transient key object with the generated key material. + * Parameters + * + object: Handle on an uninitialized transient key to populate with the generated key + * + keySize: Requested key size. Must be less than or equal to the maximum size of the object container. + * + params, paramCount: Parameters for the key generation + * Return Value + * + TEE_SUCCESS: On success + * + TEE_ERROR_BAD_PARAMETERS: If an incorrect or inconsistent attribute is detected + * Panic Reasons + * + object is not a valid opened object handle that is transient and uninitialized. + * + keySize is too large. + + A mandatory parameter is missing. + */ +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, + uint32_t keySize, + const TEE_Attribute* params, + uint32_t paramCount); + +/****************************************************************************** + * 5.6 Persistent Object Functions + ******************************************************************************/ + +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, + const void* objectID, + size_t objectIDLen, + uint32_t flags, + TEE_ObjectHandle* object); + +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, + const void* objectID, + size_t objectIDLen, + uint32_t flags, + TEE_ObjectHandle attributes, + const void* initialData, + size_t initialDataLen, + TEE_ObjectHandle* object); +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void* newObjectID, + size_t newObjectIDLen); +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object); + +/****************************************************************************** + * 5.7 Persistent Object Enumeration Functions + ******************************************************************************/ + +TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle* objectEnumerator); +void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); +void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); +TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator, + uint32_t storageID); +TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + TEE_ObjectInfo* objectInfo, + void* objectID, + size_t* objectIDLen); + +/****************************************************************************** + * 5.8 Data Stream Access Functions + ******************************************************************************/ + +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, + void* buffer, + size_t size, + uint32_t* count); +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, + const void* buffer, + size_t size); +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size); +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, + int32_t offset, + TEE_Whence whence); + +TEE_Result storage_to_disk(void); +TEE_Result storage_from_disk(void); + +/****************************************************************************** + * 6 Cryptographic Operations API + ******************************************************************************/ + +/****************************************************************************** + * 6.1 Data Types + ******************************************************************************/ + +typedef enum { + TEE_MODE_ENCRYPT, // Encryption mode + TEE_MODE_DECRYPT, // Decryption mode + TEE_MODE_SIGN, // Signature generation mode + TEE_MODE_VERIFY, // Signature verification mode + TEE_MODE_MAC, // MAC mode + TEE_MODE_DIGEST, // Digest mode + TEE_MODE_DERIVE // Key derivation mode +} TEE_OperationMode; + +typedef struct { + uint32_t algorithm; + uint32_t operationClass; + uint32_t mode; + uint32_t digestLength; + uint32_t maxKeySize; + uint32_t keySize; + uint32_t requiredKeyUsage; + uint32_t handleState; +} TEE_OperationInfo; + +typedef struct __TEE_OperationHandle* TEE_OperationHandle; + +/****************************************************************************** + * 6.2 Generic Operation Functions + ******************************************************************************/ + +TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, + uint32_t algorithm, + uint32_t mode, + uint32_t maxKeySize); +void TEE_FreeOperation(TEE_OperationHandle operation); +void TEE_GetOperationInfo(TEE_OperationHandle operation, + TEE_OperationInfo* operationInfo); +void TEE_ResetOperation(TEE_OperationHandle operation); +TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key); +TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, + TEE_ObjectHandle key2); +void TEE_CopyOperation(TEE_OperationHandle dstOperation, + TEE_OperationHandle srcOperation); + +/****************************************************************************** + * 6.3 Message Digest Functions + ******************************************************************************/ + +void TEE_DigestUpdate(TEE_OperationHandle operation, + const void* chunk, + size_t chunkSize); +TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, + const void* chunk, + size_t chunkLen, + void* hash, + size_t *hashLen); + +/****************************************************************************** + * 6.4 Symmetric Cipher Functions + ******************************************************************************/ + +void TEE_CipherInit(TEE_OperationHandle operation, const void* IV, size_t IVLen); +TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, + const void* srcData, + size_t srcLen, + void* destData, + size_t *destLen); +TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, + const void* srcData, + size_t srcLen, + void* destData, + size_t *destLen); + +/****************************************************************************** + * 6.5 MAC Functions + ******************************************************************************/ + +void TEE_MACInit(TEE_OperationHandle operation, const void* IV, size_t IVLen); +void TEE_MACUpdate(TEE_OperationHandle operation, + const void* chunk, + size_t chunkSize); +TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, + const void* message, + size_t messageLen, + void* mac, + size_t *macLen); +TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, + const void* message, + size_t messageLen, + const void* mac, + size_t *macLen); + +/****************************************************************************** + * 6.6 Authenticated Encryption Functions + ******************************************************************************/ + +TEE_Result TEE_AEInit(TEE_OperationHandle operation, + const void* nonce, + size_t nonceLen, + uint32_t tagLen, + uint32_t AADLen, + uint32_t payloadLen); +void TEE_AEUpdateAAD(TEE_OperationHandle operation, + const void* AADdata, + size_t AADdataLen); +TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, + const void* srcData, + size_t srcLen, + void* destData, + size_t *destLen); +TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, + const void* srcData, + size_t srcLen, + void* destData, + size_t* destLen, + void* tag, + size_t* tagLen); +TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void* srcData, + size_t srcLen, + void* destData, + size_t *destLen, + void* tag, + size_t tagLen); + +/****************************************************************************** + * 6.7 Asymmetric Functions + ******************************************************************************/ + +TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, + const TEE_Attribute* params, + uint32_t paramCount, + const void* srcData, + size_t srcLen, + void* destData, + size_t *destLen); + +TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, + const TEE_Attribute* params, + uint32_t paramCount, + const void* srcData, + size_t srcLen, + void* destData, + size_t *destLen); +TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, + const TEE_Attribute* params, + uint32_t paramCount, + const void* digest, + size_t digestLen, + void* signature, + size_t *signatureLen); +TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, + const TEE_Attribute* params, + uint32_t paramCount, + const void* digest, + size_t digestLen, + void* signature, + size_t signatureLen); + +/****************************************************************************** + * 6.8 Key Derivation Functions + ******************************************************************************/ + +void TEE_DeriveKey(TEE_OperationHandle operation, + const TEE_Attribute* params, + uint32_t paramCount, + TEE_ObjectHandle derivedKey); + +/****************************************************************************** + * 6.9 Random Data Generation Function + ******************************************************************************/ + +void TEE_GenerateRandom(void* randomBuffer, size_t randomBufferLen); + +/****************************************************************************** + * 6.10 Cryptographic Algorithms Specification + ******************************************************************************/ + +typedef enum { + TEE_ALG_AES_ECB_NOPAD = 0x10000010, + TEE_ALG_AES_CBC_NOPAD = 0x10000110, + TEE_ALG_AES_CTR = 0x10000210, + TEE_ALG_AES_CTS = 0x10000310, + TEE_ALG_AES_XTS = 0x10000410, + TEE_ALG_AES_CBC_MAC_NOPAD = 0x30000110, + TEE_ALG_AES_CBC_MAC_PKCS5 = 0x30000510, + TEE_ALG_AES_CMAC = 0x30000610, + TEE_ALG_AES_CCM = 0x40000710, + TEE_ALG_AES_GCM = 0x40000810, + TEE_ALG_DES_ECB_NOPAD = 0x10000011, + TEE_ALG_DES_CBC_NOPAD = 0x10000111, + TEE_ALG_DES_CBC_MAC_NOPAD = 0x30000111, + TEE_ALG_DES_CBC_MAC_PKCS5 = 0x30000511, + TEE_ALG_DES3_ECB_NOPAD = 0x10000013, + TEE_ALG_DES3_CBC_NOPAD = 0x10000113, + TEE_ALG_DES3_CBC_MAC_NOPAD = 0x30000113, + TEE_ALG_DES3_CBC_MAC_PKCS5 = 0x30000513, + TEE_ALG_RSASSA_PKCS1_V1_5_MD5 = 0x70001830, + TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 = 0x70002830, + TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 = 0x70003830, + TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 = 0x70004830, + TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 = 0x70005830, + TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 = 0x70006830, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 = 0x70212930, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 = 0x70313930, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 = 0x70414930, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 = 0x70515930, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 = 0x70616930, + TEE_ALG_RSAES_PKCS1_V1_5 = 0x60000130, + TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1 = 0x60212230, + TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224 = 0x60213230, + TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256 = 0x60214230, + TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384 = 0x60215230, + TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512 = 0x60216230, + TEE_ALG_RSA_NOPAD = 0x60000030, + TEE_ALG_DSA_SHA1 = 0x70002131, + TEE_ALG_DH_DERIVE_SHARED_SECRET = 0x80000032, + TEE_ALG_MD5 = 0x50000001, + TEE_ALG_SHA1 = 0x50000002, + TEE_ALG_SHA224 = 0x50000003, + TEE_ALG_SHA256 = 0x50000004, + TEE_ALG_SHA384 = 0x50000005, + TEE_ALG_SHA512 = 0x50000006, + TEE_ALG_HMAC_MD5 = 0x30000001, + TEE_ALG_HMAC_SHA1 = 0x30000002, + TEE_ALG_HMAC_SHA224 = 0x30000003, + TEE_ALG_HMAC_SHA256 = 0x30000004, + TEE_ALG_HMAC_SHA384 = 0x30000005, + TEE_ALG_HMAC_SHA512 = 0x30000006, +#ifdef ECC_IMPLEMENTATION + TEE_ALG_ECDSA_P160 = 0x70000041, //P160 + TEE_ALG_ECDSA_P192 = 0x70001041, //P192 + TEE_ALG_ECDSA_P224 = 0x70002041, //P224 + TEE_ALG_ECDSA_P256 = 0x70003041, //P256 + TEE_ALG_ECDSA_P384 = 0x70004041, //P384 + TEE_ALG_ECDSA_P521 = 0x70005041, //P521 + TEE_ALG_ECDH_P192 = 0x80001042, //P192 + TEE_ALG_ECDH_P224 = 0x80002042, //P224 + TEE_ALG_ECDH_P256 = 0x80003042, //P256 + TEE_ALG_ECDH_P384 = 0x80004042, //P384 + TEE_ALG_ECDH_P521 = 0x80005042, //P521 +#endif // ECC_IMPLEMENTATION +#ifdef NON_GP_PADDING + TEE_ALG_AES_ECB_PKCS5 = 0x11000010, + TEE_ALG_AES_ECB_PKCS7 = 0x12000010, + TEE_ALG_AES_ECB_ISO9797_M1 = 0x13000010, + TEE_ALG_AES_ECB_ISO9797_M2 = 0x14000010, + TEE_ALG_AES_CBC_PKCS5 = 0x11000110, + TEE_ALG_AES_CBC_PKCS7 = 0x12000110, + TEE_ALG_AES_CBC_ISO9797_M1 = 0x13000110, + TEE_ALG_AES_CBC_ISO9797_M2 = 0x14000110, + TEE_ALG_AES_CTR_NOPAD = 0x15000210, +#endif +} TEE_CRYPTO_ALGORITHMS; + +typedef enum { + TEE_TYPE_AES = 0xA0000010, + TEE_TYPE_DES = 0xA0000011, + TEE_TYPE_DES3 = 0xA0000013, + TEE_TYPE_HMAC_MD5 = 0xA0000001, + TEE_TYPE_HMAC_SHA1 = 0xA0000002, + TEE_TYPE_HMAC_SHA224 = 0xA0000003, + TEE_TYPE_HMAC_SHA256 = 0xA0000004, + TEE_TYPE_HMAC_SHA384 = 0xA0000005, + TEE_TYPE_HMAC_SHA512 = 0xA0000006, + TEE_TYPE_RSA_PUBLIC_KEY = 0xA0000030, + TEE_TYPE_RSA_KEYPAIR = 0xA1000030, + TEE_TYPE_DSA_PUBLIC_KEY = 0xA0000031, + TEE_TYPE_DSA_KEYPAIR = 0xA1000031, + TEE_TYPE_DH_KEYPAIR = 0xA1000032, +#ifdef ECC_IMPLEMENTATION + TEE_TYPE_ECDSA_PUBLIC_KEY = 0xA0000033, + TEE_TYPE_ECDSA_KEYPAIR = 0xA1000033, + TEE_TYPE_ECDH_KEYPAIR = 0xA1000034, +#endif // ECC_IMPLEMENTATION + TEE_TYPE_GENERIC_SECRET = 0xA0000000, + TEE_TYPE_CERT_ROOT_GSL = 0xA00000A0, // GPD System Loader root Certificate + TEE_TYPE_CERT_ROOT_AP = 0xA00000A1, //Application provider root Certificate + TEE_TYPE_CERT_ROOT_CRL = 0xA00000A2, //Certificate type CRL + TEE_TYPE_CERT_GENERAL_AP1 = 0xA00000A3 +// more for application certificate? +} TEE_OBJECT_TYPES; + +/****************************************************************************** + * 6.11 Object or Operation Attributes + ******************************************************************************/ + +typedef enum { + TEE_ATTR_SECRET_VALUE = 0xC0000000, + TEE_ATTR_RSA_MODULUS = 0xD0000130, + TEE_ATTR_RSA_PUBLIC_EXPONENT = 0xD0000230, + TEE_ATTR_RSA_PRIVATE_EXPONENT = 0xC0000330, + TEE_ATTR_RSA_PRIME1 = 0xC0000430, + TEE_ATTR_RSA_PRIME2 = 0xC0000530, + TEE_ATTR_RSA_EXPONENT1 = 0xC0000630, + TEE_ATTR_RSA_EXPONENT2 = 0xC0000730, + TEE_ATTR_RSA_COEFFICIENT = 0xC0000830, + TEE_ATTR_DSA_PRIME = 0xD0001031, + TEE_ATTR_DSA_SUBPRIME = 0xD0001131, + TEE_ATTR_DSA_BASE = 0xD0001231, + TEE_ATTR_DSA_PUBLIC_VALUE = 0xD0000131, + TEE_ATTR_DSA_PRIVATE_VALUE = 0xC0000231, + TEE_ATTR_DH_PRIME = 0xD0001032, + TEE_ATTR_DH_SUBPRIME = 0xD0001132, + TEE_ATTR_DH_BASE = 0xD0001232, + TEE_ATTR_DH_X_BITS = 0xF0001332, + TEE_ATTR_DH_PUBLIC_VALUE = 0xD0000132, + TEE_ATTR_DH_PRIVATE_VALUE = 0xC0000232, + TEE_ATTR_RSA_OAEP_LABEL = 0xD0000930, + TEE_ATTR_RSA_PSS_SALT_LENGTH = 0xF0000A30, + +#ifdef ECC_IMPLEMENTATION + TEE_ATTR_ECDSA_PRIME = 0xD0001041, + TEE_ATTR_ECDSA_COFF_A = 0xD0001141, + TEE_ATTR_ECDSA_COFF_B = 0xD0001241, + TEE_ATTR_ECDSA_GENERATOR_X = 0xD0001341, + TEE_ATTR_ECDSA_GENERATOR_Y = 0xD0001441, + TEE_ATTR_ECDSA_ORDER = 0xD0001541, + TEE_ATTR_ECDSA_PUBLIC_VALUE_X = 0xD0002141, + TEE_ATTR_ECDSA_PUBLIC_VALUE_Y = 0xD0003141, + TEE_ATTR_ECDSA_PRIVATE_VALUE = 0xC0000241, +#endif // ECC_IMPLEMENTATION + +//Certificate attribute start + TEE_ATTR_CERT_RAW = 0xD0000A01, + TEE_ATTR_CERT_TBS = 0xD0000A02, + TEE_ATTR_CERT_VERSION = 0xF0000A01, + TEE_ATTR_CERT_SERIAL = 0xD0000A03, + TEE_ATTR_CERT_SIG_OID1 = 0xD0000A04, + TEE_ATTR_CERT_ISSUER_RAW = 0xD0000A05, + TEE_ATTR_CERT_SUBJECT_RAW = 0xD0000A06, + TEE_ATTR_CERT_ISSUER = 0xD0000A07, + TEE_ATTR_CERT_SUBJECT = 0xD0000A08, + TEE_ATTR_CERT_VALID_FROM = 0xD0000A09, + TEE_ATTR_CERT_VALID_TO = 0xD0000A0A, + TEE_ATTR_CERT_PK_OID = 0xD0000A0B, + TEE_ATTR_CERT_ISSUER_ID = 0xD0000A0C, + TEE_ATTR_CERT_SUBJECT_ID = 0xD0000A0D, + TEE_ATTR_CERT_V3EXT = 0xD0000A0E, + TEE_ATTR_CERT_EXT_TYPE = 0xF0000A02, + TEE_ATTR_CERT_CA_ISTRUE = 0xF0000A03, + TEE_ATTR_CERT_MAX_PATHLEN = 0xF0000A04, + TEE_ATTR_CERT_KEY_USAGE = 0xF0000A05, + TEE_ATTR_CERT_EXT_KEY_USAGE = 0xD0000A0F, + TEE_ATTR_CERT_KEY_NS_TYPE = 0xF0000A06, + TEE_ATTR_CERT_SIG_OID2 = 0xD0000A10, + TEE_ATTR_CERT_SIG = 0xD0000A11, + TEE_ATTR_CERT_SIG_ALGO = 0xF0000A07, + TEE_ATTR_CERT_NEXT_CHAIN = 0xD0000A12, + //Certificate attribute end + + TEE_ATTR_FLAG_VALUE = 0x20000000, + TEE_ATTR_FLAG_PUBLIC = 0x10000000 +} TEE_OBJECT_ATTRIBUTES; + +/****************************************************************************** + * 7 Time API + ******************************************************************************/ + +/****************************************************************************** + * 7.1 Data Types + ******************************************************************************/ + +typedef struct { + uint32_t seconds; + uint32_t millis; +} TEE_Time; + +/****************************************************************************** + * 7.2 Time Functions + ******************************************************************************/ + +void TEE_GetSystemTime(TEE_Time* time); +TEE_Result TEE_Wait(uint32_t timeout); +TEE_Result TEE_GetTAPersistentTime(TEE_Time* time); +TEE_Result TEE_SetTAPersistentTime(TEE_Time* time); +void TEE_GetREETime(TEE_Time* time); + +/****************************************************************************** + * 8 TEE Arithmetical API + ******************************************************************************/ + +/****************************************************************************** + * 8.3 Data Types + ******************************************************************************/ + +typedef uint32_t TEE_BigInt; +typedef uint32_t TEE_BigIntFMMContext; +typedef uint32_t TEE_BigIntFMM; + +/****************************************************************************** + * 8.4 Memory Allocation and Size of Objects + ******************************************************************************/ + +#define TEE_BigIntSizeInU32(n) ((((n)+31)/32)+2+4) + +size_t TEE_BigIntFMMContextSizeInU32(const size_t modulusSizeInBits); +size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits); + +/****************************************************************************** + * 8.5 Initialization Functions + ******************************************************************************/ + +void TEE_BigIntInit(TEE_BigInt* value, size_t length/*in uint32_t*/); +void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext* context, + size_t len, + const TEE_BigInt* modulus); +void TEE_BigIntInitFMM(TEE_BigIntFMM* object, size_t len); + +/****************************************************************************** + * 8.6 Converter Functions + ******************************************************************************/ + +TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt* dest, + const uint8_t* buffer, + const size_t sz_buffer, + const int32_t sign); +TEE_Result TEE_BigIntConvertToOctetString(void* buffer, + size_t* sz_buffer_out, + const TEE_BigInt* value); +void TEE_BigIntConvertFromS32(TEE_BigInt* result, int32_t input); +TEE_Result TEE_BigIntConvertToS32(int32_t* result, const TEE_BigInt* input); + +/****************************************************************************** + * 8.7 Logical Operations + ******************************************************************************/ + +int32_t TEE_BigIntCmp(const TEE_BigInt* op1, const TEE_BigInt* op2); +int32_t TEE_BigIntCmpS32(const TEE_BigInt* value1, int32_t value2); +void TEE_BigIntShiftRight(TEE_BigInt* destination, + const TEE_BigInt* source, + size_t bits); +bool TEE_BigIntGetBit(const TEE_BigInt* object, uint32_t index); +uint32_t TEE_BigIntGetBitCount(const TEE_BigInt* object); + +/****************************************************************************** + * 8.8 Basic Arithmetic Operations + ******************************************************************************/ + +void TEE_BigIntAdd(TEE_BigInt* dest, + const TEE_BigInt* op1, + const TEE_BigInt* op2); +void TEE_BigIntSub(TEE_BigInt* dest, + const TEE_BigInt* op1, + const TEE_BigInt* op2); +void TEE_BigIntNeg(TEE_BigInt* dest, const TEE_BigInt* op); +void TEE_BigIntMul(TEE_BigInt* dest, + const TEE_BigInt* op1, + const TEE_BigInt* op2); +void TEE_BigIntSquare(TEE_BigInt* dest, const TEE_BigInt* op); +void TEE_BigIntDiv(TEE_BigInt* dest_q, + TEE_BigInt* dest_r, + const TEE_BigInt* op1, + const TEE_BigInt* op2); + +/****************************************************************************** + * 8.9 Modular Arithmetic Operations + ******************************************************************************/ + +void TEE_BigIntMod(TEE_BigInt* dest, const TEE_BigInt* op, const TEE_BigInt* n); +void TEE_BigIntAddMod(TEE_BigInt* dest, + const TEE_BigInt* op1, + const TEE_BigInt* op2, + const TEE_BigInt* n); +void TEE_BigIntSubMod(TEE_BigInt* dest, + const TEE_BigInt* op1, + const TEE_BigInt* op2, + const TEE_BigInt* n); +void TEE_BigIntMulMod(TEE_BigInt* dest, + const TEE_BigInt* op1, + const TEE_BigInt* op2, + const TEE_BigInt* n); +void TEE_BigIntSquareMod(TEE_BigInt* dest, + const TEE_BigInt* op, + const TEE_BigInt* n); +void TEE_BigIntInvMod(TEE_BigInt* dest, + const TEE_BigInt* op, + const TEE_BigInt* n); + +/****************************************************************************** + * 8.10 Other Arithmetic Operations + ******************************************************************************/ + +bool TEE_BigIntRelativePrime(const TEE_BigInt* op1, const TEE_BigInt* op2); +void TEE_BigIntComputeExtendedGcd(TEE_BigInt* gcd, + TEE_BigInt* u, + TEE_BigInt* v, + const TEE_BigInt* op1, + const TEE_BigInt* op2); +int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt* op, + uint32_t confidenceLevel); + +/****************************************************************************** + * 8.11 Fast Modular Multiplication Operations + ******************************************************************************/ + +void TEE_BigIntConvertToFMM(TEE_BigIntFMM* dest, + const TEE_BigInt* src, + const TEE_BigInt* n, + const TEE_BigIntFMMContext* context); +void TEE_BigIntConvertFromFMM(TEE_BigInt* dest, + const TEE_BigIntFMM* src, + const TEE_BigInt* n, + const TEE_BigIntFMMContext* context); +void TEE_BigIntComputeFMM(TEE_BigIntFMM* dest, + const TEE_BigIntFMM* op1, + const TEE_BigIntFMM* op2, + const TEE_BigInt* n, + const TEE_BigIntFMMContext* context); + +int polar_rand(void * rng_state, unsigned char *output, size_t len); + +#ifdef CERTIFICATES_API +/************************************************************************************ + * Certificates API + *************************************************************************************/ + +/* + * Description + * Root Certificate Shall be stored as a file in a Persistent + * object hence we shall parse the Root certificate into the + * Transient object from Persistent object. + * As a part of populating transient field the certificate shall + * parsed and verified. + * + * Object transient object to be used for holding parsed certificate. + * name persistent object ID (Persistent Object Identifirer) + * + * \return TEE_SUCCESS if certificate parsed successfully, TEE_ERROR_XXXX + * error if unsuccessful. + * + * \Panic If the Certificate is not part of the transient object. + */ +TEE_Result TEE_ParseVerifyRootCertFile(TEE_ObjectHandle Object, + const char* name); + +/* + * Description + * Certificate passed as a pointer to buffer shall be parsed + * into a Transient object + * The verification of the parsed certificate is done in a + * seperately step as it will need device root Certificate + * for verification as we know the passed Certificate shall + * be either just one Certificate or can be Certificate chain. + * The parsed certificate shall be the part of Transient Object + * ready for verification. + * + * Object transient object to be used for holding parsed certificate. + * buf buffer holding the raw certificate data + * buflen size of the buffer + * + * \return TEE_SUCCESS if all certificates parsed successfully, TEE_ERROR_XXXX + * error if unsuccessful. + * + * \Panic If the Certificate is not part of the transient object. + */ +TEE_Result TEE_ParseCert(TEE_ObjectHandle Object, + const unsigned char* buf, + size_t buflen); + +/* + * Description + * The Certificate Revocation List (CRL) is optional parameter and + * is used to check whether a certificate is revoked by a + * Certificate Authority. + * The CRL is passed as a pointer to buffer (in a RAW format) + * and is parsed and stored in Transient Object. + * + * Object transient object to be used for holding parsed CRL. + * buf buffer holding the raw CRL data + * buflen size of the buffer + * + * \return TEE_SUCCESS if CRL parsed successfully, TEE_ERROR_CRL_PARSING + * error if unsuccessful. + * + * \Panic If the CRL is not part of the transient object. + */ +TEE_Result TEE_ParseCrl(TEE_ObjectHandle Object, + const unsigned char* buf, + size_t buflen); + +/* + * Description + * The Certificate Revocation List (CRL) Shall be stored as a file + * in Persistent object hence we shall parse and populate the + * transient Object. + * + * Object transient object to be used for holding parsed CRL. + * name persistent object ID (Persistent Object Identifirer) + * + * \return TEE_SUCCESS if CRL parsed successfully, TEE_ERROR_xx + * error if unsuccessful. + * + * \Panic If the CRL is not part of the transient object. + */ +TEE_Result TEE_ParseCrlfile(TEE_ObjectHandle Object, const char* name); + +/* + * Description + * Store the certificate DN in printable form into buf + * + * Object transient object with parsed Certificate. + * output Output buffer holding DN string + * + * \return TEE_SUCCESS if successfully, TEE_ERROR_xx error if unsuccessful. + * + * \Panic If the Certificate is not part of the transient object. + */ +TEE_Result TEE_CertDNgets(TEE_ObjectHandle Object, + char * const output, + size_t* size); + +/* + * Description + * Check the Certificate time against system time + * + * Object transient object with parsed Certificate. + * + * \return TEE_SUCCESS if successfully, TEE_ERROR_xx error if unsuccessful. + * + * \Panic If the Certificate is not part of the transient object. + */ +TEE_Result TEE_CheckTimeExpired(TEE_ObjectHandle Object); + +/* + * Description + * Verify the certificate or certificate chain signature. + * Populate the attribute field on if the certificate, + * certificate chain is verified successfully. + * + * Appobj transient object to be used for holding parsed certificate to be verified. + * CAobj transient object holding root certificate. + * CRLobj transient object holding crl. + * + * \return TEE_SUCCESS if certificate verified successfully, TEE_ERROR_XXXX + * error if unsuccessful. + * + * \Panic If the Certificate, root certificate, CRL is not part of the + * respective transient object. + */ +TEE_Result TEE_CertVerify(TEE_ObjectHandle Appobj, + TEE_ObjectHandle CAobj, + TEE_ObjectHandle CRLobj); + +/* No Plans for Key handling files at the moment. + TEE_Result TEE_ParseKey(TEE_ObjectHandle obj_hndl, const unsigned char *key, size_t keylen); + TEE_Result TEE_ParseKeyFile(TEE_ObjectHandle obj_hndl , const char *path); // TEE_ObjectHandle keyObject); + TEE_Result TEE_ParsePublicKey(TEE_ObjectHandle obj_hndl, const unsigned char *key, size_t keylen); + TEE_Result TEE_ParsePublicKeyFile(TEE_ObjectHandle obj_hndl , const char *path); //TEE_ObjectHandle PublicKeyObject); + TEE_Result TEE_ParseDHM(TEE_ObjectHandle obj_hndl, const unsigned char *dhmin, size_t dhminlen); + TEE_Result TEE_ParseDHMfile(TEE_ObjectHandle obj_hndl, const char *path); + */ + +#endif + +// Secure Objects API +/* + * Description + * encrypt and sign input data + * + * in input buffer + * in_len input buffer length + * out output buffer (can be set to NULL in combination with *out_len = 0 for getting required output buffer size + * out_len [in/out] output buffer length + * key crypto key + * key_len key length + * ta_uuid optional pointer to TA UUID (calling TA or delegated TA). If NULL no Access Control by TA UUID will be used + * one_session_so if non 0 use Session ID Access Control + * + * return TEE_SUCCESS if data was successfully wraped or TEE_ERROR_XXXX error if unsuccessful. + */ +TEE_Result TEE_pWrapSO(const unsigned char * in, + size_t in_len, + unsigned char * out, + size_t * out_len, + const unsigned char * key, + size_t key_len, + TEE_UUID * ta_uuid, + int one_session_so); + +/* + * Description + * decrypt and verify wrapped data + * + * in input buffer + * in_len input buffer length + * out output buffer (can be set to NULL in combination with *out_len = 0 for getting required output buffer size + * out_len [in/out] output buffer length + * key crypto key + * key_len key length + * + * return TEE_SUCCESS if data was successfully unwraped or TEE_ERROR_XXXX error if unsuccessful. + */ +TEE_Result TEE_pUnwrapSO(const unsigned char * in, + size_t in_len, + unsigned char * out, + size_t * out_len, + const unsigned char * key, + size_t key_len); + +#ifdef __cplusplus +} +#endif + +#endif // _TEE_INTERNAL_API_H diff --git a/include/include/tee_sim_command.h b/include/include/tee_sim_command.h new file mode 100755 index 0000000..2133842 --- /dev/null +++ b/include/include/tee_sim_command.h @@ -0,0 +1,77 @@ +/* + * ===================================================================================== + * + * Filename: tee_sim_command.h + * + * Description: TEEC Connection Header file + * + * Version: 1.0 + * Created: 26 March 2015 12:43:30 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef __TEE_SIM_COMMAND_H__ +#define __TEE_SIM_COMMAND_H__ + +#include "tee_internal_api.h" + +typedef enum { + COMMANDINVALID = -1, + CREATE = 0, + OPENSESSION, + INVOKECOMMAND, + CLOSESESSION, + DESTROY, + REQCANCEL +} SIM_COMMAND; + +typedef struct { + uint32_t operationID; + uint32_t paramTypes; + TEE_Param params[4]; + uint32_t shmID[4]; +} Operation; + +typedef struct { + uint32_t sessionID; + TEE_Result returnValue; +} CreateTAEntryPointData; + +typedef struct { + uint32_t sessionID; +} DestroyTAEntryPointData; + +typedef struct { + uint32_t sessionID; + Operation op; + TEE_Result returnValue; + uint32_t returnOrigin; +} OpenTASessionData; + +typedef struct { + uint32_t sessionID; + uint32_t commandID; + Operation op; + TEE_Result returnValue; + uint32_t returnOrigin; +} InvokeTACommandData; + +typedef struct { + uint32_t sessionID; +} CloseTASessionData; + +typedef struct { + uint32_t sessionID; + uint32_t operationID; + TEE_Result returnValue; + uint32_t returnOrigin; + +} RequestTACancelData; + +#endif /* __TEE_SIM_COMMAND_H__ */ diff --git a/include/include/teec_data.h b/include/include/teec_data.h new file mode 100755 index 0000000..b673eb9 --- /dev/null +++ b/include/include/teec_data.h @@ -0,0 +1,100 @@ +/* + * ===================================================================================== + * + * Filename: teec_data.h + * + * Description: TEEC Data Header file + * + * Version: 1.0 + * Created: 16 April 2015 12:43:30 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#include "tee_client_api.h" + +#ifndef __TEEC_DATA_H__ +#define __TEEC_DATA_H__ + +typedef struct { + uint32_t shmKey; + size_t size; + uint32_t offset; +} MemoryRefData; + +typedef union { + MemoryRefData mem; + TEEC_Value value; +} ParamData; + +typedef struct { + uint32_t paramTypes; + ParamData params[4]; + uint32_t OperationID; +} OperationData; + +typedef struct { + size_t size; + uint32_t flags; + uint32_t shmKey; +} SharedMemoryData; + +typedef struct { + uint32_t contextID; + uint32_t nameLength; + char TEEName[MAX_CONTEXT_NAME_LEN]; + TEEC_Result returnValue; +} InitContextData; + +typedef struct { + uint32_t contextID; + uint32_t sessionID; + TEEC_UUID uuid; + uint32_t connMeth; + uint32_t connData; + OperationData operation; + uint32_t returnOrigin; + TEEC_Result returnValue; +} OpenSessionData; + +typedef struct { + uint32_t contextID; + SharedMemoryData sharedMem; + TEEC_Result returnValue; +} RegSharedMemData; + +typedef struct { + uint32_t contextID; + uint32_t sessionID; + uint32_t commandID; + OperationData operation; + uint32_t returnOrigin; + TEEC_Result returnValue; +} InvokeCommandData; + +typedef struct { + uint32_t contextID; + uint32_t sessionID; + uint32_t operationID; +} ReqCancellationData; + +typedef struct { + uint32_t contextID; + SharedMemoryData sharedMem; +} RelSharedMemData; + +typedef struct { + uint32_t contextID; + uint32_t sessionID; +} CloseSessionData; + +typedef struct { + uint32_t contextID; +} FinalizeContextData; + +#endif /* __TEEC_DATA_H__ */ diff --git a/include/include/teestub_command_data.h b/include/include/teestub_command_data.h new file mode 100755 index 0000000..e4c8c06 --- /dev/null +++ b/include/include/teestub_command_data.h @@ -0,0 +1,59 @@ +/* + * ===================================================================================== + * + * Filename: teestub_command_data.h + * + * Description: TEEStub Data Header file + * + * Version: 1.0 + * Created: 20 April 2015 12:43:30 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna Devale + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#include "tee_internal_api.h" +#include "teec_data.h" + +#ifndef __TEESTUB_COMMAND_DATA_H__ +#define __TEESTUB_COMMAND_DATA_H__ + +typedef OperationData IntTAOperationData; + +typedef struct { + TEE_UUID destination; + uint32_t cancelTimeOut; + IntTAOperationData operation; + uint32_t session; + uint32_t returnOrigin; + uint32_t returnValue; +} IntTAOpenSessionData; + +typedef struct { + uint32_t session; + uint32_t cancelTimeOut; + uint32_t commandID; + IntTAOperationData operation; + uint32_t returnOrigin; + uint32_t returnValue; +} IntTAInvokeCommandData; + +typedef struct { + uint32_t accessFlags; + void *buffer; + uint32_t size; +} IntTACheckMemoryCommandData; + +typedef struct { + uint32_t session; + +} IntTACloseSessionData; + +typedef struct { + TEE_Result panicCode; +} IntTAPanicData; +#endif /* __TEESTUB_COMMAND_DATA_H__ */ diff --git a/log/.cproject b/log/.cproject new file mode 100755 index 0000000..a63706f --- /dev/null +++ b/log/.cproject @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/log/.gitignore b/log/.gitignore new file mode 100755 index 0000000..3df573f --- /dev/null +++ b/log/.gitignore @@ -0,0 +1 @@ +/Debug/ diff --git a/log/.project b/log/.project new file mode 100755 index 0000000..d1a8b53 --- /dev/null +++ b/log/.project @@ -0,0 +1,26 @@ + + + log + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/log/.settings/language.settings.xml b/log/.settings/language.settings.xml new file mode 100755 index 0000000..6b3365f --- /dev/null +++ b/log/.settings/language.settings.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/log/.settings/org.eclipse.cdt.core.prefs b/log/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..a945b31 --- /dev/null +++ b/log/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.1318202039/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.1318202039/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.1318202039/PATH/value=C\:/Program Files/Java/jre1.8.0_40/bin/server;C/Program Files/Java/jre1.8.0_40/bin;C\:/Program Files/Java/jre1.8.0_40/lib/amd64;C\:\\Program Files (x86)\\Black Duck Software\\protexIP\\bin;C\:\\Program Files\\Common Files\\Microsoft Shared\\Windows Live;C\:\\Program Files (x86)\\Common Files\\Microsoft Shared\\Windows Live;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files (x86)\\QuickTime\\QTSystem\\;C\:\\Program Files (x86)\\Java\\jre7\\bin; C\:\\cygwin64\\bin;C\:\\Program Files\\doxygen\\bin;D\:\\eclipse;C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\Program Files (x86)\\Java\\jre1.8.0_45\\bin;C\:\\Program Files\\eclipse;C\:/Program Files/Java/jre1.8.0_31/bin/server;C\:/Program Files/Java/jre1.8.0_31/bin;C\:/Program Files/Java/jre1.8.0_31/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\csvn\\bin\\;C\:\\csvn\\Python25\\;C\:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files\\Diskeeper Corporation\\ExpressCache\\;C\:\\Program Files (x86)\\Windows Live\\Shared;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x64;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files (x86)\\WinSCP\\;C\:\\Program Files (x86)\\PuTTY;C\:\\Program Files\\Microsoft\\Web Platform Installer\\;C\:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C\:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;C\:\\Program Files (x86)\\doxygen\\bin;C\:\\Program Files (x86)\\sfk168;C\:\\Program Files (x86)\\vlc-2.1.0;C\:\\Python27\\Scripts;C\:\\Program Files (x86)\\GnuWin32\\bin;C\:\\Python27;C\:\\Program Files (x86)\\Subversion\\bin;c\:\\Program Files\\Synergy;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\MinGW\\lib\\gcc\\mingw32\\4.8.1;C\:\\Program Files (x86)\\Windows Kits\\8.1\\Windows Performance Toolkit\\;C\:\\Program Files (x86)\\GitExtensions\\;C\:\\Program Files\\Perforce;c\:\\Program Files\\Java\\jre1.8.0_31\\bin\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\tizen-sdk\\ide;${Path};D\:\\samsung-tv-sdk\\tools\\i386-linux-gnueabi-gcc-4.6\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.1318202039/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.1318202039/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.695503171/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592.695503171/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x64;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files (x86)\\GitExtensions\\;D\:\\Tizen\\tizen-sdk\\tools;D\:\\Android\\android-sdk\\platform-tools;D\:\\Android\\android-ndk-r10c;C\:\\Program Files\\Perforce;D\:\\eclipse\\eclipse-rcp-luna-SR1-win32-x86_64;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\bin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\mingbin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.22061592/appendContributed=true diff --git a/log/log.c b/log/log.c new file mode 100755 index 0000000..67c7f3e --- /dev/null +++ b/log/log.c @@ -0,0 +1,200 @@ +/* + * ===================================================================================== + * + * Filename: log.c + * + * Description: logger for Simulator + * + * Version: 1.0 + * Created: 26 March 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "log.h" +#include +#include +#include + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +static int32_t gdebug_level = 0xff; +static int32_t gmodule_level = 0xfffffff; +//static const char* gtag = "TA_SDK"; + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +/* + * This method is used to set module level and debug level to debug + * + * @param dbg_level + * [IN] enum value of DebugLevel + * + * @param mdl_level + * [IN] enum value of ModuleLevel + * + * @return void + */ +__attribute__ ((visibility("default"))) +void SetDebugAndModuleLevel(IN const int32_t module_level, + IN const int32_t debug_level) { + if (module_level < UTILS || module_level > ALL_MODULES + || debug_level < INFO_LEVEL_LOG || debug_level > VERBOSE_LEVEL_LOG) { + return; + } + /* + * set global variables for module level and debug level + */ + gmodule_level = module_level; + gdebug_level = debug_level; + return; +} + +/* + * This method is to get debug level set + * + * @param dbg_level + * [IN] enum value of DebugLevel + * + * @return const char pointer + */ +const char* GetDebugLevel(IN int32_t dbg_level) { + switch (dbg_level) { + case INFO_LEVEL_LOG: + return "INFO"; + case PACKET_LEVEL_LOG: + return "PACKET"; + case ERROR_LEVEL_LOG: + return "ERROR"; + case DEBUG_LEVEL_LOG: + return "DEBUG"; + case SECURED_LEVEL_LOG: + return "SECURED"; + case VERBOSE_LEVEL_LOG: + return "VERBOSE"; + default: + return ""; + } +} + +/* + * This method is to get module for which debug is set + * + * @param mdl_level + * [IN] enum value of ModuleLevel + * + * @return const char pointer + */ +const char* GetModuleLevel(IN int32_t module_level) { + switch (module_level) { + case UTILS: + return "UTILS"; + case SIM_DAEMON: + return "SIM_DAEMON"; + case TEEC_LIB: + return "TEEC_LIB"; + case TEE_STUB: + return "TEE_STUB"; + case SSF_LIB: + return "SSF_LIB"; + default: + return "TA_SDK"; + } +} + +/* + * This method is used to print the debug logs + * + * @param function_name + * [IN] name of the fuction + * + * @param line_no + * [IN] line number of debug statement + * + * @param module_level + * [IN] enum value of ModuleLevel + * + * @param dbg_level + * [IN] enum value of DebugLevel + * + * @param message + * [IN] message which needs to be displayed + * + * @return void + */ +__attribute__ ((visibility("default"))) +void PrintLog(IN const char* function_name, IN const int32_t line_no, + IN int32_t module_level, IN int32_t debug_level, IN const char* message, + ...) { +#ifndef _ANDROID_NDK + if (0 == (module_level & gmodule_level) + || 0 == (debug_level & gdebug_level)) { + return; + } +#endif + const char* module = GetModuleLevel(module_level); + va_list variable_list; + va_start(variable_list, message); +#if defined(__TIZEN__) + char buf[512] = {0,}; + vsnprintf(buf, 511, message, variable_list); + switch(debug_level) + { + case INFO_LEVEL_LOG: + LOG(LOG_INFO, TA_SDK_TAG, "[%s][%s:%d]%s", module, function_name, line_no, buf); + break; + case PACKET_LEVEL_LOG: + LOG(LOG_DEBUG, TA_SDK_TAG, "[%s][%s:%d]%s", module, function_name, line_no, buf); + break; + case ERROR_LEVEL_LOG: + LOG(LOG_ERROR, TA_SDK_TAG, "[%s][%s:%d]%s", module, function_name, line_no, buf); + break; + case DEBUG_LEVEL_LOG: + case SECURED_LEVEL_LOG: + case VERBOSE_LEVEL_LOG: + LOG(LOG_DEBUG, TA_SDK_TAG, "[%s][%s:%d]%s", module, function_name, line_no, buf); + break; + default: + LOG(LOG_DEBUG, TA_SDK_TAG, "[%s][%s:%d]%s", module, function_name, line_no, buf); + break; + } +#elif defined(_ANDROID_NDK) + char buf[512] = {'\0'}; + vsnprintf(buf, sizeof(buf), message, variable_list); + switch(debug_level) + { + case INFO_LEVEL_LOG: + __android_log_print(ANDROID_LOG_INFO, gtag, "[%s] %s: %d: %s\n", module, function_name, line_no, buf); + break; + case ERROR_LEVEL_LOG: + __android_log_print(ANDROID_LOG_ERROR, gtag, "[%s] %s: %d: %s\n", module, function_name, line_no, buf); + break; + case DEBUG_LEVEL_LOG: + __android_log_print(ANDROID_LOG_WARN, gtag, "[%s] %s: %d: %s\n", module, function_name, line_no, buf); + break; + case SECURED_LEVEL_LOG: + __android_log_print(ANDROID_LOG_DEBUG, gtag, "[%s] %s: %d: %s\n", module, function_name, line_no, buf); + break; + default: +// __android_log_print(ANDROID_LOG_VERBOSE, gtag, "[%s]%s: %d: %s\n", module, function_name, line_no, buf); + break; + } +#else + const char* severity = GetDebugLevel(debug_level); + printf("[%s] [%s] %s: %d: ", module, severity, function_name, line_no); + vprintf(message, variable_list); + printf("\n"); +#endif + va_end(variable_list); + return; +} diff --git a/log/log.h b/log/log.h new file mode 100755 index 0000000..534ae68 --- /dev/null +++ b/log/log.h @@ -0,0 +1,164 @@ +/* + * ===================================================================================== + * + * Filename: log.h + * + * Description: This file provides log APIs for debugging + * + * Version: 1.0 + * Created: 26 March 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef LOG_H +#define LOG_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define IN +#define INCONST +#define INOUT +#define OUT + +#define _LOGGING + +#ifdef _WIN +typedef int int8_t; +typedef int int16_t; +typedef int int32_t; +typedef long long int int64_t; +typedef long long unsigned uint64_t; +typedef int timer_t; +#endif + +#ifdef __TIZEN__ +#include +#define TA_SDK_TAG "TA_SDK" +#endif + +#ifdef _ANDROID_NDK +#include +#endif + +#ifdef _WIN +#define __attribute__(...) +#endif + +/* + * Enum to identify Debug level + */ +typedef enum { + INFO_LEVEL_LOG = 0x01, + PACKET_LEVEL_LOG = 0x02, + ERROR_LEVEL_LOG = 0x04, + DEBUG_LEVEL_LOG = 0x08, + SECURED_LEVEL_LOG = 0x10, + VERBOSE_LEVEL_LOG = 0xFF, +} DebugLevel; + +/* + * Enum to identify Module name + */ +typedef enum { + UTILS = 0x01, + SIM_DAEMON = 0x02, + TEEC_LIB = 0x04, + TEE_STUB = 0x08, + TEST = 0x10, + SSF_LIB = 0x11, + ALL_MODULES = 0xFFFFFFF, +} ModuleLevel; + +#ifdef _LOGGING + +#define _LOG(module_level,debug_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,debug_level,__VA_ARGS__) + +#define LOGE(module_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,ERROR_LEVEL_LOG,__VA_ARGS__) +#define LOGV(module_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,VERBOSE_LEVEL_LOG,__VA_ARGS__) +#define LOGD(module_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,DEBUG_LEVEL_LOG,__VA_ARGS__) +#define LOGI(module_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,SECURED_LEVEL_LOG,__VA_ARGS__) +#define LOGS(module_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,INFO_LEVEL_LOG,__VA_ARGS__) +#define LOGP(module_level,...) PrintLog(__FUNCTION__,__LINE__,module_level,PACKET_LEVEL_LOG,__VA_ARGS__) + +#else //ifdef _LOGGING + +#define LOGE(module_level,...) +#define LOGV(module_level,...) +#define LOGD(module_level,...) +#define LOGI(module_level,...) +#define LOGS(module_level,...) +#define LOGP(module_level,...) + +#endif //ifdef _LOGGING + +/* + * This method is to get debug level set + * + * @param dbg_level + * [IN] enum value of DebugLevel + * + * @return const char pointer + */ +const char* GetDebugLevel(IN int32_t dbg_level); + +/* + * This method is to get module for which debug is set + * + * @param mdl_level + * [IN] enum value of ModuleLevel + * + * @return const char pointer + */ +const char* GetModuleLevel(IN int32_t mdl_level); + +/* + * This method is used to set module level and debug level to debug + * + * @param dbg_level + * [IN] enum value of DebugLevel + * + * @param mdl_level + * [IN] enum value of ModuleLevel + * + * @return void + */ +void SetDebugAndModuleLevel(IN const int32_t module_level, + IN const int32_t debug_level); + +/* + * This method is used to print the debug logs + * + * @param function_name + * [IN] name of the fuction + * + * @param line_no + * [IN] line number of debug statement + * + * @param module_level + * [IN] enum value of ModuleLevel + * + * @param dbg_level + * [IN] enum value of DebugLevel + * + * @param message + * [IN] message which needs to be displayed + * + * @return void + */ +void PrintLog(IN const char* function_name, IN const int32_t line_no, + IN int32_t module_level, IN int32_t debug_level, IN const char* message, + ...); + +#endif diff --git a/osal/.cproject b/osal/.cproject new file mode 100755 index 0000000..afa393f --- /dev/null +++ b/osal/.cproject @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osal/.gitignore b/osal/.gitignore new file mode 100755 index 0000000..3df573f --- /dev/null +++ b/osal/.gitignore @@ -0,0 +1 @@ +/Debug/ diff --git a/osal/.project b/osal/.project new file mode 100755 index 0000000..1d29a11 --- /dev/null +++ b/osal/.project @@ -0,0 +1,26 @@ + + + osal + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/osal/.settings/org.eclipse.cdt.core.prefs b/osal/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..bb01593 --- /dev/null +++ b/osal/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461.1612701246/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461.1612701246/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461.1612701246/PATH/value=C\:/Program Files/Java/jre1.8.0_40/bin/server;C\:/Program Files/Java/jre1.8.0_40/bin;C\:/Program Files/Java/jre1.8.0_40/lib/amd64;C\:\\Program Files (x86)\\Black Duck Software\\protexIP\\bin;C\:\\Program Files\\Common Files\\Microsoft Shared\\Windows Live;C\:\\Program Files (x86)\\Common Files\\Microsoft Shared\\Windows Live;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files (x86)\\QuickTime\\QTSystem\\;C\:\\Program Files (x86)\\Java\\jre7\\bin; C\:\\cygwin64\\bin;C\:\\Program Files\\doxygen\\bin;D\:\\eclipse;C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\Program Files (x86)\\Java\\jre1.8.0_45\\bin;C\:\\Program Files\\eclipse;C\:/Program Files/Java/jre1.8.0_31/bin/server;C\:/Program Files/Java/jre1.8.0_31/bin;C\:/Program Files/Java/jre1.8.0_31/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\csvn\\bin\\;C\:\\csvn\\Python25\\;C\:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files\\Diskeeper Corporation\\ExpressCache\\;C\:\\Program Files (x86)\\Windows Live\\Shared;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x64;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files (x86)\\WinSCP\\;C\:\\Program Files (x86)\\PuTTY;C\:\\Program Files\\Microsoft\\Web Platform Installer\\;C\:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C\:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;C\:\\Program Files (x86)\\doxygen\\bin;C\:\\Program Files (x86)\\sfk168;C\:\\Program Files (x86)\\vlc-2.1.0;C\:\\Python27\\Scripts;C\:\\Program Files (x86)\\GnuWin32\\bin;C\:\\Python27;C\:\\Program Files (x86)\\Subversion\\bin;c\:\\Program Files\\Synergy;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\MinGW\\lib\\gcc\\mingw32\\4.8.1;C\:\\Program Files (x86)\\Windows Kits\\8.1\\Windows Performance Toolkit\\;C\:\\Program Files (x86)\\GitExtensions\\;C\:\\Program Files\\Perforce;c\:\\Program Files\\Java\\jre1.8.0_31\\bin\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\tizen-sdk\\ide;${Path};D\:\\samsung-tv-sdk\\tools\\i386-linux-gnueabi-gcc-4.6\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461.1612701246/append=true +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461.1612701246/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x64;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files (x86)\\GitExtensions\\;D\:\\Tizen\\tizen-sdk\\tools;D\:\\Android\\android-sdk\\platform-tools;D\:\\Android\\android-ndk-r10c;C\:\\Program Files\\Perforce;D\:\\eclipse\\eclipse-rcp-luna-SR1-win32-x86_64;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\bin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\mingbin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/append=true +environment/project/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/appendContributed=true diff --git a/osal/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/osal/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100755 index 0000000..16b7426 --- /dev/null +++ b/osal/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/CPATH/delimiter=; +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/CPATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/C_INCLUDE_PATH/delimiter=; +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/append=true +environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.1210907461/appendContributed=true diff --git a/osal/OsaCommon.c b/osal/OsaCommon.c new file mode 100755 index 0000000..e2ef8be --- /dev/null +++ b/osal/OsaCommon.c @@ -0,0 +1,439 @@ +/* + * ===================================================================================== + * + * Filename: OsaCommon.c + * + * Description: Common functions + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "OsaLinuxUser.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +// Global Timer Datatypes +void timer_handler(int iJunk); + +typedef void (*tHandler)(int data); + +typedef void (*TimerProcT)(void* pvdata); + +struct Timerdata { + unsigned int stop_timer; + unsigned int start_timer; + struct itimerval iTval_t; + TimerProcT callback; + void* pvTmpdata; + +}; +struct Timerdata Timer_data_t; + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +void * OsaMalloc(unsigned int size) { + return malloc(size); +} + +void *OsaFree(void *pbuf) { + if (pbuf != NULL) { + free(pbuf); + pbuf = NULL; + } + return pbuf; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : InitTimerData + // Detail Description : This function initialises the timer data structure. + // + // Return Data Type : void + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +void InitTimerData(void) { + Timer_data_t.stop_timer = FALSE; + Timer_data_t.start_timer = FALSE; + + memset(&Timer_data_t.iTval_t, 0, sizeof(struct itimerval)); + + Timer_data_t.callback = NULL; + + Timer_data_t.pvTmpdata = NULL; + +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerCreate + // Detail Description : This function creates the timer.It initialises the + // timer data and sets the callback function to be called + // upon timer expiry. + // + // Return Data Type : ErrorType. + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerCreate(int* pTimerId, int periodic, int s32Time, + void (*entry)(void* data), void* pvAr) { + unsigned int uiDiv, uiRem; + struct sigaction Action_t; + + uiDiv = s32Time / 1000; + uiRem = s32Time % 1000; + + if (Timer_data_t.start_timer != TRUE) { + + // Initialize the Timer data structure + InitTimerData(); + + /* + * Fill the structure with the periodic or one shot time + * interval after which a function has to be called + */ + + if (periodic == OSAL_TIMER_PERODIC) { + Timer_data_t.iTval_t.it_interval.tv_sec = uiDiv; + Timer_data_t.iTval_t.it_interval.tv_usec = uiRem * 1000; + Timer_data_t.iTval_t.it_value.tv_sec = uiDiv; + Timer_data_t.iTval_t.it_value.tv_usec = uiRem * 1000; + } else { + Timer_data_t.iTval_t.it_interval.tv_sec = 0; + Timer_data_t.iTval_t.it_interval.tv_usec = 0; + Timer_data_t.iTval_t.it_value.tv_sec = uiDiv; + Timer_data_t.iTval_t.it_value.tv_usec = uiRem * 1000; + + } + + /* + * Set Signal handler + */ + + Action_t.sa_handler = (tHandler)timer_handler; + Timer_data_t.callback = (entry); + Timer_data_t.pvTmpdata = pvAr; + + sigemptyset(&(Action_t.sa_mask));/*No other signal blocked*/ + + /* + * Add SIGALRM in the list + */ + if (sigaddset(&(Action_t.sa_mask), SIGALRM) < 0) { + //PrintError("In OsaTimerCreate() : Could Not Stop \n"); + return OSAL_ERROR; + } + + /* + * Unblock the SIGALRM,if it is blocked + */ + if (sigprocmask(SIG_UNBLOCK, &(Action_t.sa_mask), NULL) < 0) { + //PrintError("In OsaTimerCreate() : Could not mask the Signal \n"); + return OSAL_ERROR; + } + + /* + * Set the Global vairable. + * + */ + //stop_timer = FALSE; + Timer_data_t.stop_timer = FALSE; + + /* + * Restore the signal previous setting + */ + /* OSAL_080922 : before SA_SIGINFO was used. */ + Action_t.sa_flags = SA_RESTART; + + sigaction(SIGALRM, &Action_t, NULL); + return OSAL_OK; + } else { + return OSAL_ERROR; + } + +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerStart + // Detail Description : This function starts the already created timer . + // + // Return Data Type : ErrorType. + / + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerStart(int iTimerId) { + /* The timer is started */ + if (Timer_data_t.start_timer != TRUE) { + if (setitimer(ITIMER_REAL, &Timer_data_t.iTval_t, NULL) < 0) { + //PrintError("In OsaTimerStart() : OsaTimerStart failed \n "); + return OSAL_ERROR; + } + Timer_data_t.start_timer = TRUE; + return OSAL_OK; + } else { + return OSAL_ERROR; + } +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerStop + // Detail Description : This function stops the current running timer . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerStop(int iTimerId) { + //struct sigaction Action_t; + //Action_t.sa_flags = 0; + struct itimerval trivial_it; /* OSAL_080918_1 */ + + if (Timer_data_t.start_timer == FALSE) { + //PrintError("In OsaTimerStop() : Timer not yet started \n"); + return OSAL_ERROR; + } + + /* OSAL_080920 : Don't block the alarm signal */ +#if 0 + /* OSAL_080918_2 : init signal set variable */ + sigemptyset(&(Action_t.sa_mask)); + + /* + * Add SIGALRM in the signal List + */ + if(sigaddset(&(Action_t.sa_mask),SIGALRM) <0) + { + PrintError("In OsaTimerStop() : Could Not Stop \n"); + return OSAL_ERROR; + } + /* + * Block SIGALRM + */ + if(sigprocmask(SIG_BLOCK,&(Action_t.sa_mask),NULL) <0) + { + PrintError("In OsaTimerStop() : Could not mask the Signal \n"); + return OSAL_ERROR; + } +#endif + + /* OSAL_080918_1 : stop interval timer after alarm signal blocked */ + trivial_it.it_value.tv_sec = 0; + trivial_it.it_value.tv_usec = 0; + if (setitimer(ITIMER_REAL, &trivial_it, NULL) == -1) { + //PrintError("OsaTimerStop failed\n "); + return OSAL_ERROR; + } + + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerDelete + // Detail Description : This function deletes the current timer . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerDelete(int iTimerId) { + //struct sigaction Action_t; + struct itimerval iTmpval_t; + + //Action_t.sa_flags = 0; + + if (Timer_data_t.start_timer == FALSE) { + //PrintError("In OsaTimerDelete() : No timer present to be deleted \n"); + return OSAL_ERROR; + } + + iTmpval_t.it_interval.tv_sec = 0; + iTmpval_t.it_interval.tv_usec = 0; + iTmpval_t.it_value.tv_sec = 0; + iTmpval_t.it_value.tv_usec = 0; + + /* The Timer is deleted */ + + if (setitimer(ITIMER_REAL, &iTmpval_t, NULL) < 0) { + //PrintError("In OsaTimerDelete() : pOsaTimerDelete failed \n"); + return -1; + } + Timer_data_t.stop_timer = TRUE; + Timer_data_t.start_timer = FALSE; + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerRestart + // Detail Description : This function restarts the stopped timer . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerRestart(int iTimerId) { + struct sigaction Action_t; + if (Timer_data_t.stop_timer == TRUE) { + //PrintError("In OsaTimerRestart() : Has been stopped forever \n"); + return OSAL_ERROR; + } + + /* OSAL_080918_1 : + reset it_value to keep the first expiration after restart */ + if (setitimer(ITIMER_REAL, &Timer_data_t.iTval_t, NULL) == -1) { + //PrintError("OsaTimerRestart failed\n "); + return OSAL_ERROR; + } + + /* OSAL_080918_2 : init signal set variable */ + sigemptyset(&(Action_t.sa_mask)); + sigaddset(&(Action_t.sa_mask), SIGALRM); + + Action_t.sa_flags = 0; + if (sigprocmask(SIG_UNBLOCK, &(Action_t.sa_mask), NULL) < 0) { + //PrintError("In OsaTimerRestart() : Could Not Start Again \n"); + return OSAL_ERROR; + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : timer_handler + // Detail Description : Private timer_handler + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +void timer_handler(int iJunk) { + (Timer_data_t.callback)(Timer_data_t.pvTmpdata); + +} + +void OsaWait(int mSecs) { + unsigned int delay = mSecs * 1000; + usleep(delay); +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaCurrentTime + // Detail Description : This API returns the current time in _milliseconds_ + // using CPU timer + // Return Data Type : ErrorType + // + // Programming Note : + // (Linux OsaCurrentTime, OsaCurrentTimeVal function) + // 1) kernel should support the high-resolution clocksource. + // Otherwise, the maximum resolution is only 1 or 10 mili sec. + // Default clocksource of arm linux kernel is system tick timer. + // 2) In some cases, time-warp can be occur. (time goes back in 10 milliseconds or less) + // When system lose the timer tick interrupt. + //------------------------------------------------------------------------------ + // $$$ + */ +unsigned int OsaCurrentTime(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); // SoC_D00003324 + + return (unsigned int)((ts.tv_sec * 1000) + (ts.tv_nsec / 1000000)); +} + +/* COMMON_070709-2 */ +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaCurrentTimeVal + // Detail Description : This function returns the current timeval using CPU clock + // Return Data Type : pOsaTime_t (1st argument) + // + // Programming Note : See "Programming note" in the OsaCurrentTime function + //------------------------------------------------------------------------------ + // $$$ + */ +void OsaCurrentTimeVal(pOsaTime_t pTimeVal) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); // SoC_D00003324 + + pTimeVal->Sec = ts.tv_sec; + pTimeVal->NanoSec = ts.tv_nsec; + +} + +/* COMMON_070709-2 */ +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaDiffTimeVal + // Detail Description : Subtract pVal2 to pVal1, stores result to pResult + // Return Data Type : pOsaTime_t (1st argument) + // + // Programming Note : If pVal2 is less than pVal1, result is 0. + //------------------------------------------------------------------------------ + // $$$ + */ +void OsaDiffTimeVal(pOsaTime_t pResult, const pOsaTime_t pVal1, + const pOsaTime_t pVal2) { + /* no negative result */ + if ((pVal2->Sec < pVal1->Sec) + || ((pVal1->Sec == pVal2->Sec) && (pVal2->NanoSec < pVal1->NanoSec))) { + pResult->Sec = 0; + pResult->NanoSec = 0; + return; + } + + pResult->Sec = pVal2->Sec - pVal1->Sec; + + /* perform the carry */ + if (pVal2->NanoSec < pVal1->NanoSec) { + pResult->Sec--; + pResult->NanoSec = pVal2->NanoSec + 1000000000 - pVal1->NanoSec; + } else { + pResult->NanoSec = pVal2->NanoSec - pVal1->NanoSec; + } +} + +int OsaGetTicksPerSecond(void) { + /* return OS Timer frequency(usually 100hz). */ + return 100; +} + diff --git a/osal/OsaIpc.c b/osal/OsaIpc.c new file mode 100755 index 0000000..57bb384 --- /dev/null +++ b/osal/OsaIpc.c @@ -0,0 +1,350 @@ +/* + * ===================================================================================== + * + * Filename: OsaIpc.c + * + * Description: Semaphore and Shared Memory implementation + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "OsaLinuxUser.h" + +key_t OsaGetKey(const char pcName[10]) { + uid_t uid; + key_t key; + int i, len, acc; + char aName[10]; + + memset(aName, 0x00, 10); + memcpy(aName, pcName, 9); + + uid = 1; //getuid(); + acc = 0; + len = strlen(aName); + + for (i = 0; i < len; i++) { + acc <<= 1; + acc = acc + aName[i]; + } + key = (uid << 16) | (acc & 0x0000FFFF); + + return (key); +} + +/* + // ------------------------------------------------------------------- + // Shared Memory Implementation + // ------------------------------------------------------------------- + */ +int OsaShmCreate(const char pcName[10], unsigned int u32ShmSegSize, + int* ps32ShmId) { + key_t key = (key_t)OsaGetKey(pcName); + + if (NULL == ps32ShmId) { + return OSAL_ERROR; + } + + *ps32ShmId = shmget(key, u32ShmSegSize, IPC_CREAT | IPC_EXCL | 0666); + if (*ps32ShmId == -1) { + if (errno == EEXIST) { + *ps32ShmId = shmget(key, u32ShmSegSize, 0666); + return OSAL_EXIST; + } else { + return OSAL_ERROR; + } + } + + return OSAL_OK; +} + +int OsaShmDelete(int s32ShmId) { + if (shmctl(s32ShmId, IPC_RMID, NULL) == -1) { + return OSAL_ERROR; + } + + return OSAL_OK; +} + +int OsaShmAttach(int s32ShmId, void** pShmAddr) { + if (NULL == pShmAddr) { + return OSAL_ERROR; + } + + *pShmAddr = (void*)shmat(s32ShmId, NULL, 0); + + if (*pShmAddr == (void*)-1) { + return OSAL_ERROR; + } + + return OSAL_OK; +} + +int OsaShmDetach(const void *pShmAddr) { + if (NULL == pShmAddr) { + return OSAL_ERROR; + } + + if (shmdt(pShmAddr) == -1) { + //PrintError("Error in Detaching"); + return OSAL_ERROR; + } + + return OSAL_OK; +} + +/* + // ------------------------------------------------------------------- + // Semaphore Implementation(System V) + // ------------------------------------------------------------------- + */ +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; +}; + +typedef struct _UlOsaSem { + int iSemId; + int iAttribute; + int iCount; + char bName[16]; + key_t semKey; +} UlOsaSem_t; + +typedef struct { + int bUsed; + key_t semKey; + int s32Count; +} OsaNamedSemMgr_t; + +#define MAX_NAMEDSEM_MGR 256 + +static int UlOsaNamedSemCreate(const char pcName[10], int iCount, + int iAttribute, unsigned int* puiSmid) { + int iRetVal = OSAL_OK; + UlOsaSem_t* sem; + key_t semKey; + + sem = (UlOsaSem_t*)malloc(sizeof(*sem)); + if (!sem) { + //PrintError ("UlOsaSemCreate, Out of memory!\n"); + return OSAL_ERROR; + } + + semKey = OsaGetKey(pcName); + + sem->iSemId = semget(semKey, 1, IPC_CREAT | IPC_EXCL | 0666); + + if (sem->iSemId != -1) { + union semun semUnion; + + semUnion.val = iCount; + if (semctl(sem->iSemId, 0, SETVAL, semUnion) == -1) { + semctl(sem->iSemId, 0, IPC_RMID, NULL); + free(sem); + //PrintError ("UlOsaSemCreate, semctl Failed!\n"); + return OSAL_ERROR; + } + } else { + if (errno == EEXIST) { + sem->iSemId = semget(semKey, 1, 0); + iRetVal = OSAL_EXIST; + } else { + free(sem); + //PrintError ("UlOsaSemCreate, semget Failed!\n"); + return OSAL_ERROR; + } + } + + sem->iAttribute = iAttribute; + sem->iCount = iCount; + sem->semKey = semKey; + + memcpy((void*)sem->bName, (const void*)pcName, (size_t)10); + sem->bName[10] = '\0'; + + *puiSmid = (unsigned int)sem; + + return iRetVal; +} + +#if 0 // unused funciton Á¦°Å. +static int UlOsaNamedSemDelete(unsigned int uiSmid) +{ + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + + if (!sem) + { + return OSAL_ERROR; + } + + if (semctl (sem->iSemId, 0, IPC_RMID, NULL) == -1) + { + return OSAL_ERROR; + } + + free((void*)uiSmid); + + return OSAL_OK; +} +#endif + +static int UlOsaNamedSemGet(unsigned int uiSmid, int iFlags, int iTimeout) { + struct sembuf semBuf; + struct timespec ts; + struct timeval tv; + + int ret; + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + + if (!sem) { + return OSAL_ERROR; + } + + if (iFlags == OSAL_SEM_NOWAIT) { + semBuf.sem_num = 0; + semBuf.sem_op = 0; + semBuf.sem_flg = IPC_NOWAIT; + + ret = semop(sem->iSemId, &semBuf, 1); + } else if (iTimeout == 0) { + /* wait _inifinite_ */ + //PrintDbg ("UlOsaSemGet-infinite(%s).\n", sem->bName); + semBuf.sem_num = 0; + semBuf.sem_op = -1; + semBuf.sem_flg = SEM_UNDO; + + ret = OSAL_FAILURE_RETRY(semop(sem->iSemId, &semBuf, 1)); + } else { + /* with _timeout_ */ + //PrintDbg ("UlOsaSemGet-timeout(%s).\n", sem->bName); + if (iTimeout < 0) { + //PrintError ("UlOsaSemGet-timeout: invalid arg!\n"); + return OSAL_ERROR; + } + + gettimeofday(&tv, NULL); + tv.tv_sec += iTimeout / 1000000; + tv.tv_usec += iTimeout % 1000000; + if (tv.tv_usec >= 1000000) { + tv.tv_sec += tv.tv_usec / 1000000; + tv.tv_usec %= 1000000; + } + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + + ret = OSAL_FAILURE_RETRY(semtimedop(sem->iSemId, &semBuf, 1, &ts)); + } + + /* result */ + if (ret == 0) { + //PrintDbg ("UlOsaSemGet(%s) success.\n", sem->bName); + return OSAL_OK; + } else { + if (iFlags == OSAL_SEM_NOWAIT && errno == EAGAIN) { + //PrintError ("UlOsaSemGet-nowait: now locked, failed to get.\n"); + return OSAL_ERROR; + } else if (iTimeout > 0 && errno == EAGAIN) { + //PrintError ("UlOsaSemGet-timeout(%s): time-out\n", sem->bName); + return OSAL_ERR_TIMEOUT; + } else { + //PrintError ("UlOsaSemGet error, errno=%d\n", errno); + return OSAL_ERROR; + } + } + +} +static int UlOsaNamedSemRelease(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + struct sembuf semBuf; + + if (!sem) { + return OSAL_ERROR; + } + + //PrintDbg ("UlOsaSemRelease(%s)\n", sem->bName); + semBuf.sem_num = 0; + semBuf.sem_op = 1; + semBuf.sem_flg = SEM_UNDO; + + if (semop(sem->iSemId, &semBuf, 1) == -1) { + //PrintError ("UlOsaSemRelease(%s) error! errno=%d.\n", sem->bName, errno); + return OSAL_ERROR; + } else { + return OSAL_OK; + } +} + +static int UlOsaNamedSemReset(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + union semun semUnion; + + if (!sem) { + return OSAL_ERROR; + } + + //PrintDbg ("UlOsaSemReset(%s).\n", sem->bName); + semUnion.val = sem->iCount; + if (semctl(sem->iSemId, 0, SETVAL, semUnion) == -1) { + //PrintError ("UlOsaSemReset, semctl Failed!\n"); + return OSAL_ERROR; + } + + return OSAL_OK; +} + +static int UlOsaNamedSemGetval(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + int n; + + if (!sem) { + return OSAL_ERROR; + } + n = semctl(sem->iSemId, 0, GETVAL, NULL); + if (n == -1) { + //PrintError ("UlOsaSemGetval, semctl Failed!\n"); + return OSAL_ERROR; + } else { + //PrintDbg ("UlOsaSemGetval(%s): now %d\n", sem->bName, n); + return (int)n; + } +} + +int OsaNamedSemCreate(const char bName[10], int iCount, int iAttribute, + unsigned int* puiSmid) { + return UlOsaNamedSemCreate(bName, iCount, iAttribute, puiSmid); +} + +int OsaNamedSemGet(unsigned int uiSmid, int iFlags, int iTimeout) { + return UlOsaNamedSemGet(uiSmid, iFlags, iTimeout); +} + +int OsaNamedSemRelease(unsigned int uiSmid) { + return UlOsaNamedSemRelease(uiSmid); +} + +int OsaNamedSemDelete(unsigned int uiSmid) { // Deleting Semaphore : Never USE!!! - junhyeong.kim, sukki.min 12.04.20 +//return UlOsaNamedSemDelete (uiSmid); + return -1; +} + +int OsaNamedSemGetval(unsigned int uiSmid) { + return UlOsaNamedSemGetval(uiSmid); +} + +int OsaNamedSemReset(unsigned int uiSmid) { + return UlOsaNamedSemReset(uiSmid); +} + diff --git a/osal/OsaLinuxUser.h b/osal/OsaLinuxUser.h new file mode 100755 index 0000000..af517b1 --- /dev/null +++ b/osal/OsaLinuxUser.h @@ -0,0 +1,48 @@ +/* + * ===================================================================================== + * + * Filename: OsaLinuxUser.h + * + * Description: This file includes linux header for user mode. + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef _LINUXUSER_H_ +#define _LINUXUSER_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include // posix queue +#include // posix queue +#include +#include // system V IPC +#include // system V IPC +#include // system V IPC +#include +#include +#include +#include +#include + +#include "Osal.h" + +#endif + diff --git a/osal/OsaQueue.c b/osal/OsaQueue.c new file mode 100755 index 0000000..15e3ef9 --- /dev/null +++ b/osal/OsaQueue.c @@ -0,0 +1,461 @@ +/* + * ===================================================================================== + * + * Filename: OsaQueue.c + * + * Description: Implementation of POSIX Message queue + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "OsaLinuxUser.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +//it should provide the same APIs in OsaSys5MQueue.c because it was provided before +typedef struct _osaMsgBuf_t { + long msgType; + char msgBuf[MAXML]; +} osaMsgBuf_t; + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsaQueueCreate() + // Detail Description : + // + // + // + // + // Return Data Type : Error Type. + // + // Programming Note : + // + //--------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueCreate(const char bName[10], unsigned int uiFlags, + unsigned int uiMaxnum, unsigned int uiMaxlen, unsigned int* puiQid) { +#ifndef __NO_OS__ +#ifdef POSIX_QUEUE + struct mq_attr MqAttr; + mqd_t QuId; + + if (puiQid == NULL) + { + PrintDbg("Null Argument(s) \n"); + return OSAL_ERROR; + } + + MqAttr.mq_maxmsg = uiMaxnum; + MqAttr.mq_msgsize = uiMaxlen; + + if((QuId = mq_open(bName, uiFlags, 0 ,&MqAttr)) < 0) + { + perror("mq_open() Failed: \n"); + return errno; + } + *puiQid = (unsigned int)QuId; +#else /* SYS5 MSG QUEUE*/ + /* + uiFlags ; IPC_CREAT or IPC_CREAT | IPC_EXCL + */ + struct msqid_ds tSetMqAttr; + + if (uiMaxnum == OSAL_DEFAULT_Q_NUM || uiMaxnum > MAXNBM) { + uiMaxnum = MAXNBM; + } + + if (uiMaxlen == OSAL_DEFAULT_Q_LEN || uiMaxlen > MAXML) { + uiMaxlen = MAXML; + } + + *puiQid = msgget(IPC_PRIVATE/*OsaGetKeyMQ(bName)*/, (int)uiFlags); + if (((int)*puiQid) == -1) //IPC_CREATE + { + perror("In OsaQueueCreate() : msgget: msgget failed"); + //PrintError("In OsaQueueCreate() : Error no. : %d\n",errno); + return ((int)errno); + } + + /* Get the current value from the structure for the message queue and copy it in buf_t*/ + if (msgctl((int)(*puiQid), IPC_STAT, &tSetMqAttr) == -1) { + perror("In OsaQueueCreate() : msgctl: msgctl failed"); + //PrintError("In OsaQueueCreate() : Error no. : %d\n",errno); + return ((int)errno); + } + + /*SET the values of the message structure member using IPC_SET*/ + tSetMqAttr.msg_qbytes = (unsigned long int)(uiMaxnum * uiMaxlen); + + if (msgctl((int)(*puiQid), IPC_SET, &tSetMqAttr) == -1) { + perror("In OsaQueueCreate() : msgctl: msgctl failed"); + //PrintError("In OsaQueueCreate() : Error no. : %d\n",errno); + return ((int)errno); + } + +#endif /*END OF POSIX MSG QUEUE*/ +#endif + return OSAL_OK; +} + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsaQueueClose() + // Detail Description : This is inconformance with POSIX standard. POSIX treats + // as a file + // + // Return Data Type : Error Type + // + // Programming Note : None + //--------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueClose(unsigned int uiQid) { +#ifdef POSIX_QUEUE + if (mq_close((mqd_t)uiQid) < 0) + { + perror("mq_close() Failed :\n"); + return ((int)errno); + } + return OSAL_OK; +#endif + return OSAL_OK; +}/*OsaQueueClose*/ + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsaQueueDelete() + // Detail Description : It deletes the Queue created using the puiQid and releases + // allocated resources for the message queue. + // + // Return Data Type : Error Type + // + // Programming Note : None + //--------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueDelete(const char* bName, unsigned int uiQid) { +#ifndef __NO_OS__ +#ifdef POSIX_QUEUE + if (mq_unlink(bName) < 0) + { + perror("mq_unlink() Failed :\n"); + return ((int)errno); + } +#else /*SYS5 MSG QUEUE*/ + // bName is not applicable in this case + + if (msgctl((int)uiQid, IPC_RMID, NULL) == -1) { + perror("In OsaQueueDelete(): msgctl: msgctl failed"); + //PrintError("In OsaQueueDelete(): Error no. : %d\n",errno); + return ((int)errno); + } + +#endif /* EOF POSIX_QUEUE */ +#endif + return OSAL_OK; + +} //End if OsalQueueDelete + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsaQueueSend + // Detail Description : This function sends messages on queues. + // + // Return Data Type : ErrorTypes + // + // Programming Note : + //-------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueSend(unsigned int uiQid, unsigned int uiFlags, void* pvMsg_buf, + unsigned int uiMsgLen, unsigned int uiPriority, pOsaTime_t ptTimeOut) + +{ +#ifndef __NO_OS__ +#ifdef POSIX_QUEUE + + unsigned int err_no; + struct mq_attr tMqAttr; + + if (uiFlags & OSAL_Q_NOWAIT) + { + tMqAttr.mq_flags = O_NONBLOCK; + + if((err_no = mq_setattr((mqd_t)uiQid, &tMqAttr, (struct mq_attr *)NULL)) < 0) + { + ////PrintError("mq_setattr(): mq_setattr() Failed errno=%d\n",err_no,0,0,0,0,0); //COMMON_071024_1 + return (OSAL_ERROR); + } + } + + if ((err_no=mq_send((mqd_t)uiQid, (const char *)pvMsg_buf, uiMsgLen, uiPriority)) < 0) + { + ////PrintError("mq_send():Failed errno=%d qid=%x flag=%d\n",err_no,uiQid,uiFlags,0,0,0); //COMMON_071024_1 + return (OSAL_ERROR); + } + +#else /*SYS5 MSG QUEUE*/ + /* + uiFlags : IPC_NOWAIT , ZERO + pMsgLen: len - sizeof(int); + */ + osaMsgBuf_t osaMsg; + int ret; + + if (uiMsgLen > MAXML) { + ////PrintError("Message length exceeds max limit of %d\n",MAXML); //COMMON_071024_1 + return OSAL_ERROR; + } + + //Copy the message into OsaMsgStructure + osaMsg.msgType = 1; /* Should always be > 0*/ + memcpy((void *)osaMsg.msgBuf, pvMsg_buf, uiMsgLen); + + /* OSAL_080714 */ + ret = OSAL_FAILURE_RETRY( + msgsnd((int )uiQid, (void* )&osaMsg, uiMsgLen, (int )uiFlags)); + if (ret != 0) { + //perror("In OsaQueueSend () : msgsnd failed"); //COMMON_071024_1 + ////PrintError("In OsaQueueSend() : Error no. : %d\n",errno); //COMMON_071024_1 + return ((int)errno); + } +#endif + +#endif /* EOF POSIX_QUEUE */ + + return OSAL_OK; +} + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsaQueueReceive + // Detail Description : It recieves the messages from the Message queue + // + // Return Data Type : Error Tyoe + // + // Programming Note : + //-------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueReceive(unsigned int uiQid, unsigned int uiFlags, void* pvMsgBuf, + unsigned int uiBufLen, unsigned int* pMsgLen, pOsaTime_t ptTimeOut) + +{ +#ifndef __NO_OS__ +#ifdef POSIX_QUEUE + /* + uiFlags : IPC_NOWAIT , ZERO + */ +#if 0 + struct timespec absTimeOut; +#endif + struct mq_attr tMqAttr; + int uiMsgLen =0; + + if (uiFlags & OSAL_Q_NOWAIT) + { + tMqAttr.mq_flags = O_NONBLOCK; + } + else + { + tMqAttr.mq_flags = 0; + } +#if 0 + if (ptTimeOut && (!(uiFlags & OSAL_Q_NOWAIT))) + { + absTimeOut.tv_sec = ptTimeOut->Sec; + absTimeOut.tv_nsec = ptTimeOut->NanoSec; + } + else + { + absTimeOut.tv_sec = 0; + absTimeOut.tv_nsec = 0; + } +#endif + if(mq_setattr((mqd_t)uiQid, &tMqAttr, (struct mq_attr *)NULL) < 0) + { + perror("OsaQueueSend(): mq_setattr() Failed \n"); + return ((int)errno); + } + + if ((uiMsgLen = mq_receive((mqd_t)uiQid, (char *)pvMsgBuf, uiBufLen, + (unsigned int *)NULL)) < 0) + { + perror("OsaQueueReceive(): mq_receive() Failed \n"); + return ((int)errno); + } + + // Update the received message length + *pMsgLen = uiMsgLen; +#else /*SYS5 MSG QUEUE*/ + /* + uiFlags : IPC_NOWAIT, MSG_NOERROR + buf_len : len - sizeof(int); + */ + + int iRet = 0; + osaMsgBuf_t osaMsg; + + /* + type field is always ZERO as oldest message on the queue is to be returned . + */ + /* OSAL_080714 */ + iRet = OSAL_FAILURE_RETRY( + msgrcv((int)uiQid,(void*)&osaMsg, uiBufLen,OSAL_ZERO , (int)uiFlags)); + + if (iRet == -1) { + *pMsgLen = OSAL_ZERO; + pvMsgBuf = NULL; + + if (errno != ENOMSG) { + perror("In OsaQueueReceive() : msgrcv failed"); + //PrintError("In OsaQueueReceive() : Msg id %d, Error no. : %d\n", uiQid, errno); + } + return ((int)errno); + } else { + *pMsgLen = iRet; + memcpy(pvMsgBuf, (void *)osaMsg.msgBuf, (unsigned int)iRet); + } +#endif +#endif /* EOF POSIX_QUEUE */ + return OSAL_OK; +} + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsaQueueGetinfo + // Detail Description : It gets Message queue info . + // + // Return Data Type : Error Type + // + // Programming Note : It only get the number of messages in the queue(mqlen) + // and maximum message length allowed (maxlen). + //--------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueGetinfo(unsigned int uiQid, void* pvBuf) { +#ifndef __NO_OS__ +#ifdef POSIX_QUEUE + struct mq_attr tMqAttr; + + if (pvBuf == NULL) + { + //PrintError("Null Argument(s) \n"); + return OSAL_ERROR; + } + + if (mq_getattr((mqd_t)uiQid, &tMqAttr) , 0) + { + perror("OsaQueueGetinfo(): mq_getattr() Failed \n"); + return ((int)errno); + } + + ((pOsaQueueInfo_t)pvBuf)->flags = tMqAttr.mq_flags; + ((pOsaQueueInfo_t)pvBuf)->mqlen = tMqAttr.mq_curmsgs; + ((pOsaQueueInfo_t)pvBuf)->mqmax = tMqAttr.mq_maxmsg; + ((pOsaQueueInfo_t)pvBuf)->maxlen = tMqAttr.mq_msgsize; +#else /*SYS5 MSG QUEUE*/ + struct msqid_ds buf; + struct QueueInfo *data_t; + + if (pvBuf == NULL) { + return OSAL_ERROR; + } + + data_t = (struct QueueInfo*)pvBuf; + + if (msgctl((int)uiQid, IPC_STAT, &buf) < 0) { + perror("In OsaQueueGetinfo() : msgctl: msgctl failed"); + //PrintError("In OsaQueueGetinfo() : Error no. : %d\n",errno); + return ((int)errno); + + } + + data_t->flags = 0; + data_t->wqlen = 0; + data_t->wtid = 0; + data_t->mqlen = buf.msg_qnum; + data_t->mqmax = 0; + data_t->tid_ntfy = 0; + data_t->ev_ntfy = 0; + data_t->maxlen = buf.msg_qbytes; +#endif +#endif /* EOF POSIX_QUEUE */ + + return OSAL_OK; +} + +/* + // $$$ + //--------------------------------------------------------------------------------- + // Function Name : OsalQueueSetinfo + // Detail Description : it sets the corresponding Info for the queue + // + // Return Data Type : ErrorType + // + // Programming Note : + //--------------------------------------------------------------------------------- + // $$$ + */ +int OsaQueueSetinfo(unsigned int uiQid, void* pvBuf) { +#ifndef __NO_OS__ +#ifdef POSIX_QUEUE + + struct mq_attr tMqAttr; + + if (pvBuf == NULL) + { + //PrintError("Null Argument(s) \n"); + return OSAL_ERROR; + } + + tMqAttr.mq_flags = ((pOsaQueueInfo_t)pvBuf)->flags; + + if (mq_setattr((mqd_t)uiQid, &tMqAttr, (struct mq_attr *)NULL) , 0) + { + perror("OsaQueueGetinfo(): mq_getattr() Failed \n"); + return ((int)errno); + } +#else /*SYS5 MSG QUEUE*/ + struct msqid_ds buf; + struct QueueInfo *data_t; + + if (pvBuf == NULL) { + return OSAL_ERROR; + } + + data_t = (struct QueueInfo*)pvBuf; + + msgctl((int)uiQid, IPC_STAT, &buf); + buf.msg_qbytes = data_t->maxlen; + + if (msgctl((int)uiQid, IPC_SET, &buf) < 0) { + perror("In OsaQueueGetinfo() : msgctl: msgctl failed"); + //PrintError("In OsaQueueGetinfo() : Error no. : %d\n",errno); + return ((int)errno); + } +#endif +#endif /* EOF POSIX_QUEUE */ + + return OSAL_OK; +} + diff --git a/osal/OsaSem.c b/osal/OsaSem.c new file mode 100755 index 0000000..eaef3e1 --- /dev/null +++ b/osal/OsaSem.c @@ -0,0 +1,448 @@ +/* + * ===================================================================================== + * + * Filename: OsaSem.c + * + * Description: Semaphore and Mutex implementation + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "OsaLinuxUser.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +/* OSA_070901 : Replace System V semaphore with POSIX semaphore API. */ +typedef struct _UlOsaSem { + sem_t sem; + int iAttribute; + int iCount; + char bName[16]; +} UlOsaSem_t; + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +/* TODO: apply iAttribute */ +// COMMON_071008_1 +static int UlOsaSemCreate(const char bName[10], int iCount, int iAttribute, + unsigned int* puiSmid) { + UlOsaSem_t* sem; + + sem = (UlOsaSem_t*)malloc(sizeof(*sem)); + if (!sem) { + //PrintError ("UlOsaSemCreate, Out of memory!\n"); + return OSAL_ERROR; + } + + if (sem_init(&sem->sem, 1, (unsigned int)iCount) < 0) { + //PrintError ("UlOsaSemCreate, sem_init Failed!\n"); + free(sem); + return OSAL_ERROR; + } + + sem->iAttribute = iAttribute; + sem->iCount = iCount; + + memcpy((void*)sem->bName, (const void*)bName, (size_t)10); + sem->bName[10] = '\0'; + + *puiSmid = (unsigned int)sem; + + return OSAL_OK; +} + +static int UlOsaSemDelete(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + + if (!sem) { + return OSAL_ERROR; + } + + sem_destroy(&sem->sem); + free(sem); + + return OSAL_OK; +} + +static int UlOsaSemGet(unsigned int uiSmid, int iFlags, int iTimeout) { + int ret; + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + + if (!sem) { + return OSAL_ERROR; + } + + if (iFlags == OSAL_SEM_NOWAIT) { + /* no wait */ + //PrintDbg ("UlOsaSemGet-nowait(%s).\n", sem->bName); + ret = sem_trywait(&sem->sem); + } else if (iTimeout == 0) { + /* wait _inifinite_ */ + //PrintDbg ("UlOsaSemGet-infinite(%s).\n", sem->bName); + ret = OSAL_FAILURE_RETRY(sem_wait(&sem->sem)); + } else { + /* with _timeout_ */ + //PrintDbg ("UlOsaSemGet-timeout(%s).\n", sem->bName); + if (iTimeout < 0) { + //PrintError ("UlOsaSemGet-timeout: invalid arg!\n"); + return OSAL_ERROR; + } +#if 0 + struct timeval tv; + + gettimeofday (&tv, NULL); + tv.tv_sec += iTimeout / 1000000; + tv.tv_usec += iTimeout % 1000000; + if (tv.tv_usec >= 1000000) + { + tv.tv_sec += tv.tv_usec / 1000000; + tv.tv_usec %= 1000000; + } + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + + ret = OSAL_FAILURE_RETRY(sem_timedwait (&sem->sem, &ts)); +#endif + do // SoC_D00003324 + { + ret = sem_trywait(&sem->sem); + if (ret != 0 && errno == EAGAIN) { + usleep(10000); + iTimeout -= 10000; + } else // No-Error + Error without EAGAIN + { + break; + } + } while (iTimeout > 0); + } + + /* result */ + if (ret == 0) { + //PrintDbg ("UlOsaSemGet(%s) success.\n", sem->bName); + return OSAL_OK; + } else { + if (iFlags == OSAL_SEM_NOWAIT && errno == EAGAIN) { +// PrintError ("UlOsaSemGet-nowait: now locked, failed to get.\n"); + return OSAL_ERROR; + } else if (iFlags == OSAL_SEM_WAIT && iTimeout <= 0) {// Before : cond - (iTimeout > 0 && errno == ETIMEDOUT) + //PrintError ("UlOsaSemGet-timeout(%s): time-out\n",sem->bName); + return OSAL_ERR_TIMEOUT; + } else { + //PrintError ("UlOsaSemGet error, errno=%d\n", errno); + return OSAL_ERROR; + } + } +} + +static int UlOsaSemRelease(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + if (!sem) { + return OSAL_ERROR; + } + + //PrintDbg ("UlOsaSemRelease(%s)\n", sem->bName); + if (sem_post(&sem->sem) != 0) { + //PrintError ("UlOsaSemRelease(%s) error! errno=%d.\n", sem->bName, errno); + return OSAL_ERROR; + } else { + return OSAL_OK; + } +} + +static int UlOsaSemReset(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + if (!sem) { + return OSAL_ERROR; + } + //PrintDbg ("UlOsaSemReset(%s).\n", sem->bName); + + /* For threads currently blocked, the effect of destroying is not defined in POSIX. + Currently, this will not release any blocked threads. */ + if (sem_destroy(&sem->sem) < 0) { + //PrintError ("UlOsaSemReset, sem_destroy errno=%d\n", errno); + return OSAL_ERROR; + } + + /* re-init */ + sem_init(&sem->sem, 1, (unsigned int)sem->iCount); + + return OSAL_OK; +} + +static int UlOsaSemGetval(unsigned int uiSmid) { + UlOsaSem_t *sem = (UlOsaSem_t*)uiSmid; + int n; + if (!sem) { + return OSAL_ERROR; + } + + if (sem_getvalue(&sem->sem, &n) != 0) { + //PrintError ("UlOsaSemGetval(%s), sem_getvalue errno=%d\n", sem->bName, errno); + return OSAL_ERROR; + } else { + //PrintDbg ("UlOsaSemGetval(%s): now %d\n", sem->bName, n); + return (int)n; + } +} + +/** + * @brief Create a semaphore object. + * @remarks the semaphore value shall be incremented more than initial value. + * @param bName [in] semaphore name, for debugging. + * @param iCount [in] initial semaphore value + * @param iAttribute [in] not used now implementation. + * @param puiSmid [out] semaphore object ID. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemCreate(const char bName[10], int iCount, int iAttribute, + unsigned int* puiSmid) { + /* OSA_070901 */ + return UlOsaSemCreate(bName, iCount, iAttribute, puiSmid); +} + +/** + * @brief Lock a semaphore. + * @remarks perform a semaphore lock operation. + * @param uiSmid [in] semaphore object ID created by OsaSemCreate. + * @param iFlags [in] [OSAL_SEM_NOWAIT | OSAL_SEM_WAIT] + - OSAL_SEM_NOWAIT : lock the semaphore only if the semaphore value is + currently not locked. otherwise, return OSAL_ERROR. + - OSAL_SEM_WAIT : lock the semaphore. If the semaphore values is + currently locked, the calling thread shall be blocked. + In linux kernel mode, iFlags is not used, always wait infinitely. + * @param iTimeout [in] timeout value in _microsecond_. + Only affected when iFlags is OSAL_SEM_WAIT. + - 0 : wait infinitely. + - positive value : wait will be terminated when expires and return OSAL_ERR_TIMEOUT. + - negative value : error. + * @retval [OSAL_OK | OSAL_ERROR | OSAL_ERR_TIMEOUT] + */ +int OsaSemGet(unsigned int uiSmid, int iFlags, int iTimeout) { + /* OSA_070901 */ + return UlOsaSemGet(uiSmid, iFlags, iTimeout); +} + +/** + * @brief Unlock a semaphore + * @remarks If the semaphore value is positive currently, then no threads were + blocked by semaphore and simply semaphore value is incremented. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemRelease(unsigned int uiSmid) { + /* OSA_070901 */ + return UlOsaSemRelease(uiSmid); +} + +/** + * @brief Destroy a semaphore object. + * @remarks It is unsafe if any thread is currently blocked by the semaphore. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemDelete(unsigned int uiSmid) { + /* OSA_070901 */ + return UlOsaSemDelete(uiSmid); +} + +/** + * @brief Get the current semaphore value + * @remarks If the semaphore is locked, returns zero or negative value. + Only implemented in linux user mode. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemGetval(unsigned int uiSmid) { + /* OSA_070901 */ + return UlOsaSemGetval(uiSmid); +} + +/** + * @brief Reset the semaphore to initial state. + * @remarks Set the semaphore value to iCount that given by OsaSemCreate(). + Blocked threads by this semaphore shall not released if initial + value was zero or negative. If initial value was positive, + same number(semaphore value) of threads shall be released. + Only implemented in linux user mode. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemReset(unsigned int uiSmid) { + /* OSA_070901 */ + return UlOsaSemReset(uiSmid); +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaMutCreate + // Detail Description : This function is used to creat a mutex. + // Mutex attributes can be either "Fast" mutex, "Recursive + // mutexes or "Error checking " mutex . + // piMutid is the pointer to the new mutex ID created else + // is NULL. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaMutCreate(const char bName[10], int iAttributes, unsigned int* puiMutid) { + pthread_mutexattr_t attr_t; + pthread_mutex_t* pmutex_t; + + if (puiMutid == NULL) { + //PrintError("In OsaMutCreate() : NULL PTR ERROR"); + return OSAL_ERROR; + } + + pmutex_t = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (pmutex_t) { + pthread_mutexattr_init(&attr_t); + + switch (iAttributes) { + case OSAL_MU_RECURSIVE: + pthread_mutexattr_settype(&attr_t, PTHREAD_MUTEX_RECURSIVE_NP); + pthread_mutex_init(pmutex_t, (const pthread_mutexattr_t *)&attr_t); + break; + case OSAL_MU_NOERROR: + pthread_mutexattr_settype(&attr_t, PTHREAD_MUTEX_ERRORCHECK_NP); + pthread_mutex_init(pmutex_t, (const pthread_mutexattr_t *)&attr_t); + break; + default: + pthread_mutex_init(pmutex_t, NULL); + break; + } + + (*puiMutid) = (unsigned int)pmutex_t; + + pthread_mutexattr_destroy(&attr_t); + } else { + //PrintError("In OsaMutCreate() : No memory"); + return OSAL_ERROR; + } + + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaMutDelete + // Detail Description : This function deletes the Mutex with corresponding + // mutex ID . + // This function deallocates any system resources allocated + // by the system for use by this task for this Mutex. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + // + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaMutDelete(unsigned int uiMutid) { + int iRet; + + pthread_mutex_t* pmutex_t = (pthread_mutex_t *)uiMutid; + if (pmutex_t == NULL) { + return OSAL_OK; + } + + iRet = pthread_mutex_destroy(pmutex_t); + if (iRet < 0) { + perror("In OsaMutDelete() : failed "); + //PrintError("Error no. : %d\n",errno); + return ((int)errno); + } + + free(pmutex_t); + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaMutRelease + // Detail Description : This function unlocks the mutex. + // + // Return Data Type : ErrorType + // + // Programming Note : None + // + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaMutRelease(unsigned int uiMutid) { + int iRet; + + pthread_mutex_t* pmutex_t = (pthread_mutex_t *)uiMutid; + iRet = pthread_mutex_unlock(pmutex_t); + if (iRet < 0) { + perror("In OsaMutRelease() : failed "); + //PrintError("Error no. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaMutGet + // Detail Description : This function locks the mutex. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaMutGet(unsigned int uiMutid, int iFlags, int iTimeout) { + int iRet; + pthread_mutex_t* pmutex_t = (pthread_mutex_t *)uiMutid; + iRet = pthread_mutex_lock(pmutex_t); + if (iRet < 0) { + perror("In OsaMutGet() : failed "); + //PrintError("Error no. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +// $$$ +//----------------------------------------------------------------------------- +// Function Name : OsaMutTryGet +// Detail Description : This function locks the mutex. But if the mutex is +// already locked, it returns immediately with error. +// +// Return Data Type : ErrorType +// +// Programming Note : None. +//------------------------------------------------------------------------------ +// $$$ +int OsaMutTryGet(unsigned int uiMutid, int iFlags, int iTimeout) { + int iRet; + + pthread_mutex_t* pmutex_t = (pthread_mutex_t *)uiMutid; + iRet = pthread_mutex_trylock(pmutex_t); + if (iRet) { + return ((int)iRet); + } + return OSAL_OK; +} + diff --git a/osal/OsaSignal.c b/osal/OsaSignal.c new file mode 100755 index 0000000..59144c1 --- /dev/null +++ b/osal/OsaSignal.c @@ -0,0 +1,146 @@ +/* + * ===================================================================================== + * + * Filename: OsaSignal.c + * + * Description: Signal implementation + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "OsaLinuxUser.h" + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaSigProcmask + // Detail Description : Examine and/or change the list of currently blocked + // signals + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaSigProcmask(int iMode, const unsigned int* puiNewmask, + unsigned int* puiOldmask) { + int iRet; + iRet = sigprocmask(iMode, (const sigset_t *)puiNewmask, + (sigset_t*)puiOldmask); + if (iRet) { + perror("SigProcMask: SigProcMask Failed "); + //PrintError("Error No. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaSigSuspend + // Detail Description : Suspend the task until delivery of a signal + // + // Return Data Type : ErroType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaSigSuspend(unsigned int* puiPending) { + int iRet; + + iRet = sigpending((sigset_t *)puiPending); + if (iRet) { + perror("SigSuspend: SigSuspend INTR "); + //PrintError("Error No. : %d\n",errno); + return ((int)errno); + + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaSigTimedwait + // Detail Description : Wait for a signal + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ + +int OsaSigTimedwait(void) { + int iRet; + iRet = pause(); + if (iRet) { + perror("TimeWait: TimeWait INTR "); + //PrintError("Error No. : %d\n",errno); + return ((int)errno); + + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaSigSetmask + // Detail Description : Set the signal mask + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaSigSetmask(int iSigno) { + struct sigaction Action_t; + + Action_t.sa_flags = 0; + + if (sigaddset(&(Action_t.sa_mask), iSigno) < 0) { + perror("sigaddset: sigaddset Failed "); + //PrintError("Error No. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaKill + // Detail Description : Send a kill signal to a task + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaKill(int iId, int iSigno) { + if (kill(iId, iSigno) < 0) { + perror("KILL: Error "); + return OSAL_ERROR; + } + return OSAL_OK; +} diff --git a/osal/OsaTask.c b/osal/OsaTask.c new file mode 100755 index 0000000..492a437 --- /dev/null +++ b/osal/OsaTask.c @@ -0,0 +1,424 @@ +/* + * ===================================================================================== + * + * Filename: OsaTask.c + * + * Description: Thread implementation + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "OsaLinuxUser.h" + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define TASK_COMM_LEN 16 + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +typedef void (*pEntry_f)(void*); + +typedef struct { + char aName[TASK_COMM_LEN]; + pEntry_f pEntryFunc; + void* pArg; +} ThreadParam_t; + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +static void* _thread_start_handler(void* pArg) { + int iRet; + ThreadParam_t sThreadParam; + + if (NULL == pArg) { + return 0; + } + sThreadParam = *((ThreadParam_t*)pArg); + free(pArg); + + iRet = prctl(PR_SET_NAME, sThreadParam.aName, 0, 0, 0); + if (iRet) { + perror("In OsaTaskSpawn() : prctl() Failed\n "); + //PrintError("In OsaTaskSpawn() : prctl() error no. : %d\n", iRet); + } + + (*sThreadParam.pEntryFunc)(sThreadParam.pArg); + return 0; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskSpawn + // Detail Description : This API function creates and activates a new task + // with a specified priority and options. It returns + // a system-assigned ID. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTaskSpawn(const char* pName, unsigned int* puiTid, int iPriority, + int iStacksize, unsigned int uiMode, void* pEntryPt, int iArg1, int iArg2, + int iArg3, int iArg4, void* pvArg5) { + +#define OSAL_SCHED_POLICY SCHED_FIFO + + int iRet; + pthread_t curThread = pthread_self(); + pthread_t createThread; + pthread_attr_t tattr_t; + struct sched_param param_t; + int curThreadPolicy; + int createThreadPolicy = OSAL_SCHED_POLICY; + ThreadParam_t* pThreadParam; + + pthread_getschedparam(curThread, &curThreadPolicy, ¶m_t); + + if (iPriority == 0) { + createThreadPolicy = SCHED_OTHER; + } else if (iPriority > sched_get_priority_max(OSAL_SCHED_POLICY)) { + iPriority = sched_get_priority_max(OSAL_SCHED_POLICY); + } else if (iPriority < sched_get_priority_min(OSAL_SCHED_POLICY)) { + iPriority = sched_get_priority_min(OSAL_SCHED_POLICY); + } + + if (iStacksize < OSAL_DEFAULT_STSZ) { + iStacksize = OSAL_DEFAULT_STSZ; + } + + /* set thread parameters: name, entry func and argument. */ + pThreadParam = (ThreadParam_t*)malloc(sizeof(ThreadParam_t)); + + if (NULL == pThreadParam) { + perror("Memory Allocation Failed : \n"); + return OSAL_ERROR; + } + + memset(pThreadParam->aName, 0x00, TASK_COMM_LEN); + strncpy(pThreadParam->aName, pName, (TASK_COMM_LEN - 1)); + pThreadParam->pEntryFunc = (pEntry_f)pEntryPt; + pThreadParam->pArg = pvArg5; + + /* set stack size : 16Kbyte */ + if (iStacksize <= PTHREAD_STACK_MIN) { + iRet = pthread_create(&createThread, (pthread_attr_t *)NULL, + _thread_start_handler, (void*)pThreadParam); + if (iRet) { + *puiTid = (unsigned int)NULL; + free(pThreadParam); + perror("In OsaTaskSpawn() : pthread create Failed\n "); + //PrintError("In OsaTaskSpawn() : error no. : %d\n", iRet); + return ((int)iRet); + } + } + // set Stakc size by iStacksize, using pthread_attr_t + else { + iRet = pthread_attr_init(&tattr_t); + if (iRet) { + *puiTid = (unsigned int)NULL; + free(pThreadParam); + perror("In OsaTaskSpawn() : pthread attr init Failed\n "); + //PrintError("In OsaTaskSpawn() : error no. : %d\n", iRet); + return ((int)iRet); + } + iRet = pthread_attr_setstacksize(&tattr_t, (unsigned int)iStacksize); + if (iRet) { + *puiTid = (unsigned int)NULL; + free(pThreadParam); + perror("In OsaTaskSpawn() : pthread attr setstacksize Failed\n "); + //PrintError("In OsaTaskSpawn() : error no. : %d\n", iRet); + pthread_attr_destroy(&tattr_t); + return ((int)iRet); + } + iRet = pthread_create(&createThread, (pthread_attr_t *)&tattr_t, + _thread_start_handler, (void*)pThreadParam); + if (iRet) { + *puiTid = (unsigned int)NULL; + free(pThreadParam); + perror("In OsaTaskSpawn() : pthread create Failed\n "); + //PrintError("In OsaTaskSpawn() : error no. : %d\n", iRet); + pthread_attr_destroy(&tattr_t); + return ((int)iRet); + } + + pthread_attr_destroy(&tattr_t); + } + + /* Set Priority by iPriority , if different from parent priority */ + if (iPriority != param_t.__sched_priority) { + param_t.__sched_priority = iPriority; + iRet = pthread_setschedparam(createThread, createThreadPolicy, ¶m_t); + if (iRet) { + *puiTid = (unsigned int)NULL; + perror("In OsaTaskSpawn() : pthread setschedparam Failed\n "); + //PrintError("In OsaTaskSpawn() : error no. : %d\n", iRet); + pthread_kill(createThread, (int)NULL); + return ((int)iRet); + } + } + + iRet = pthread_detach(createThread); + if (iRet) { + *puiTid = (unsigned int)NULL; + perror("In OsaTaskSpawn() : pthread_detach Failed\n "); + //PrintError("In OsaTaskSpawn() : detach error no. : %d\n", iRet); + pthread_kill(createThread, (int)NULL); + return ((int)iRet); + } + *puiTid = (unsigned int)createThread; + + //PrintDbg("%s thread created policy: %d, priority %d\n", pName, createThreadPolicy, iPriority); + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaExit + // Detail Description : This function terminates the calling thread. + // + // Return Data Type : Void + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +void OsaExit(int iStatus) { + pthread_exit(0); +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskDelete + // Detail Description : This function terminates the thread having the + // corresponding thread ID . + // + // Return Data Type : ErrorType + // + // Programming Note : None + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTaskDelete(unsigned int uiTid) { + int iRet = 0; + iRet = pthread_cancel((pthread_t)uiTid); + if (iRet) { + perror("In OsaTaskDelete() : TaskDelete Failed "); + //PrintError("In OsaTaskDelete() : error no. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskSetPriority + // Detail Description : This function sets the Priority for the created thread. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTaskSetPriority(unsigned int uiTid, int iNewpriority) { + int iRet, iPolicy; + struct sched_param param_t; + /* sched_priority will be the priority of the thread */ + param_t.sched_priority = iNewpriority; + /* only supported policy, others will result in ENOTSUP */ + iPolicy = SCHED_FIFO; + /* scheduling parameters of target thread */ + iRet = pthread_setschedparam(uiTid, iPolicy, ¶m_t); + if (iRet) { + perror("In OsaTaskSetPriority() : TaskSetPriority set Failed "); + //PrintError("In OsaTaskSetPriority() : error no. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskGetPriority + // Detail Description : This function gets the corresponding priority of the + // supplied thread ID . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ + +int OsaTaskGetPriority(unsigned int uiTid, int* piPriority) { + int iRet, iPolicy = 0; + struct sched_param param_t; + iRet = pthread_getschedparam(uiTid, (int *)&iPolicy, ¶m_t); + if (iRet) { + piPriority = NULL; + perror("In OsaTaskGetPriority() : TaskGetPriority Failed "); + //PrintError("In OsaTaskGetPriority() : error no. : %d\n",errno); + return ((int)errno); + } + *piPriority = param_t.sched_priority; + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskNanosleep + // Detail Description : This function makes the thread to sleep for nanosec + // precision. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ + +int OsaTaskNanosleep(int iNanosec) { + struct timespec timeSpec_t, timeSpecRem_t; + int iRetval; + + timeSpec_t.tv_sec = 0; + + if (iNanosec > OSAL_NSEC_MAX) { + iNanosec = OSAL_NSEC_MAX; + } + + timeSpec_t.tv_nsec = iNanosec; + + iRetval = nanosleep(&timeSpec_t, &timeSpecRem_t); + + if (iRetval) { + perror("TaskNanoSleep: TaskNanoSleep Failed "); + //PrintError("Error No. : %d\n",errno); + return ((int)errno); + + } + + return OSAL_OK; +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskGetId + // Detail Description : This function get the current thread ID. + // + // Return Data Type : Current thread ID . + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTaskGetId(void) { + return ((pthread_t)pthread_self()); +} + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTaskDelaymsecs + // Detail Description : This function makes the thread to sleep for millisec + // precision. + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTaskDelaymsecs(unsigned int uiMsec) { + unsigned int uiDiv, uiRem; + struct timespec timeSpec_t, timeSpecRem_t; + int iRetval; + + uiDiv = uiMsec / 1000; + uiRem = uiMsec % 1000; + + timeSpec_t.tv_sec = uiDiv; + timeSpec_t.tv_nsec = uiRem * 1000000; + + iRetval = nanosleep(&timeSpec_t, &timeSpecRem_t); + + if (iRetval) { + perror("In OsaTaskDelaymsecs() : TaskNanoSleep Failed "); + //PrintError("In OsaTaskDelaymsecs() : error no. : %d\n",errno); + return ((int)errno); + } + return OSAL_OK; +} + +/***************************************************************************** + ** OsaTaskDelayticks - + *****************************************************************************/ +int OsaTaskDelayticks(int iTicks) { + struct timespec ts, tsr; + unsigned int hz; + int ret; + + hz = OsaGetTicksPerSecond(); + ts.tv_sec = iTicks / hz; + ts.tv_nsec = (iTicks % hz) * (1000 * 1000 * 1000 / hz); + + for (;;) { + ret = nanosleep(&ts, &tsr); + if (ret == 0) { + return OSAL_OK; + } else if (errno == EINTR) { + ts = tsr; + } else { + return OSAL_ERROR; + } + } +} + +/***************************************************************************** + ** OsaTaskSuspend- + *****************************************************************************/ +int OsaTaskSuspend(unsigned int uiTid) { + //Not Implemented + return OSAL_OK; + +} + +/***************************************************************************** + ** OsaTaskResume- + *****************************************************************************/ +int OsaTaskResume(unsigned int uiTid) { + //Not Implemented + return OSAL_OK; + +} + +/***************************************************************************** + ** OsaTaskRestart- + *****************************************************************************/ +int OsaTaskRestart(unsigned int uiTid) { + //Not Implemented + return OSAL_OK; +} diff --git a/osal/Osal.h b/osal/Osal.h new file mode 100755 index 0000000..d7ef083 --- /dev/null +++ b/osal/Osal.h @@ -0,0 +1,459 @@ +/* + * ===================================================================================== + * + * Filename: Osal.h + * + * Description: OSAL header file + * + * Version: 1.0 + * Created: 26 March 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef _OSAL_H_ +#define _OSAL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#if defined(__KERNEL__) +#include +#else + +#include +#include +#include + +#endif + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define OSAL_OK 0x00 +#define OSAL_EXIST -2 +#define OSAL_ERROR -1 +#define OSAL_ZERO 0x00 + +#if !defined(__KERNEL__) +#if defined(_GNU_SOURCE) +#define OSAL_FAILURE_RETRY(expr) TEMP_FAILURE_RETRY(expr) +#else +#define OSAL_FAILURE_RETRY(expr) \ + ({ long int _ret; \ + do _ret = (long int) (expr); \ + while (_ret == -1L && errno == EINTR); \ + _ret; }) +#endif /* _GNU_SOURCE */ +#endif /*!__KERNEL__ */ + +#if defined(__KERNEL__) +#define OSA_Q_NOWAIT 0x1 +#define OSA_Q_WAIT 0x2 +#elif defined(POSIX_QUEUE) //user mode, posix queue +#define OSA_Q_NOWAIT O_NONBLOCK +#define OSA_Q_WAIT 0x00 +#elif defined(__NO_OS__) +#define OSA_Q_NOWAIT 0 +#define OSA_Q_WAIT 0 +#else //user mode, system v ipc +#define OSA_Q_NOWAIT IPC_NOWAIT +#define OSA_Q_WAIT 0x00 +#endif + +#define OSAL_ERR_TIMEOUT 0x37 +#define OSAL_ERR_NOMSG 0x01 + +#define OSAL_TIMER_PERODIC 1 +#define OSAL_TIMER_ONESHOT 0 +#define OSAL_NSEC_MAX 999999999 + +#if defined(__KERNEL__) // Linux kernel mode +#define OSAL_MIN_STSZ (16*1024) /*kthread min statck size*/ +#else // Linux user mode +#undef PTHREAD_STACK_MIN ///* PTHREAD_STACK_MIN is defined in , It's configure stack limit in pthread +#define PTHREAD_STACK_MIN (16*1024) +#define OSAL_MIN_STSZ PTHREAD_STACK_MIN +#endif + +#define OSAL_MAX_STSZ (16*1024) +#define OSAL_DEFAULT_STSZ OSAL_MIN_STSZ +#define OSAL_DEFAULT_PRIORITY 0 + +#define MAXNBM 1024 //5 +#define MAXML 8192 +#define OSAL_DEFAULT_Q_NUM 1 +#define OSAL_DEFAULT_Q_LEN 1 + +#define OSAL_Q_NOWAIT OSA_Q_NOWAIT +#define OSAL_Q_WAIT OSA_Q_WAIT + +#define OSAL_Q_CREAT O_CREAT +#define OSAL_Q_EXCL O_EXCL + +//Mutex +#define OSAL_MU_RECURSIVE 0x00000001 +#define OSAL_MU_NOERROR 0x00000002 +#define OSAL_MU_DEFAULT 0x00000000 + +//Semaphore +#define OSAL_SINGLE_SEM 1 +#define OSAL_SEM_CREAT IPC_CREAT +#define OSAL_SEM_EXCL IPC_EXCL +#define OSAL_SEM_WAIT -1 +#define OSAL_SEM_NOWAIT 0 +#define OSAL_DEFAULT_SEMVAL 1 + +// Signal +#define OSAL_SIG_BLOCK SIG_BLOCK +#define OSAL_SIG_UNBLOCK SIG_UNBLOCK +#define OSAL_SIG_SETMASK SIG_SETMASK + +#if defined(__KERNEL__) +#define OSAL_ASSERT(expression) \ + { \ + if(!expression){ \ + panic("Assertion: \"%s\" failed, in file %s, line %d\n", \ + #expression, __FILE__, __LINE__); \ + } \ + } +#else +#define OSAL_ASSERT(expression) assert(expression) +#endif + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +typedef struct QueueInfo { + char name[10]; /* name of the queue */ + unsigned int flags; /* queue attributes */ + unsigned int wqlen; /* number of waiting tasks */ + unsigned int wtid; /* ID of the first waiting task */ + unsigned int mqlen; /* number of messages in the queue */ + unsigned int mqmax; /* max number of messages allowed */ + unsigned int tid_ntfy; /* task to be notified of message arrival */ + unsigned int ev_ntfy; /* events to post to notify message arrival */ + unsigned int maxlen; /* maximum message length allowed */ +} OsaQueueInfo_t, *pOsaQueueInfo_t; + +typedef struct _Osa_Time { + unsigned int Sec; + unsigned int NanoSec; +} OsaTime_t, *pOsaTime_t; + +typedef enum { + CACHE_FLUSH = 0, CACHE_INVALIDE, CACHE_CLEAN, CACHE_FLUSH_ALL, +} OsaCacheCtrl_t; + +typedef struct _cache_io_param { + OsaCacheCtrl_t type; + unsigned int startAddr; + unsigned int endAddr; +} ioCacheData_t, *pioCacheData_t; + +/*----------------------------------------------------------------------------- + * Functions + *-----------------------------------------------------------------------------*/ +int OsaTaskSpawn(const char* pName, unsigned int* puiTid, int iPriority, + int iStacksize, unsigned int uiMode, void* pvEntryPt, int iArg1, int iArg2, + int iArg3, int iArg4, void* pvArg5); + +/* stop a running thread (called by "killer") */ +int OsaTaskDelete(unsigned int uiTid); + +/* cleanup thread environment (called by thread upon receiving termination signal) */ +void OsaExitKthread(void* pvArg); + +/* setup thread environment (called by new thread) */ +void OsaInitKthread(void* pvArg); + +int OsaTaskGetId(void); + +/** + * @brief Create a semaphore object. + * @remarks the semaphore value shall be incremented more than initial value. + * @param bName [in] semaphore name, for debugging. + * @param iCount [in] initial semaphore value + * @param iAttribute [in] not used now implementation. + * @param puiSmid [out] semaphore object ID. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemCreate(const char bName[10], int iCount, int iAttribute, + unsigned int* puiSmid); // COMMON_071008_1 + +/** + * @brief Lock a semaphore. + * @remarks perform a semaphore lock operation. + * @param uiSmid [in] semaphore object ID created by OsaSemCreate. + * @param iFlags [in] [OSAL_SEM_NOWAIT | OSAL_SEM_WAIT] + - OSAL_SEM_NOWAIT : lock the semaphore only if the semaphore value is + currently not locked. otherwise, return OSAL_ERROR. + - OSAL_SEM_WAIT : lock the semaphore. If the semaphore values is + currently locked, the calling thread shall be blocked. + In linux kernel mode, iFlags is not used, always wait infinitely. + * @param iTimeout [in] timeout value in _microsecond_. + Only affected when iFlags is OSAL_SEM_WAIT. + - 0 : wait infinitely. + - positive value : wait will be terminated when expires and return OSAL_ERR_TIMEOUT. + - negative value : error. + * @retval [OSAL_OK | OSAL_ERROR | OSAL_ERR_TIMEOUT] + */ +int OsaSemGet(unsigned int uiSmid, int iFlags, int iTimeout); + +/** + * @brief Unlock a semaphore + * @remarks If the semaphore value is positive currently, then no threads were + blocked by semaphore and simply semaphore value is incremented. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemRelease(unsigned int uiSmid); + +/** + * @brief Destroy a semaphore object. + * @remarks It is unsafe if any thread is currently blocked by the semaphore. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemDelete(unsigned int uiSmid); + +/** + * @brief Get the current semaphore value + * @remarks If the semaphore is locked, returns zero or negative value. + Only implemented in linux user mode. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemGetval(unsigned int uiSmid); + +/** + * @brief Reset the semaphore to initial state. + * @remarks Set the semaphore value to iCount that given by OsaSemCreate(). + Blocked threads by this semaphore shall not released if initial + value was zero or negative. If initial value was positive, + same number(semaphore value) of threads shall be released. + Only implemented in linux user mode. + * @param uiSmid [id] semaphore object ID created by OsaSemCreate. + * @retval [OSAL_OK | OSAL_ERROR] + */ +int OsaSemReset(unsigned int uiSmid); + +//Mutex +int OsaMutCreate(const char bName[10], int iAttributes, unsigned int* pvArg); + +int OsaMutDelete(unsigned int uiSmid); + +int OsaMutRelease(unsigned int uiSmid); + +int OsaMutGet(unsigned int uiSmid, int iFlags, int iTimeout); + +//Queue +int OsaQueueCreate(const char name[10], unsigned int flags, unsigned int maxnum, + unsigned int maxlen, unsigned int* pqid); +int OsaQueueOpen(unsigned int uiQid); +int OsaQueueClose(unsigned int uiQid); + +int OsaQueueSend(unsigned int uiQid, unsigned int uiFlags, void* pvMsg_buf, + unsigned int uiMsgLen, unsigned int uiPriority, pOsaTime_t ptTimeOut); +int OsaQueueReceive(unsigned int uiQid, unsigned int uiFlags, void* pvMsgBuf, + unsigned int uiBufLen, unsigned int* pMsgLen, pOsaTime_t ptTimeOut); + +int OsaQueueDelete(const char* bName, unsigned int uiQid); + +//Timer +void OsaWait(int mSecs); +unsigned long OsaGetTick(void); +unsigned int OsaCurrentTime(void); +void * OsaMalloc(unsigned int size); +void * OsaFree(void *pbuf); +int OsaTaskDelaymsecs(unsigned int); +int OsaTaskSetPriority(unsigned int uiTid, int iNewpriority); +int OsaTaskGetPriority(unsigned int uiTid, int* piPriority); + +int OsaTaskDelayticks(int iTicks); +int OsaGetTicksPerSecond(void); +void OsaCurrentTimeVal(pOsaTime_t pTimeVal); +void OsaDiffTimeVal(pOsaTime_t pResult, const pOsaTime_t pVal1, + const pOsaTime_t pVal2); + +int OsaIrqSet(unsigned int irq, void (*handler)(void), unsigned int priority, + const char *name, unsigned int isShared); +void OsaIrqFree(unsigned int irq, unsigned int isShared, void (*handler)(void)); +void OsaIrqDisable(unsigned int irq); +void OsaIrqEnable(unsigned int irq); +void OsaIrqPendClear(unsigned int irq); + +#if defined(__KERNEL__) +unsigned int OsaIrqGetCount(unsigned int irq); +void OsaIrqResetCount(void); +#endif + +#if defined(__KERNEL__) +void OsaModule_Open(void); +void OsaModule_Close(void); +int OsaModule_RegisterDev(const char* devname,int iminor_cnt,struct file_operations *fp_op); +int OsaModule_UnRegisterDev(unsigned int devId, const char* devname,int iminor_cnt); +int OsaModule_Remap_page_range(struct vm_area_struct *vma,unsigned int uiaddr); + +/*added by tukho.kim@samsung.com 080714 */ +/*modified by tukho.kim@samsung.com 090818 */ + +/* OSAL_100928_1: Support outer cache handling(flush_all) + * OSAL_DCACHE_XXX are not supported. Do not use. */ +#if 0 +#include + +#define OSAL_DCACHE_FLUSH() __cpuc_flush_kern_all() + +#define OSAL_DCACHE_FLUSH_RANGE(start, end) \ + dmac_flush_range((const void*) start, (const void*) end) + +#define OSAL_DCACHE_INVAL(start, end) \ + dmac_inv_range((const void*) start, (const void*) end) + +#define OSAL_DCACHE_CLEAN(start, end) \ + dmac_clean_range((const void*) start, (const void*) end) + +/*modified by tukho.kim@samsung.com 090818 end*/ +#endif + +/* OSAL_100928_1: Support outer cache handling(flush_all) + * OSAL_DCACHE_XXX are not supported. Do not use. */ +static void __attribute__((unused)) staOsaWarnDeprecatedFunction(const char *func, const char *caller) +{ + printk (KERN_WARNING "[WARNING]\n"); + printk (KERN_WARNING "\tcaller=%s. %s is not support. Do not use!\n", caller, func); +} + +#define OSAL_DCACHE_FLUSH() staOsaWarnDeprecatedFunction("OSAL_DCACHE_FLUSH", __FUNCTION__) +#define OSAL_DCACHE_FLUSH_RANGE(start, end) staOsaWarnDeprecatedFunction("OSAL_DCACHE_FLUSH_RANGE", __FUNCTION__) +#define OSAL_DCACHE_INVAL(start, end) staOsaWarnDeprecatedFunction("OSAL_DCACHE_INVAL", __FUNCTION__) +#define OSAL_DCACHE_CLEAN(start, end) staOsaWarnDeprecatedFunction("OSAL_DCACHE_CLEAN", __FUNCTION__) + +#endif + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerCreate + // Detail Description : This function creates the timer.It initialises the + // timer data and sets the callback function to be called + // upon timer expiry. + // + // Return Data Type : ErrorType. + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerCreate(int* pTimerId, int periodic, int time, + void (*entry)(void* data), void* pvAr); + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerStart + // Detail Description : This function starts the already created timer . + // + // Return Data Type : ErrorType. + / + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerStart(int iTimerId); + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerStop + // Detail Description : This function stops the current running timer . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerStop(int iTimerId); + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerDelete + // Detail Description : This function deletes the current timer . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerDelete(int iTimerId); + +/* + // $$$ + //----------------------------------------------------------------------------- + // Function Name : OsaTimerRestart + // Detail Description : This function restarts the stopped timer . + // + // Return Data Type : ErrorType + // + // Programming Note : None. + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaTimerRestart(int iTimerId); + +/* + // $$$ + //----------------------------------------------------------------------------- + // Shared memory related API + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaShmCreate(const char pName[10], unsigned int u32ShmSegSize, + int* ps32ShmId); +int OsaShmDelete(int s32ShmId); +int OsaShmAttach(int s32ShmId, void** pShmAddr); +int OsaShmDetach(const void *pShmAddr); + +/* + // $$$ + //----------------------------------------------------------------------------- + // System V(or POSIX named) semaphore related API + //------------------------------------------------------------------------------ + // $$$ + */ +int OsaNamedSemCreate(const char pName[10], int iCount, int iAttribute, + unsigned int* puiSemId); +int OsaNamedSemGet(unsigned int uiSemId, int iFlags, int iTimeout); +int OsaNamedSemRelease(unsigned int uiSemId); +int OsaNamedSemDelete(unsigned int uiSemId); +int OsaNamedSemGetval(unsigned int uiSemId); +int OsaNamedSemReset(unsigned int uiSemId); + +#ifdef __cplusplus +} +#endif + +#endif /* OSAL_H */ + diff --git a/simulatordaemon/.cproject b/simulatordaemon/.cproject new file mode 100755 index 0000000..8fc762f --- /dev/null +++ b/simulatordaemon/.cproject @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/simulatordaemon/.gitignore b/simulatordaemon/.gitignore new file mode 100755 index 0000000..3df573f --- /dev/null +++ b/simulatordaemon/.gitignore @@ -0,0 +1 @@ +/Debug/ diff --git a/simulatordaemon/.project b/simulatordaemon/.project new file mode 100755 index 0000000..d1ea21c --- /dev/null +++ b/simulatordaemon/.project @@ -0,0 +1,29 @@ + + + SimulatorDaemon + + + TEECLib + TEEStub + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/simulatordaemon/.settings/language.settings.xml b/simulatordaemon/.settings/language.settings.xml new file mode 100755 index 0000000..53ab1a6 --- /dev/null +++ b/simulatordaemon/.settings/language.settings.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/simulatordaemon/.settings/org.eclipse.cdt.core.prefs b/simulatordaemon/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..71eacce --- /dev/null +++ b/simulatordaemon/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356.743154132/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356.743154132/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356.743154132/PATH/value=C\:/Program Files/Java/jre1.8.0_40/bin/server;C\:/Program Files/Java/jre1.8.0_40/bin;C\:/Program Files/Java/jre1.8.0_40/lib/amd64;C\:\\Program Files (x86)\\Black Duck Software\\protexIP\\bin;C\:\\Program Files\\Common Files\\Microsoft Shared\\Windows Live;C\:\\Program Files (x86)\\Common Files\\Microsoft Shared\\Windows Live;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files (x86)\\QuickTime\\QTSystem\\;C\:\\Program Files (x86)\\Java\\jre7\\bin; C\:\\cygwin64\\bin;C\:\\Program Files\\doxygen\\bin;D\:\\eclipse;C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\Program Files (x86)\\Java\\jre1.8.0_45\\bin;C\:\\Program Files\\eclipse;C\:/Program Files/Java/jre1.8.0_31/bin/server;C\:/Program Files/Java/jre1.8.0_31/bin;C\:/Program Files/Java/jre1.8.0_31/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\csvn\\bin\\;C\:\\csvn\\Python25\\;C\:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files\\Diskeeper Corporation\\ExpressCache\\;C\:\\Program Files (x86)\\Windows Live\\Shared;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x64;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files (x86)\\WinSCP\\;C\:\\Program Files (x86)\\PuTTY;C\:\\Program Files\\Microsoft\\Web Platform Installer\\;C\:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C\:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;C\:\\Program Files (x86)\\doxygen\\bin;C\:\\Program Files (x86)\\sfk168;C\:\\Program Files (x86)\\vlc-2.1.0;C\:\\Python27\\Scripts;C\:\\Program Files (x86)\\GnuWin32\\bin;C\:\\Python27;C\:\\Program Files (x86)\\Subversion\\bin;c\:\\Program Files\\Synergy;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\MinGW\\lib\\gcc\\mingw32\\4.8.1;C\:\\Program Files (x86)\\Windows Kits\\8.1\\Windows Performance Toolkit\\;C\:\\Program Files (x86)\\GitExtensions\\;C\:\\Program Files\\Perforce;c\:\\Program Files\\Java\\jre1.8.0_31\\bin\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;D\:\\samsung-tv-sdk\\ide;${Path};D\:\\samsung-tv-sdk\\tools\\i386-linux-gnueabi-gcc-4.6\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\bin;D\:\\samsung-tv-sdk\\tools\\mingw\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356.743154132/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356.743154132/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x64;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files (x86)\\GitExtensions\\;D\:\\Tizen\\tizen-sdk\\tools;D\:\\Android\\android-sdk\\platform-tools;D\:\\Android\\android-ndk-r10c;C\:\\Program Files\\Perforce;D\:\\eclipse\\eclipse-rcp-luna-SR1-win32-x86_64;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\bin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\mingbin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356/append=true +environment/project/cdt.managedbuild.config.gnu.cross.exe.debug.1895221356/appendContributed=true diff --git a/simulatordaemon/inc/ClientCommands/CommandBase.h b/simulatordaemon/inc/ClientCommands/CommandBase.h new file mode 100755 index 0000000..10e8b37 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandBase.h @@ -0,0 +1,62 @@ +/* + * ===================================================================================== + * + * Filename: CommandBase.h + * + * Description: CommandBase Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDBASE_H_ +#define COMMANDBASE_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_command.h" +#include "tee_client_api.h" +#include "teec_data.h" +#include "teestub_command_data.h" +#include "boost/shared_ptr.hpp" +#include "log.h" +#include "OsaLinuxUser.h" + +class TEEContext; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandBase { +protected: + TEEContext *pTEECtx; +public: + /** + * Command Base for command pattern handling the commands received from + * TEECLib. + * @param TEECtx object associated with command + */ + CommandBase(TEEContext *TEECtx) : + pTEECtx(TEECtx) { + + } + /** + * Command Base Execute for commands received from TEECLib. + * @param none + */ + virtual void execute() = 0; + ~CommandBase() { + } +}; + +typedef boost::shared_ptr CommandBasePtr; + +#endif /* COMMANDBASE_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandCloseSession.h b/simulatordaemon/inc/ClientCommands/CommandCloseSession.h new file mode 100755 index 0000000..61f40bb --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandCloseSession.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: CommandCloseSession.h + * + * Description: CommandCloseSession Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDCLOSESESSION_H_ +#define COMMANDCLOSESESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandCloseSession: + public CommandBase { +public: + CloseSessionData data; + CommandCloseSession(CloseSessionData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandCloseSession(); +}; + +#endif /* COMMANDCLOSESESSION_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandCloseTASession.h b/simulatordaemon/inc/ClientCommands/CommandCloseTASession.h new file mode 100755 index 0000000..031b5cb --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandCloseTASession.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: CommandCloseTASession.h + * + * Description: CommandCloseTASession Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDCLOSETASESSION_H_ +#define COMMANDCLOSETASESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandCloseTASession: + public CommandBase { +public: + IntTACloseSessionData data; + CommandCloseTASession(IntTACloseSessionData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandCloseTASession(); +}; + +#endif /* COMMANDCLOSETASESSION_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandFinContext.h b/simulatordaemon/inc/ClientCommands/CommandFinContext.h new file mode 100755 index 0000000..820c650 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandFinContext.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: CommandFinContext.h + * + * Description: CommandFinContext Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDFINCONTEXT_H_ +#define COMMANDFINCONTEXT_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandFinContext: + public CommandBase { +public: + FinalizeContextData data; + CommandFinContext(FinalizeContextData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandFinContext(); +}; + +#endif /* COMMANDFINCONTEXT_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandInitContext.h b/simulatordaemon/inc/ClientCommands/CommandInitContext.h new file mode 100755 index 0000000..f3f536c --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandInitContext.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: CommandInitContext.h + * + * Description: CommandInitContext Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDINITCONTEXT_H_ +#define COMMANDINITCONTEXT_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandInitContext: + public CommandBase { +public: + InitContextData data; + CommandInitContext(InitContextData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandInitContext(); +}; + +#endif /* COMMANDINITCONTEXT_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandInvokeCommand.h b/simulatordaemon/inc/ClientCommands/CommandInvokeCommand.h new file mode 100755 index 0000000..efb0f3b --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandInvokeCommand.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: CommandInvokeCommand.h + * + * Description: CommandInvokeCommand Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDINVOKECOMMAND_H_ +#define COMMANDINVOKECOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandInvokeCommand: + public CommandBase { +public: + InvokeCommandData data; + CommandInvokeCommand(InvokeCommandData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandInvokeCommand(); + +}; + +#endif /* COMMANDINVOKECOMMAND_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandInvokeTACommand.h b/simulatordaemon/inc/ClientCommands/CommandInvokeTACommand.h new file mode 100755 index 0000000..6eac1c0 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandInvokeTACommand.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: CommandInvokeTACommand.h + * + * Description: CommandInvokeTACommand Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDINVOKETACOMMAND_H_ +#define COMMANDINVOKETACOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandInvokeTACommand: + public CommandBase { +public: + IntTAInvokeCommandData data; + CommandInvokeTACommand(IntTAInvokeCommandData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandInvokeTACommand(); + +}; + +#endif /* COMMANDINVOKETACOMMAND_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandOpenSession.h b/simulatordaemon/inc/ClientCommands/CommandOpenSession.h new file mode 100755 index 0000000..b17e979 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandOpenSession.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: CommandOpenSession.h + * + * Description: CommandOpenSession Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDOPENSESSION_H_ +#define COMMANDOPENSESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandOpenSession: + public CommandBase { +public: + OpenSessionData data; + CommandOpenSession(OpenSessionData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandOpenSession(); +}; + +#endif /* COMMANDOPENSESSION_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandOpenTASession.h b/simulatordaemon/inc/ClientCommands/CommandOpenTASession.h new file mode 100755 index 0000000..e193cd7 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandOpenTASession.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: CommandOpenTASession.h + * + * Description: CommandOpenTASession Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDOPENTASESSION_H_ +#define COMMANDOPENTASESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandOpenTASession: + public CommandBase { +public: + IntTAOpenSessionData data; + CommandOpenTASession(IntTAOpenSessionData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandOpenTASession(); +}; + +#endif /* COMMANDOPENTASESSION_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandPanic.h b/simulatordaemon/inc/ClientCommands/CommandPanic.h new file mode 100755 index 0000000..e979e60 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandPanic.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: CommandPanic.h + * + * Description: CommandPanic Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDPANIC_H_ +#define COMMANDPANIC_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandPanic: + public CommandBase { +public: + IntTAPanicData data; + CommandPanic(IntTAPanicData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandPanic(); + +}; + +#endif /* COMMANDPANIC_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandRegSharedMem.h b/simulatordaemon/inc/ClientCommands/CommandRegSharedMem.h new file mode 100755 index 0000000..d1da1f5 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandRegSharedMem.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: CommandRegSharedMem.h + * + * Description: CommandRegSharedMem Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDREGSHAREDMEM_H_ +#define COMMANDREGSHAREDMEM_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandRegSharedMem: + public CommandBase { +public: + RegSharedMemData data; + CommandRegSharedMem(RegSharedMemData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandRegSharedMem(); + +}; + +#endif /* COMMANDREGSHAREDMEM_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandRelSharedMem.h b/simulatordaemon/inc/ClientCommands/CommandRelSharedMem.h new file mode 100755 index 0000000..6f34322 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandRelSharedMem.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: CommandRelSharedMem.h + * + * Description: CommandRelSharedMem Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDRELSHAREDMEM_H_ +#define COMMANDRELSHAREDMEM_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandRelSharedMem: + public CommandBase { +public: + RelSharedMemData data; + CommandRelSharedMem(RelSharedMemData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandRelSharedMem(); + +}; + +#endif /* COMMANDRELSHAREDMEM_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/CommandReqCancellation.h b/simulatordaemon/inc/ClientCommands/CommandReqCancellation.h new file mode 100755 index 0000000..fe69843 --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/CommandReqCancellation.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: CommandReqCancellation.h + * + * Description: CommandReqCancellation Header file + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef COMMANDREQCANCELLATION_H_ +#define COMMANDREQCANCELLATION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "CommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class CommandReqCancellation: + public CommandBase { +public: + ReqCancellationData data; + CommandReqCancellation(ReqCancellationData data, TEEContext *TEECtx); + void execute(); + virtual ~CommandReqCancellation(); + +}; + +#endif /* COMMANDREQCANCELLATION_H_ */ diff --git a/simulatordaemon/inc/ClientCommands/MakeCommand.h b/simulatordaemon/inc/ClientCommands/MakeCommand.h new file mode 100755 index 0000000..ca653bf --- /dev/null +++ b/simulatordaemon/inc/ClientCommands/MakeCommand.h @@ -0,0 +1,52 @@ +/* + * ===================================================================================== + * + * Filename: MakeCommand.h + * + * Description: MakeCommand Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef MAKECOMMAND_H_ +#define MAKECOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include "CommandCloseSession.h" +#include "CommandCloseTASession.h" +#include "CommandInitContext.h" +#include "CommandFinContext.h" +#include "CommandInvokeCommand.h" +#include "CommandInvokeTACommand.h" +#include "CommandOpenSession.h" +#include "CommandOpenTASession.h" +#include "CommandRegSharedMem.h" +#include "CommandRelSharedMem.h" +#include "CommandReqCancellation.h" +#include "CommandPanic.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class MakeCommand { +private: + MakeCommand(); +public: + static CommandBasePtr getCommand(TEE_CMD command, void* data, + TEEContext *TEECtx); + static uint32_t getDataSize(TEE_CMD command); + virtual ~MakeCommand(); +}; + +#endif /* MAKECOMMAND_H_ */ diff --git a/simulatordaemon/inc/ConnectionSession.h b/simulatordaemon/inc/ConnectionSession.h new file mode 100755 index 0000000..53e02c3 --- /dev/null +++ b/simulatordaemon/inc/ConnectionSession.h @@ -0,0 +1,87 @@ +/* + * ===================================================================================== + * + * Filename: ConnectionSession.h + * + * Description: Connection handler for Simulator Daemon server + * + * Version: 1.0 + * Created: 16 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_CONNECTIONSESSION_H) +#define _CONNECTIONSESSION_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include "tee_client_api.h" +#include "ioService.h" +#include "ClientCommands/MakeCommand.h" +#include "TEEContext.h" +#include "IConnectionSession.h" + +using namespace std; + +// COMPILE TIME CHECK TO SEE IF UNIX DOMAIN SOCKETS ARE AVAILABLE ON SYSTEM +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +using boost::asio::local::stream_protocol; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ConnectionSession: public boost::enable_shared_from_this, public IConnectionSession +{ +public: + pthread_mutex_t connLock; + typedef boost::shared_ptr session_ptr; + static session_ptr create(boost::asio::io_service& io_service) + { + return session_ptr(new ConnectionSession(io_service)); + } + ConnectionSession(boost::asio::io_service& io_service): + clientSocket(io_service) + { + pthread_mutex_init(&connLock, NULL); + currentState = CMD_READ; + TEECtx = NULL; + command = INVALID; + } + stream_protocol::socket& socket() + { + return clientSocket; + } + void start(); + TEEC_Result write(TEE_CMD command, char* data, size_t size); + ~ConnectionSession(); +private: + TEEContext *TEECtx; + void handleRead(const boost::system::error_code& error, + size_t bytes_transferred); + // The socket used to communicate with the client. + stream_protocol::socket clientSocket; + // Buffer used to store data received from the client. + boost::array clientData; + states currentState; + vector commandData; + TEE_CMD command; +}; + +#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +# error Unix domain/local sockets not available on this platform. +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +#endif /* _CONNECTIONSESSION_H */ + diff --git a/simulatordaemon/inc/IConnectionSession.h b/simulatordaemon/inc/IConnectionSession.h new file mode 100644 index 0000000..046a69b --- /dev/null +++ b/simulatordaemon/inc/IConnectionSession.h @@ -0,0 +1,37 @@ +/* + * ===================================================================================== + * + * Filename: IConnectionSession.h + * + * Description: Interface for Connection handler for Simulator Daemon server + * + * Version: 1.0 + * Created: 27 August 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_ICONNECTIONSESSION_H) +#define _ICONNECTIONSESSION_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_command.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class IConnectionSession { +public: + virtual TEEC_Result write(TEE_CMD command, char* data, size_t size) = 0; + virtual ~IConnectionSession() {} +}; + +#endif /* _ICONNECTIONSESSION_H */ + diff --git a/simulatordaemon/inc/ISession.h b/simulatordaemon/inc/ISession.h new file mode 100644 index 0000000..766c719 --- /dev/null +++ b/simulatordaemon/inc/ISession.h @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * Filename: ISession.h + * + * Description: Interface class for Session Header file + * + * Version: 1.0 + * Created: 25 August 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_ISESSION_H) +#define _ISESSION_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include "tee_command.h" +#include "teestub_command_data.h" +#include "ITAInstance.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ + +class ISession { +public: + virtual TEEC_Result createSession(OpenSessionData data) = 0; + virtual TEEC_Result handleCommand(InvokeCommandData data) = 0; + virtual TEEC_Result finalize(uint32_t contextID) = 0; + virtual void handleCancel(ReqCancellationData data) = 0; + virtual bool checkInternal() = 0; + virtual uint32_t getContextID() = 0; + virtual uint32_t getSessionID() = 0; + virtual TAInstancePtr getTAInstance() = 0; + virtual TEEC_Result writeResponse(TEE_CMD command, char* data, size_t size) = 0; + virtual void detachFromContext() = 0; + virtual ~ISession() {} +}; + +#endif //_ISESSION_H diff --git a/simulatordaemon/inc/ITAInstance.h b/simulatordaemon/inc/ITAInstance.h new file mode 100644 index 0000000..f797c6c --- /dev/null +++ b/simulatordaemon/inc/ITAInstance.h @@ -0,0 +1,81 @@ +/* + * ===================================================================================== + * + * Filename: ITAInstance.h + * + * Description: Interface for TAInstance Header file + * + * Version: 1.0 + * Created: 26 August 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_ITAINSTANCE_H) +#define _ITAINSTANCE_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include "teec_data.h" +#include "tee_sim_command.h" + +using namespace std; + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define RETRY_COUNT 10000000 + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +/* In order to handle TA crash situations, a map is created containing all + * the pending commands for the TA instance. Union cmdData is the value type + * for storing the data to be sent in response + */ +union cmdData { + OpenTASessionData osdata; + InvokeTACommandData icdata; + RequestTACancelData rcdata; + CloseTASessionData csdata; +}; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ + +class ISession; + +class ITAInstance { +public: + virtual TEEC_Result sendRequestToTA(SIM_COMMAND cmd, void* data, uint32_t size) = 0; + virtual void receiveResponseFromTA() = 0; + virtual TEEC_Result receiveCreateResponse() = 0; + virtual TEEC_Result connecttoTA(std::stringstream& str) = 0; + virtual bool checkKeepAlive() = 0; + virtual bool getCreated() = 0; + virtual void setCreated(bool value) = 0; + virtual pid_t getPID() = 0; + virtual void takeSessionMapLock() = 0; + virtual void releaseSessionMapLock() = 0; + virtual void eraseSessionMap(uint32_t sessID) = 0; + virtual uint32_t getSessionMapSize() = 0; + virtual void insertSessionMap(ISession* session) = 0; + virtual void eraseCommand(SIM_COMMAND cmd, uint32_t sessID) = 0; + virtual void insertCommand(SIM_COMMAND cmd, cmdData data) = 0; + virtual void killTA() = 0; + virtual void cleanup() = 0; + virtual ~ITAInstance() {} +}; + +typedef boost::shared_ptr TAInstancePtr; + +#endif //_ITAINSTANCE_H diff --git a/simulatordaemon/inc/ResponseCommands/ResCommandBase.h b/simulatordaemon/inc/ResponseCommands/ResCommandBase.h new file mode 100755 index 0000000..b19b71f --- /dev/null +++ b/simulatordaemon/inc/ResponseCommands/ResCommandBase.h @@ -0,0 +1,56 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandBase.h + * + * Description: ResCommandBase Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef RESCOMMANDBASE_H_ +#define RESCOMMANDBASE_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include "tee_command.h" +#include "tee_client_api.h" +#include "teec_data.h" +#include "tee_sim_command.h" +#include "teestub_command_data.h" +#include "ISession.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ResCommandBase { +protected: + std::map *pSessionMap; +public: + /** + * Command Base for command pattern handling the responses received from TEEStub. + * @param SessionMap to find the session associated with command + */ + ResCommandBase(std::map *sessionMap) : + pSessionMap(sessionMap) { + } + virtual void execute() = 0; + ~ResCommandBase() { + } +}; + +typedef boost::shared_ptr ResCommandBasePtr; + +#endif /* RESCOMMANDBASE_H_ */ diff --git a/simulatordaemon/inc/ResponseCommands/ResCommandCloseSession.h b/simulatordaemon/inc/ResponseCommands/ResCommandCloseSession.h new file mode 100755 index 0000000..4642b9b --- /dev/null +++ b/simulatordaemon/inc/ResponseCommands/ResCommandCloseSession.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandCloseSession.h + * + * Description: ResCommandCloseSession Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef RESCOMMANDCLOSESESSION_H_ +#define RESCOMMANDCLOSESESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResCommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ResCommandCloseSession: + public ResCommandBase { +public: + CloseTASessionData *data; + ResCommandCloseSession(CloseTASessionData *data, + std::map *sessionMap); + void execute(); + virtual ~ResCommandCloseSession(); +}; + +#endif /* RESCOMMANDCLOSESESSION_H_ */ diff --git a/simulatordaemon/inc/ResponseCommands/ResCommandInvokeCommand.h b/simulatordaemon/inc/ResponseCommands/ResCommandInvokeCommand.h new file mode 100755 index 0000000..18c8714 --- /dev/null +++ b/simulatordaemon/inc/ResponseCommands/ResCommandInvokeCommand.h @@ -0,0 +1,40 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandInvokeCommand.h + * + * Description: ResCommandInvokeCommand Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef RESCOMMANDINVOKECOMMAND_H_ +#define RESCOMMANDINVOKECOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResCommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ResCommandInvokeCommand: + public ResCommandBase { +public: + InvokeTACommandData *data; + ResCommandInvokeCommand(InvokeTACommandData *data, + std::map *sessionMap); + void execute(); + virtual ~ResCommandInvokeCommand(); + +}; + +#endif /* RESCOMMANDINVOKECOMMAND_H_ */ diff --git a/simulatordaemon/inc/ResponseCommands/ResCommandOpenSession.h b/simulatordaemon/inc/ResponseCommands/ResCommandOpenSession.h new file mode 100755 index 0000000..15de38b --- /dev/null +++ b/simulatordaemon/inc/ResponseCommands/ResCommandOpenSession.h @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandOpenSession.h + * + * Description: ResCommandOpenSession Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#ifndef RESCOMMANDOPENSESSION_H_ +#define RESCOMMANDOPENSESSION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResCommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ResCommandOpenSession: + public ResCommandBase { +public: + OpenTASessionData *data; + ResCommandOpenSession(OpenTASessionData *data, + std::map *sessionMap); + void execute(); + virtual ~ResCommandOpenSession(); +}; + +#endif /* RESCOMMANDOPENSESSION_H_ */ diff --git a/simulatordaemon/inc/ResponseCommands/ResCommandReqCancellation.h b/simulatordaemon/inc/ResponseCommands/ResCommandReqCancellation.h new file mode 100755 index 0000000..fa42c04 --- /dev/null +++ b/simulatordaemon/inc/ResponseCommands/ResCommandReqCancellation.h @@ -0,0 +1,41 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandReqCancellation.h + * + * Description: ResCommandReqCancellation Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef RESCOMMANDREQCANCELLATION_H_ +#define RESCOMMANDREQCANCELLATION_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResCommandBase.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ResCommandReqCancellation: + public ResCommandBase { +public: + ReqCancellationData *data; + ResCommandReqCancellation(ReqCancellationData *data, + std::map *sessionMap); + void execute(); + virtual ~ResCommandReqCancellation(); + +}; + +#endif /* RESCOMMANDREQCANCELLATION_H_ */ diff --git a/simulatordaemon/inc/ResponseCommands/ResMakeCommand.h b/simulatordaemon/inc/ResponseCommands/ResMakeCommand.h new file mode 100755 index 0000000..b6b28e3 --- /dev/null +++ b/simulatordaemon/inc/ResponseCommands/ResMakeCommand.h @@ -0,0 +1,52 @@ +/* + * ===================================================================================== + * + * Filename: ResMakeCommand.h + * + * Description: ResMakeCommand Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef RESMAKECOMMAND_H_ +#define RESMAKECOMMAND_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include "ResCommandCloseSession.h" +#include "ResCommandInvokeCommand.h" +#include "ResCommandOpenSession.h" +#include "ResCommandReqCancellation.h" +#include "tee_command.h" +#include "tee_sim_command.h" +#include "teestub_command_data.h" +#include "ISession.h" +#include "log.h" + +using namespace std; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ResMakeCommand { +private: + ResMakeCommand(); +public: + static ResCommandBasePtr getCommand(SIM_COMMAND command, void* data, + std::map *sessionMap); + static uint32_t getDataSize(SIM_COMMAND command); + virtual ~ResMakeCommand(); +}; + +#endif /* RESMAKECOMMAND_H_ */ diff --git a/simulatordaemon/inc/Session.h b/simulatordaemon/inc/Session.h new file mode 100755 index 0000000..8569059 --- /dev/null +++ b/simulatordaemon/inc/Session.h @@ -0,0 +1,58 @@ +/* + * ===================================================================================== + * + * Filename: Session.h + * + * Description: Session Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_SESSION_H) +#define _SESSION_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include "ISession.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ + +class TEEContext; + +class Session : public ISession { +private: + // Session ID assigned to the Session + uint32_t mSessionID; + // Context associated with the Session + TEEContext* mContext; + // TA instance associated with the Session + TAInstancePtr mTAInstance; +public: + Session(TEEContext* TEECtx); + TEEC_Result createSession(OpenSessionData data); + TEEC_Result handleCommand(InvokeCommandData data); + TEEC_Result finalize(uint32_t contextID); + void handleCancel(ReqCancellationData data); + bool checkInternal(); + uint32_t getContextID(); + uint32_t getSessionID(); + TAInstancePtr getTAInstance(); + TEEC_Result writeResponse(TEE_CMD command, char* data, size_t size); + void detachFromContext(); + ~Session(); +}; + +#endif //_SESSION_H diff --git a/simulatordaemon/inc/SimulatorDaemonServer.h b/simulatordaemon/inc/SimulatorDaemonServer.h new file mode 100755 index 0000000..b0a8ec5 --- /dev/null +++ b/simulatordaemon/inc/SimulatorDaemonServer.h @@ -0,0 +1,41 @@ +/* + * ===================================================================================== + * + * Filename: SimulatorDaemonServer.h + * + * Description: SimulatorDaemonServer Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#if !defined(_SIMULATORDAEMONSERVER_H) +#define _SIMULATORDAEMONSERVER_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ConnectionSession.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class SimulatorDaemonServer { +public: + SimulatorDaemonServer(boost::asio::io_service& io_service, + const std::string& file); +private: + void startAccept(void); + void handleAccept(ConnectionSession::session_ptr new_session, + const boost::system::error_code& error); + boost::asio::io_service& mem_io_service; + stream_protocol::acceptor acceptor; +}; + +#endif //_SIMULATORDAEMONSERVER_H diff --git a/simulatordaemon/inc/TAFactory.h b/simulatordaemon/inc/TAFactory.h new file mode 100755 index 0000000..e3916c3 --- /dev/null +++ b/simulatordaemon/inc/TAFactory.h @@ -0,0 +1,59 @@ +/* + * ===================================================================================== + * + * Filename: TAFactory.h + * + * Description: TAFactory Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_TAFACTORY_H) +#define _TAFACTORY_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include "ISession.h" +#include "TAInstance.h" +#include "TABinaryManager.h" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TAFactory { +public: + pthread_rwlock_t mTAInstanceMapLock; + multimap mTAInstanceMap; + static TAFactory* getInstance(); + TAInstancePtr getTAInstance(TEEC_UUID TAUUID, ISession* session); +private: + static TAFactory *instance; + // instLock for TA Instance ID + pthread_rwlock_t instIDLock; + uint32_t InstID; + TAFactory(); + bool checkIfTARunning(string TAUUID); + TAInstancePtr createUninitalizedTAInstance(string TAUUID, ISession* session); + bool launchTA(string TAUUID, std::stringstream& str, bool debug, pid_t& pid); + static void* waitForChild(void *pid); + void cleanupTAInstance(pid_t PID); + ~TAFactory(); +}; + +#endif //_TAFACTORY_H diff --git a/simulatordaemon/inc/TAInstance.h b/simulatordaemon/inc/TAInstance.h new file mode 100755 index 0000000..ebdf60f --- /dev/null +++ b/simulatordaemon/inc/TAInstance.h @@ -0,0 +1,107 @@ +/* + * ===================================================================================== + * + * Filename: TAInstance.h + * + * Description: TAInstance Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_TAINSTANCE_H) +#define _TAINSTANCE_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ITAInstance.h" +#include "ioService.h" +#include "tee_client_api.h" + +using namespace std; + +// COMPILE TIME CHECK TO SEE IF UNIX DOMAIN SOCKETS ARE AVAILABLE ON SYSTEM +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +using boost::asio::local::stream_protocol; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TAInstance: public boost::enable_shared_from_this, public ITAInstance { +public: + TAInstance(uint32_t pid, bool alive, bool debug, uint32_t InstID, boost::asio::io_service& client_io_service); + TEEC_Result sendRequestToTA(SIM_COMMAND cmd, void* data, uint32_t size); + void receiveResponseFromTA(); + TEEC_Result receiveCreateResponse(); + TEEC_Result connecttoTA(std::stringstream& str); + bool checkKeepAlive(); + bool getCreated(); + void setCreated(bool value); + pid_t getPID(); + void takeSessionMapLock(); + void releaseSessionMapLock(); + void eraseSessionMap(uint32_t sessID); + uint32_t getSessionMapSize(); + void insertSessionMap(ISession* session); + void eraseCommand(SIM_COMMAND cmd, uint32_t sessID); + void insertCommand(SIM_COMMAND cmd, cmdData data); + void killTA(); + void cleanup(); + ~TAInstance(); +private: + // pthread lock for Session Map + pthread_rwlock_t mSessionMapLock; + // pthread lock for Command Map + pthread_rwlock_t mCommandMapLock; + // Member variable to check if the instance is reused or being newly created + bool isCreated; + // Member variable to check if the TA is launched in debug or release mode + bool isDebug; + /* Member variable to check if the instance has to be deleted or not if no + * session is associated with it + */ + bool isKeepAlive; + // Member variable to store the PID of the launched TA + pid_t mPID; + // Instance ID assigned to the TA instance + uint32_t mTAInstanceID; + // Map containing the Sessions associated with the TA instance + map mSessionMap; + /* Map containing all the pending commands (commands sent to TA and waiting + * for response) + */ + multimap mCommandMap; + pthread_mutex_t sendLock; + stream_protocol::socket mTAConnectionSocket; + boost::array readData; + vector commandData; + SIM_COMMAND command; + states currentState; + int32_t setSocketOpt(struct timeval timeout); + void handleRead(const boost::system::error_code& error, + size_t bytes_transferred); + void closeConnectionToTA(); +}; + + +#else // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +# error Unix domain/local sockets not available on this platform. +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + +#endif //_TAINSTANCE_H diff --git a/simulatordaemon/inc/TEEContext.h b/simulatordaemon/inc/TEEContext.h new file mode 100755 index 0000000..ac0669f --- /dev/null +++ b/simulatordaemon/inc/TEEContext.h @@ -0,0 +1,75 @@ +/* + * ===================================================================================== + * + * Filename: TEEContext.h + * + * Description: TEEContext Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_TEECONTEXT_H) +#define _TEECONTEXT_H + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include "log.h" +#include "Session.h" +#include "tee_command.h" +#include "IConnectionSession.h" + +using namespace std; +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define TEENAME "Simulator" + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ + +class TEEContext { +private: + pthread_rwlock_t mShmListLock; + list mShmList; +public: + pthread_rwlock_t mSessionMapLock; + map mSessionMap; + // Connection session instance associated with the TEEContext instance + IConnectionSession* mConnSess; + // ContextID assigned to the instance + uint32_t mContextID; + /* For TA internal APIs support, dummy Context is created and for recognizing + * the context as dummy isInternal member variable is used + */ + bool isInternal; + TEEContext(uint32_t contextID, IConnectionSession* connSession); + TEEC_Result initContext(InitContextData* data); + void finContext(FinalizeContextData data); + TEEC_Result openSession(OpenSessionData data); + TEEC_Result closeSession(CloseSessionData data); + TEEC_Result invokeCommand(InvokeCommandData data); + TEEC_Result openTASession(IntTAOpenSessionData data); + void closeTASession(IntTACloseSessionData data); + TEEC_Result invokeTACommand(IntTAInvokeCommandData data); + TEEC_Result registerSharedMemory(RegSharedMemData data); + TEEC_Result releaseSharedMemory(RelSharedMemData data); + void reqCancel(ReqCancellationData data); + ~TEEContext(); +}; + +#endif //_TEECONTEXT_H diff --git a/simulatordaemon/inc/ioService.h b/simulatordaemon/inc/ioService.h new file mode 100755 index 0000000..e539a4e --- /dev/null +++ b/simulatordaemon/inc/ioService.h @@ -0,0 +1,47 @@ +/* + * ===================================================================================== + * + * Filename: ioService.h + * + * Description: ioService Header file + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ + +#include +#include +#include "log.h" +#include "OsaLinuxUser.h" + +#if !defined(_IOSERVICE_H) +#define _IOSERVICE_H +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +typedef enum { + CMD_READ, DATA_READ, +} states; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class ioService { +public: + static boost::asio::io_service& getInstance(); +private: + static boost::asio::io_service io_service; +}; + +#endif //_IOSERVICE_H diff --git a/simulatordaemon/inc/path.h b/simulatordaemon/inc/path.h new file mode 100755 index 0000000..2aac940 --- /dev/null +++ b/simulatordaemon/inc/path.h @@ -0,0 +1,31 @@ +/* + * ===================================================================================== + * + * Filename: path.h + * + * Description: path details + * + * Version: 1.0 + * Created: 29 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#if !defined(_PATH_H) +#define _PATH_H + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ + +// shm path to be created for Shared memory functionality support +#define SHM_PATH "/tmp/shm" +// socket path for connection with Simulator Daemon +#define SIMDAEMON_PATH "/tmp/simdaemon" + +#endif //_PATH_H diff --git a/simulatordaemon/src/ClientCommands/CommandCloseSession.cpp b/simulatordaemon/src/ClientCommands/CommandCloseSession.cpp new file mode 100755 index 0000000..98795bc --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandCloseSession.cpp @@ -0,0 +1,57 @@ +/* + * ===================================================================================== + * + * Filename: CommandCloseSession.cpp + * + * Description: CommandCloseSession class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandCloseSession.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * CloseSession command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandCloseSession::CommandCloseSession(CloseSessionData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * CloseSession command execute. + * @param none + */ +void CommandCloseSession::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->closeSession(data); + if (result != TEEC_SUCCESS) { + //Communication error - CA exited + FinalizeContextData fdata; + fdata.contextID = data.contextID; + pTEECtx->finContext(fdata); + delete pTEECtx; + } +} + +CommandCloseSession::~CommandCloseSession() { + +} diff --git a/simulatordaemon/src/ClientCommands/CommandCloseTASession.cpp b/simulatordaemon/src/ClientCommands/CommandCloseTASession.cpp new file mode 100755 index 0000000..dc0ee4c --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandCloseTASession.cpp @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * Filename: CommandCloseTASession.cpp + * + * Description: CommandCloseTASession class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandCloseTASession.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * CloseTASession command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandCloseTASession::CommandCloseTASession(IntTACloseSessionData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * CloseTASession command execute. + * @param none + */ +void CommandCloseTASession::execute() { + pTEECtx->closeTASession(data); +} + +CommandCloseTASession::~CommandCloseTASession() { + +} diff --git a/simulatordaemon/src/ClientCommands/CommandFinContext.cpp b/simulatordaemon/src/ClientCommands/CommandFinContext.cpp new file mode 100755 index 0000000..5d6a407 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandFinContext.cpp @@ -0,0 +1,48 @@ +/* + * ===================================================================================== + * + * Filename: CommandFinContext.cpp + * + * Description: CommandFinContext class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandFinContext.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * FinalizeContext command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandFinContext::CommandFinContext(FinalizeContextData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * FinalizeContext command execute. + * @param none + */ +void CommandFinContext::execute() { + pTEECtx->finContext(data); +} + +CommandFinContext::~CommandFinContext() { +} diff --git a/simulatordaemon/src/ClientCommands/CommandInitContext.cpp b/simulatordaemon/src/ClientCommands/CommandInitContext.cpp new file mode 100755 index 0000000..2914b96 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandInitContext.cpp @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * Filename: CommandInitContext.cpp + * + * Description: CommandInitContext class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandInitContext.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * InitializeContext command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandInitContext::CommandInitContext(InitContextData data, TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * InitializeContext command execute. + * @param none + */ +void CommandInitContext::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->initContext(&data); + if (result != TEEC_SUCCESS) delete pTEECtx; +} + +CommandInitContext::~CommandInitContext() { +} diff --git a/simulatordaemon/src/ClientCommands/CommandInvokeCommand.cpp b/simulatordaemon/src/ClientCommands/CommandInvokeCommand.cpp new file mode 100755 index 0000000..7d60242 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandInvokeCommand.cpp @@ -0,0 +1,56 @@ +/* + * ===================================================================================== + * + * Filename: CommandInvokeCommand.cpp + * + * Description: CommandInvokeCommand class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandInvokeCommand.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * InvokeCommand command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandInvokeCommand::CommandInvokeCommand(InvokeCommandData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * InvokeCommand command execute. + * @param none + */ +void CommandInvokeCommand::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->invokeCommand(data); + if (result != TEEC_SUCCESS) { + FinalizeContextData fdata; + fdata.contextID = data.contextID; + pTEECtx->finContext(fdata); + delete pTEECtx; + } +} + +CommandInvokeCommand::~CommandInvokeCommand() { + +} diff --git a/simulatordaemon/src/ClientCommands/CommandInvokeTACommand.cpp b/simulatordaemon/src/ClientCommands/CommandInvokeTACommand.cpp new file mode 100755 index 0000000..cd240c8 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandInvokeTACommand.cpp @@ -0,0 +1,53 @@ +/* + * ===================================================================================== + * + * Filename: CommandInvokeTACommand.cpp + * + * Description: CommandInvokeTACommand class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandInvokeTACommand.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * InvokeTACommand command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandInvokeTACommand::CommandInvokeTACommand(IntTAInvokeCommandData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * InvokeCommand command execute. + * @param none + */ +void CommandInvokeTACommand::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->invokeTACommand(data); + if (result != TEEC_SUCCESS) { + delete pTEECtx; + } +} + +CommandInvokeTACommand::~CommandInvokeTACommand() { + +} diff --git a/simulatordaemon/src/ClientCommands/CommandOpenSession.cpp b/simulatordaemon/src/ClientCommands/CommandOpenSession.cpp new file mode 100755 index 0000000..80ebfdc --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandOpenSession.cpp @@ -0,0 +1,54 @@ +/* + * ===================================================================================== + * + * Filename: CommandOpenSession.cpp + * + * Description: CommandOpenSession class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandOpenSession.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * OpenSession command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandOpenSession::CommandOpenSession(OpenSessionData data, TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * OpenSession command execute. + * @param none + */ +CommandOpenSession::~CommandOpenSession() { +} + +void CommandOpenSession::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->openSession(data); + if (result != TEEC_SUCCESS) { + FinalizeContextData fdata; + fdata.contextID = data.contextID; + pTEECtx->finContext(fdata); + delete pTEECtx; + } +} diff --git a/simulatordaemon/src/ClientCommands/CommandOpenTASession.cpp b/simulatordaemon/src/ClientCommands/CommandOpenTASession.cpp new file mode 100755 index 0000000..8e35480 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandOpenTASession.cpp @@ -0,0 +1,53 @@ +/* + * ===================================================================================== + * + * Filename: CommandOpenTASession.cpp + * + * Description: CommandOpenTASession class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandOpenTASession.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * OpenTASession command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandOpenTASession::CommandOpenTASession(IntTAOpenSessionData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * OpenTASession command execute. + * @param none + */ +CommandOpenTASession::~CommandOpenTASession() { + +} + +void CommandOpenTASession::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->openTASession(data); + if (result != TEEC_SUCCESS) { + delete pTEECtx; + } +} diff --git a/simulatordaemon/src/ClientCommands/CommandPanic.cpp b/simulatordaemon/src/ClientCommands/CommandPanic.cpp new file mode 100755 index 0000000..2766f71 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandPanic.cpp @@ -0,0 +1,48 @@ +/* + * ===================================================================================== + * + * Filename: CommandPanic.cpp + * + * Description: CommandPanic class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandPanic.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Panic command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandPanic::CommandPanic(IntTAPanicData data, TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * Panic command execute. + * @param none + */ +void CommandPanic::execute() { + //TODO: Handle TA Panic + return; +} + +CommandPanic::~CommandPanic() { +} diff --git a/simulatordaemon/src/ClientCommands/CommandRegSharedMem.cpp b/simulatordaemon/src/ClientCommands/CommandRegSharedMem.cpp new file mode 100755 index 0000000..f8774ab --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandRegSharedMem.cpp @@ -0,0 +1,56 @@ +/* + * ===================================================================================== + * + * Filename: CommandRegSharedMem.cpp + * + * Description: CommandRegSharedMem class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandRegSharedMem.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * RegisterSharedMemory command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandRegSharedMem::CommandRegSharedMem(RegSharedMemData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * RegisterSharedMemory command execute. + * @param none + */ +void CommandRegSharedMem::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->registerSharedMemory(data); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Register Shared Memory response write to CA FAILED"); + FinalizeContextData fdata; + fdata.contextID = data.contextID; + pTEECtx->finContext(fdata); + delete pTEECtx; + } +} + +CommandRegSharedMem::~CommandRegSharedMem() { +} diff --git a/simulatordaemon/src/ClientCommands/CommandRelSharedMem.cpp b/simulatordaemon/src/ClientCommands/CommandRelSharedMem.cpp new file mode 100755 index 0000000..955f834 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandRelSharedMem.cpp @@ -0,0 +1,56 @@ +/* + * ===================================================================================== + * + * Filename: CommandRelSharedMem.cpp + * + * Description: CommandRelSharedMem class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandRelSharedMem.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * ReleaseSharedMemory command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandRelSharedMem::CommandRelSharedMem(RelSharedMemData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * ReleaseSharedMemory command execute. + * @param none + */ +void CommandRelSharedMem::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + result = pTEECtx->releaseSharedMemory(data); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Release Shared Memory response write to CA FAILED"); + FinalizeContextData fdata; + fdata.contextID = data.contextID; + pTEECtx->finContext(fdata); + delete pTEECtx; + } +} + +CommandRelSharedMem::~CommandRelSharedMem() { +} diff --git a/simulatordaemon/src/ClientCommands/CommandReqCancellation.cpp b/simulatordaemon/src/ClientCommands/CommandReqCancellation.cpp new file mode 100755 index 0000000..afc721c --- /dev/null +++ b/simulatordaemon/src/ClientCommands/CommandReqCancellation.cpp @@ -0,0 +1,48 @@ +/* + * ===================================================================================== + * + * Filename: CommandReqCancellation.cpp + * + * Description: CommandReqCancellation class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/CommandReqCancellation.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * RequestCancellation command handling. + * @param data received from TEECLib + * @param TEECtx object associated with command + */ +CommandReqCancellation::CommandReqCancellation(ReqCancellationData data, + TEEContext *TEECtx) : + CommandBase(TEECtx) { + this->data = data; +} + +/** + * RequestCancellation command execute. + * @param none + */ +void CommandReqCancellation::execute() { + pTEECtx->reqCancel(data); +} + +CommandReqCancellation::~CommandReqCancellation() { +} diff --git a/simulatordaemon/src/ClientCommands/MakeCommand.cpp b/simulatordaemon/src/ClientCommands/MakeCommand.cpp new file mode 100755 index 0000000..4d660a4 --- /dev/null +++ b/simulatordaemon/src/ClientCommands/MakeCommand.cpp @@ -0,0 +1,192 @@ +/* + * ===================================================================================== + * + * Filename: MakeCommand.cpp + * + * Description: MakeCommand class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ClientCommands/MakeCommand.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Creates a command object based on the type of command passed in + * @param command name of command from enum TEE_CMD + * @param data pointer to structure defining the command in TEE_CMD + * @param TEECtx object associated with command + */ +CommandBasePtr MakeCommand::getCommand(TEE_CMD teecmd, void* teedata, + TEEContext *TEECtx) { + + LOGD(SIM_DAEMON, "Entry"); + CommandBasePtr command; + switch (teecmd) { + case INITIALIZE_CONTEXT: { + InitContextData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandInitContext(data, TEECtx)); + break; + } + case FINALIZE_CONTEXT: { + FinalizeContextData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandFinContext(data, TEECtx)); + break; + } + case OPEN_SESSION: { + OpenSessionData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandOpenSession(data, TEECtx)); + break; + } + case INVOKE_COMMAND: { + InvokeCommandData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandInvokeCommand(data, TEECtx)); + break; + } + case CLOSE_SESSION: { + CloseSessionData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandCloseSession(data, TEECtx)); + break; + } + case OPEN_TA_SESSION: { + IntTAOpenSessionData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandOpenTASession(data, TEECtx)); + break; + } + case INVOKE_TA_COMMAND: { + IntTAInvokeCommandData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandInvokeTACommand(data, TEECtx)); + break; + } + case CLOSE_TA_SESSION: { + IntTACloseSessionData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandCloseTASession(data, TEECtx)); + break; + } + case REQUEST_CANCELLATION: { + ReqCancellationData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandReqCancellation(data, TEECtx)); + break; + } + case REGISTER_SHARED_MEMORY: { + RegSharedMemData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandRegSharedMem(data, TEECtx)); + break; + } + case RELEASE_SHARED_MEMORY: { + RelSharedMemData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandRelSharedMem(data, TEECtx)); + break; + } + case PANIC: { + IntTAPanicData data; + data = *(reinterpret_cast(teedata)); + command = CommandBasePtr(new CommandPanic(data, TEECtx)); + break; + } + default: { + command.reset(); + break; + } + } + return command; +} + +MakeCommand::~MakeCommand() { + +} + +/** + * Calculates size of data expected based on command received + * @param command TEE_CMD to be executed on TA + * @return size of data in bytes based on command. + * A return size of -1 means invalid command. For a valid command + * return size will always be positive integer. + * + */ +uint32_t MakeCommand::getDataSize(TEE_CMD command) { + + uint32_t size = -1; + switch (command) { + case INITIALIZE_CONTEXT: + size = sizeof(InitContextData); + LOGD(SIM_DAEMON, "[TEEC] InitContextData Size: %d", size); + break; + case OPEN_SESSION: + size = sizeof(OpenSessionData); + LOGD(SIM_DAEMON, "[TEEC] OpenSessionData Size: %d", size); + break; + case REGISTER_SHARED_MEMORY: + size = sizeof(RegSharedMemData); + LOGD(SIM_DAEMON, "[TEEC] RegSharedMemData Size: %d", size); + break; + case INVOKE_COMMAND: + size = sizeof(InvokeCommandData); + LOGD(SIM_DAEMON, "[TEEC] InvokeCommandData Size: %d", size); + break; + case RELEASE_SHARED_MEMORY: + size = sizeof(RelSharedMemData); + LOGD(SIM_DAEMON, "[TEEC] RelSharedMemData Size: %d", size); + break; + case CLOSE_SESSION: + size = sizeof(CloseSessionData); + LOGD(SIM_DAEMON, "[TEEC] CloseSessionData Size: %d", size); + break; + case FINALIZE_CONTEXT: + size = sizeof(FinalizeContextData); + LOGD(SIM_DAEMON, "[TEEC] FinalizeContextData Size: %d", size); + break; + case REQUEST_CANCELLATION: + size = sizeof(ReqCancellationData); + LOGD(SIM_DAEMON, "[TEEC] ReqCancellationData Size: %d", size); + break; + case OPEN_TA_SESSION: + size = sizeof(IntTAOpenSessionData); + LOGD(SIM_DAEMON, "[TEEC] IntTAOpenSessionData Size: %d", size); + break; + case INVOKE_TA_COMMAND: + size = sizeof(IntTAInvokeCommandData); + LOGD(SIM_DAEMON, "[TEEC] IntTAInvokeCommandData Size: %d", size); + break; + case CLOSE_TA_SESSION: + size = sizeof(IntTACloseSessionData); + LOGD(SIM_DAEMON, "[TEEC] IntTACloseSessionData Size: %d", size); + break; + case CHECK_MEMORY: + // size = sizeof(CheckMemoryData); + LOGD(SIM_DAEMON, "[TEEC] CheckMemoryData Size: %d", size); + break; + case PANIC: + size = sizeof(IntTAPanicData); + LOGD(SIM_DAEMON, "[TEEC] PanicData Size: %d", size); + break; + default: + size = -1; + break; + } + return size; +} diff --git a/simulatordaemon/src/ConnectionSession.cpp b/simulatordaemon/src/ConnectionSession.cpp new file mode 100755 index 0000000..759eab4 --- /dev/null +++ b/simulatordaemon/src/ConnectionSession.cpp @@ -0,0 +1,210 @@ +/* + * ===================================================================================== + * + * Filename: ConnectionSession.cpp + * + * Description: ConnectionSession class + * + * Version: 1.0 + * Created: 16 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ConnectionSession.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +// Lock for Context ID to be assigned to Context +pthread_rwlock_t ctxIDLock = PTHREAD_RWLOCK_INITIALIZER; +// Context ID to be assigned to Context +uint32_t ctxID = 21; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ + +/** + * On starting the server and accepting a connection, read some data from the socket. + * * @param none + */ +void ConnectionSession::start() { + LOGD(SIM_DAEMON, "Entry"); + + // Create a new Context + pthread_rwlock_wrlock(&ctxIDLock); + TEECtx = new TEEContext(ctxID, this); + // Increment the Context ID to be assigned to next Context + ctxID++; + if (ctxID == 0) ctxID++; + pthread_rwlock_unlock(&ctxIDLock); + currentState = CMD_READ; + // read exactly 1 byte to identify the command and execute callback when + // command is received + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(1), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); +} + +/** + * On asynchronously reading from socket, this call back is executed. + * @param error Boost error code and error message object + * @param bytes_transferred Number of bytes read from the socket + */ +void ConnectionSession::handleRead(const boost::system::error_code& error, + size_t bytes_transferred) { + LOGD(SIM_DAEMON, "Entry"); + + if (!error) { + /** + * A simple small state machine to parse command and handle its + * call back to TEECLib interface + * The state machine identifies the command. If valid, finds out how + * many bytes of data to be read further else if invalid, exits the Simulator Daemon. + * + * Later, exact number of identified size of data is read from + * stream and stored. + */ + switch (currentState) { + case CMD_READ: { + // Identify command + command = (TEE_CMD)clientData.at(0); + LOGD(SIM_DAEMON, "Command received: %d", (uint32_t )command); + + // Calculate pending numbers of bytes pending to be read only for commands + int32_t data_size = MakeCommand::getDataSize(command); + + if (data_size > 0) { + currentState = DATA_READ; + // read remaining bytes related to received valid command + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(data_size), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + else if (-1 == data_size) { + // else case is invalid command + // TODO: Identify the correct behavior; what to do when invalid command is received? + LOGE(SIM_DAEMON, "Invalid command received!"); + } else if (0 == data_size) { + + // reset state to read new command + currentState = CMD_READ; + // read command and register callback to read data + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(1), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + break; + } //case + + case DATA_READ: { + // At this pointer data is completely read + // clear the vector for the first time and copy client data received + commandData.clear(); + for (uint32_t i = 0; i < clientData.size(); i++) { + commandData.push_back(clientData.at(i)); + } + string tempData(commandData.begin(), commandData.end()); + + // Call the TEEContext object to handle commands + CommandBasePtr ptr = MakeCommand::getCommand(command, + (void*)tempData.c_str(), TEECtx); + + if (!ptr == false) { + ptr->execute(); + } else { + LOGE(SIM_DAEMON, "Command not found"); + } + + // reset state to read new command + currentState = CMD_READ; + // read command and register callback to read data + boost::asio::async_read(clientSocket, boost::asio::buffer(clientData), + boost::asio::transfer_exactly(1), + boost::bind(&ConnectionSession::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + break; + } //case + } //switch + } else { + LOGE(SIM_DAEMON, "Error in reading from CA"); + LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); + LOGE(SIM_DAEMON, "Response returned with error code %s", + error.category().name()); + // Call the TEEContext object to cleanup + FinalizeContextData data; + data.contextID = 0; + CommandBasePtr ptr = MakeCommand::getCommand(FINALIZE_CONTEXT, + (void*)&data, TEECtx); + if (!ptr == false) { + ptr->execute(); + } else { + LOGE(SIM_DAEMON, "Command not found"); + } + } +} + +/** + * Synchronous write to the socket. + * @param command to be sent to TEECLib + * @param data to be sent to TEECLib + * @param size of data to be sent to TEECLib + */ +TEEC_Result ConnectionSession::write(TEE_CMD cmd, char* data, size_t size) { + LOGD(SIM_DAEMON, "Entry"); + + TEEC_Result result = TEEC_ERROR_COMMUNICATION; + boost::system::error_code error = boost::asio::error::host_not_found; + pthread_mutex_lock (&connLock); + // Send command to TEECLib for CA + boost::asio::write(clientSocket, + boost::asio::buffer((char*)&cmd, sizeof(char)), + boost::asio::transfer_all(), error); + + if ((!error) && (size != 0)) { + // Send command data to TEECLib for CA + boost::asio::write(clientSocket, boost::asio::buffer(data, size), + boost::asio::transfer_all(), error); + if (!error) + result = TEEC_SUCCESS; + else { + LOGE(SIM_DAEMON, "Error in writing Data to CA"); + LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); + LOGE(SIM_DAEMON, "Response returned with error code %s", + error.category().name()); + } + } else { + LOGE(SIM_DAEMON, "Error in writing Command to CA"); + LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); + LOGE(SIM_DAEMON, "Response returned with error code %s", + error.category().name()); + } + pthread_mutex_unlock(&connLock); + return result; +} + +ConnectionSession::~ConnectionSession() { + LOGD(SIM_DAEMON, "Entry"); + // Destory the lock for write (connLock) + pthread_mutex_destroy (&connLock); + // delete Context + delete TEECtx; + TEECtx = NULL; +} diff --git a/simulatordaemon/src/RemoteSystemsTempFiles/.project b/simulatordaemon/src/RemoteSystemsTempFiles/.project new file mode 100755 index 0000000..5447a64 --- /dev/null +++ b/simulatordaemon/src/RemoteSystemsTempFiles/.project @@ -0,0 +1,12 @@ + + + RemoteSystemsTempFiles + + + + + + + org.eclipse.rse.ui.remoteSystemsTempNature + + diff --git a/simulatordaemon/src/ResponseCommands/ResCommandCloseSession.cpp b/simulatordaemon/src/ResponseCommands/ResCommandCloseSession.cpp new file mode 100755 index 0000000..479ac9c --- /dev/null +++ b/simulatordaemon/src/ResponseCommands/ResCommandCloseSession.cpp @@ -0,0 +1,117 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandCloseSession.cpp + * + * Description: ResCommandCloseSession class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResponseCommands/ResCommandCloseSession.h" +#include "ConnectionSession.h" +#include "TAFactory.h" +#include "ITAInstance.h" +#include "ISession.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * CloseSession response command handling. + * @param data received from TEEStub + * @param Session Map to find out the Session object associated with command + */ +ResCommandCloseSession::ResCommandCloseSession(CloseTASessionData *data, + std::map *sessionMap) : + ResCommandBase(sessionMap) { + this->data = data; +} + +/** + * CloseSession response command execute. + * @param none + */ +void ResCommandCloseSession::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + TAFactory *TAFact = TAFactory::getInstance(); + if (NULL == TAFact) { + // This error should not come + LOGE(SIM_DAEMON, "TA Factory instance creation failed. Check logs for further info"); + return; + } + map::iterator it; + it = pSessionMap->find(data->sessionID); + if (it != pSessionMap->end()) { + ISession* session = it->second; + (session->getTAInstance())->takeSessionMapLock(); + pSessionMap->erase(it); + multimap::iterator itTAMap; + pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock); + for (itTAMap = TAFact->mTAInstanceMap.begin(); + itTAMap != TAFact->mTAInstanceMap.end(); ++itTAMap) { + if (itTAMap->second == session->getTAInstance()) { + if (pSessionMap->size() == 0) { + if ((session->getTAInstance())->checkKeepAlive() != true) { + DestroyTAEntryPointData ddata; + memset(&ddata, 0, sizeof(DestroyTAEntryPointData)); + ddata.sessionID = data->sessionID; + result = (session->getTAInstance())->sendRequestToTA(DESTROY, + (void*)&ddata, sizeof(DestroyTAEntryPointData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Destroy sendRequestToTA FAILED"); + (session->getTAInstance())->killTA(); + } + } else break; + } + TAFact->mTAInstanceMap.erase(itTAMap); + break; + } + } + pthread_rwlock_unlock(&TAFact->mTAInstanceMapLock); + session->getTAInstance()->releaseSessionMapLock(); + if (session->getContextID() != 0) { + if (session->checkInternal()) { + IntTACloseSessionData cdata; + memset(&cdata, 0, sizeof(IntTACloseSessionData)); + cdata.session = data->sessionID; + result = session->writeResponse(CLOSE_TA_SESSION, + (char*)&cdata, sizeof(IntTACloseSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Close Session response write to TA FAILED"); + } + } else { + CloseSessionData cdata; + memset(&cdata, 0, sizeof(CloseSessionData)); + cdata.contextID = session->getContextID(); + cdata.sessionID = data->sessionID; + result = session->writeResponse(CLOSE_SESSION, (char*)&cdata, + sizeof(CloseSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Close Session response write to CA FAILED"); + } + } + session->detachFromContext(); + } + session->getTAInstance()->eraseCommand(CLOSESESSION, data->sessionID); + delete session; + } else { + // This error should not come + LOGE(SIM_DAEMON, "SessionID: %d not found in map", data->sessionID); + } +} + +ResCommandCloseSession::~ResCommandCloseSession() { + +} diff --git a/simulatordaemon/src/ResponseCommands/ResCommandInvokeCommand.cpp b/simulatordaemon/src/ResponseCommands/ResCommandInvokeCommand.cpp new file mode 100755 index 0000000..e26e6b4 --- /dev/null +++ b/simulatordaemon/src/ResponseCommands/ResCommandInvokeCommand.cpp @@ -0,0 +1,115 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandInvokeCommand.cpp + * + * Description: ResCommandInvokeCommand class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResponseCommands/ResCommandInvokeCommand.h" +#include "ConnectionSession.h" +#include "ITAInstance.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * InvokeCommand response command handling. + * @param data received from TEEStub + * @param Session Map to find out the Session object associated with command + */ +ResCommandInvokeCommand::ResCommandInvokeCommand(InvokeTACommandData *data, + std::map *sessionMap) : + ResCommandBase(sessionMap) { + this->data = data; +} + +/** + * InvokeCommand response command execute. + * @param none + */ +void ResCommandInvokeCommand::execute() { + TEEC_Result result = TEEC_ERROR_GENERIC; + uint32_t i, type; + map::iterator it; + it = pSessionMap->find(data->sessionID); + if ((it != pSessionMap->end()) && (it->second->getContextID() != 0)) { + if (it->second->checkInternal()) { + IntTAInvokeCommandData idata; + memset(&idata, 0, sizeof(IntTAInvokeCommandData)); + idata.operation.paramTypes = data->op.paramTypes; + for (i = 0; i < 4; i++) { + type = ((data->op.paramTypes) >> (8 * i)) & 0x7f; + if ((type == TEEC_VALUE_INPUT) || (type == TEEC_VALUE_OUTPUT) + || (type == TEEC_VALUE_INOUT)) { + idata.operation.params[i].value.a = data->op.params[i].value.a; + idata.operation.params[i].value.b = data->op.params[i].value.b; + } else if (type == TEEC_NONE) { + // No operation data + } else { + idata.operation.params[i].mem.size = data->op.params[i].memref.size; + idata.operation.params[i].mem.shmKey = data->op.shmID[i]; + } + } + idata.returnValue = data->returnValue; + idata.returnOrigin = data->returnOrigin; + idata.session = data->sessionID; + + idata.commandID = data->commandID; + result = it->second->writeResponse(INVOKE_TA_COMMAND, + (char*)&idata, sizeof(IntTAInvokeCommandData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Invoke Command response write to TA FAILED"); + } + } else { + InvokeCommandData idata; + memset(&idata, 0, sizeof(InvokeCommandData)); + idata.contextID = it->second->getContextID(); + idata.operation.paramTypes = data->op.paramTypes; + for (i = 0; i < 4; i++) { + type = ((data->op.paramTypes) >> (8 * i)) & 0x7f; + if ((type == TEEC_VALUE_INPUT) || (type == TEEC_VALUE_OUTPUT) + || (type == TEEC_VALUE_INOUT)) { + idata.operation.params[i].value.a = data->op.params[i].value.a; + idata.operation.params[i].value.b = data->op.params[i].value.b; + } else if (type == TEEC_NONE) { + // No operation data + } else { + idata.operation.params[i].mem.size = data->op.params[i].memref.size; + idata.operation.params[i].mem.shmKey = data->op.shmID[i]; + } + } + idata.returnValue = data->returnValue; + idata.returnOrigin = data->returnOrigin; + idata.sessionID = data->sessionID; + + idata.commandID = data->commandID; + result = it->second->writeResponse(INVOKE_COMMAND, + (char*)&idata, sizeof(InvokeCommandData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Invoke Command response write to CA FAILED"); + } + } + it->second->getTAInstance()->eraseCommand(INVOKECOMMAND, data->sessionID); + } else { + // This error should not come + LOGE(SIM_DAEMON, "SessionID: %d not found in map", data->sessionID); + } +} + +ResCommandInvokeCommand::~ResCommandInvokeCommand() { + +} diff --git a/simulatordaemon/src/ResponseCommands/ResCommandOpenSession.cpp b/simulatordaemon/src/ResponseCommands/ResCommandOpenSession.cpp new file mode 100755 index 0000000..c1debd6 --- /dev/null +++ b/simulatordaemon/src/ResponseCommands/ResCommandOpenSession.cpp @@ -0,0 +1,112 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandOpenSession.cpp + * + * Description: ResCommandOpenSession class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResponseCommands/ResCommandOpenSession.h" +#include "ConnectionSession.h" +#include "ITAInstance.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * OpenSession response command handling. + * @param data received from TEEStub + * @param Session Map to find out the Session object associated with command + */ +ResCommandOpenSession::ResCommandOpenSession(OpenTASessionData *data, + std::map *sessionMap) : + ResCommandBase(sessionMap) { + this->data = data; +} + +/** + * OpenSession response command execute. + * @param none + */ +void ResCommandOpenSession::execute() { + uint32_t i, type; + TEEC_Result result = TEEC_ERROR_GENERIC; + map::iterator it; + it = pSessionMap->find(data->sessionID); + if ((it != pSessionMap->end()) && (it->second->getContextID() != 0)) { + if (it->second->checkInternal()) { + IntTAOpenSessionData odata; + memset(&odata, 0, sizeof(IntTAOpenSessionData)); + odata.operation.paramTypes = data->op.paramTypes; + for (i = 0; i < 4; i++) { + type = ((data->op.paramTypes) >> (8 * i)) & 0x7f; + if ((type == TEEC_VALUE_INPUT) || (type == TEEC_VALUE_OUTPUT) + || (type == TEEC_VALUE_INOUT)) { + odata.operation.params[i].value.a = data->op.params[i].value.a; + odata.operation.params[i].value.b = data->op.params[i].value.b; + } else if (type == TEEC_NONE) { + // No operation data + } else { + odata.operation.params[i].mem.size = data->op.params[i].memref.size; + odata.operation.params[i].mem.shmKey = data->op.shmID[i]; + } + } + odata.returnValue = data->returnValue; + odata.returnOrigin = data->returnOrigin; + odata.session = data->sessionID; + + result = it->second->writeResponse(OPEN_TA_SESSION, + (char*)&odata, sizeof(IntTAOpenSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Open Session response write to TA FAILED"); + } + } else { + OpenSessionData odata; + memset(&odata, 0, sizeof(OpenSessionData)); + odata.contextID = it->second->getContextID(); + odata.operation.paramTypes = data->op.paramTypes; + for (i = 0; i < 4; i++) { + type = ((data->op.paramTypes) >> (8 * i)) & 0x7f; + if ((type == TEEC_VALUE_INPUT) || (type == TEEC_VALUE_OUTPUT) + || (type == TEEC_VALUE_INOUT)) { + odata.operation.params[i].value.a = data->op.params[i].value.a; + odata.operation.params[i].value.b = data->op.params[i].value.b; + } else if (type == TEEC_NONE) { + // No operation data + } else { + odata.operation.params[i].mem.size = data->op.params[i].memref.size; + odata.operation.params[i].mem.shmKey = data->op.shmID[i]; + } + } + odata.returnValue = data->returnValue; + odata.returnOrigin = data->returnOrigin; + odata.sessionID = data->sessionID; + + result = it->second->writeResponse(OPEN_SESSION, + (char*)&odata, sizeof(OpenSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Open Session response write to CA FAILED"); + } + } + it->second->getTAInstance()->eraseCommand(OPENSESSION, data->sessionID); + } else { + // This error should not come + LOGE(SIM_DAEMON, "SessionID: %d not found in map", data->sessionID); + } +} + +ResCommandOpenSession::~ResCommandOpenSession() { +} diff --git a/simulatordaemon/src/ResponseCommands/ResCommandReqCancellation.cpp b/simulatordaemon/src/ResponseCommands/ResCommandReqCancellation.cpp new file mode 100755 index 0000000..4a22539 --- /dev/null +++ b/simulatordaemon/src/ResponseCommands/ResCommandReqCancellation.cpp @@ -0,0 +1,49 @@ +/* + * ===================================================================================== + * + * Filename: ResCommandReqCancellation.cpp + * + * Description: ResCommandReqCancellation class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResponseCommands/ResCommandReqCancellation.h" +#include "ConnectionSession.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * ReqCancel response command handling. + * @param data received from TEEStub + * @param Session Map to find out the Session object associated with command + */ +ResCommandReqCancellation::ResCommandReqCancellation(ReqCancellationData *data, + std::map *sessionMap) : + ResCommandBase(sessionMap) { + this->data = data; +} + +/** + * ReqCancel response command execute. + * @param none + */ +ResCommandReqCancellation::~ResCommandReqCancellation() { +} + +void ResCommandReqCancellation::execute() { + //Not supported in current design + return; +} diff --git a/simulatordaemon/src/ResponseCommands/ResMakeCommand.cpp b/simulatordaemon/src/ResponseCommands/ResMakeCommand.cpp new file mode 100755 index 0000000..8b90d28 --- /dev/null +++ b/simulatordaemon/src/ResponseCommands/ResMakeCommand.cpp @@ -0,0 +1,116 @@ +/* + * ===================================================================================== + * + * Filename: ResMakeCommand.cpp + * + * Description: ResMakeCommand class + * + * Version: 1.0 + * Created: 23 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ResponseCommands/ResMakeCommand.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Creates a command object based on the type of command passed in + * @param command name of command from enum SIM_COMMAND + * @param data pointer to structure defining the command in SIM_COMMAND + */ +ResCommandBasePtr ResMakeCommand::getCommand(SIM_COMMAND tacmd, void* tadata, + std::map *sessionMap) { + + ResCommandBasePtr command; + switch (tacmd) { + case OPENSESSION: { + OpenTASessionData *data; + data = (reinterpret_cast(tadata)); + command = ResCommandBasePtr(new ResCommandOpenSession(data, sessionMap)); + break; + } + case INVOKECOMMAND: { + InvokeTACommandData *data; + data = (reinterpret_cast(tadata)); + command = ResCommandBasePtr( + new ResCommandInvokeCommand(data, sessionMap)); + break; + } + case CLOSESESSION: { + CloseTASessionData *data; + data = (reinterpret_cast(tadata)); + command = ResCommandBasePtr(new ResCommandCloseSession(data, sessionMap)); + break; + } + case REQCANCEL: { + ReqCancellationData *data; + data = (reinterpret_cast(tadata)); + command = ResCommandBasePtr( + new ResCommandReqCancellation(data, sessionMap)); + break; + } + default: { + command.reset(); + break; + } + } + return command; +} + +ResMakeCommand::~ResMakeCommand() { + +} + +/** + * Calculates size of data expected based on command received + * @param command SIM_COMMAND to be executed + * @return size of data in bytes based on command. + * A return size of -1 means invalid command. For a valid command + * return size will always be positive integer. + * + */ +uint32_t ResMakeCommand::getDataSize(SIM_COMMAND command) { + + uint32_t size = -1; + switch (command) { + case CREATE: + size = sizeof(CreateTAEntryPointData); + LOGD(SIM_DAEMON, "[TA] CreateTAEntryPoint Size: %d", size); + break; + case DESTROY: + size = sizeof(DestroyTAEntryPointData); + LOGD(SIM_DAEMON, "[TA] DestroyTAEntryPoint Size: %d", size); + break; + case OPENSESSION: + size = sizeof(OpenTASessionData); + LOGD(SIM_DAEMON, "[TA] OpenTASessionData Size: %d", size); + break; + case INVOKECOMMAND: + size = sizeof(InvokeTACommandData); + LOGD(SIM_DAEMON, "[TA] InvokeTACommandData Size: %d", size); + break; + case CLOSESESSION: + size = sizeof(CloseTASessionData); + LOGD(SIM_DAEMON, "[TA] CloseTASessionData Size: %d", size); + break; + case REQCANCEL: + size = sizeof(RequestTACancelData); + LOGD(SIM_DAEMON, "[TA] RequestTACancelData Size: %d", size); + break; + default: + size = -1; + break; + } + return size; +} diff --git a/simulatordaemon/src/Session.cpp b/simulatordaemon/src/Session.cpp new file mode 100755 index 0000000..0739089 --- /dev/null +++ b/simulatordaemon/src/Session.cpp @@ -0,0 +1,353 @@ +/* + * ===================================================================================== + * + * Filename: Session.cpp + * + * Description: Session class + * + * Version: 1.0 + * Created: 27 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "Session.h" +#include "TAFactory.h" +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Session constructer. Session is created for each OpenSession call + * @param TEECtx Context instance associated with the session + */ +Session::Session(TEEContext* TEECtx) { + LOGD(SIM_DAEMON, "Entry"); + mContext = TEECtx; + mSessionID = -1; +} + +bool Session::checkInternal() { + return mContext->isInternal; +} + +uint32_t Session::getContextID() { + LOGD(SIM_DAEMON, "Entry"); + if (mContext != NULL) { + LOGD(SIM_DAEMON, "Entry"); + return mContext->mContextID; + } else { + return 0; + } +} + +uint32_t Session::getSessionID() { + return mSessionID; +} + +TAInstancePtr Session::getTAInstance() { + return mTAInstance; +} + +void Session::detachFromContext() { + /* Find the Session instance in the session map */ + map::iterator it; + pthread_rwlock_wrlock(&mContext->mSessionMapLock); + it = mContext->mSessionMap.find(mSessionID); + if (it == mContext->mSessionMap.end()) { + LOGE(SIM_DAEMON, "Session not found"); + pthread_rwlock_unlock(&mContext->mSessionMapLock); + return; + } + mContext->mSessionMap.erase(it); + pthread_rwlock_unlock(&mContext->mSessionMapLock); +} + +TEEC_Result Session::writeResponse(TEE_CMD command, char* data, size_t size) { + return mContext->mConnSess->write(command, data, size); +} +/** + * Session initializer. Called after Session constructor to initialize a + * session + * @param data OpenSessionData type of data for opening a session + */ +TEEC_Result Session::createSession(OpenSessionData data) { + + uint32_t i, type; + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + // Get TA factory instance + TAFactory *TAFact = TAFactory::getInstance(); + // Update member variable mSessionID with the assigned session ID + mSessionID = data.sessionID; + + //Check if the TA is to be launched in Debug mode, Kill alive TA process + TAInstancePtr TAInst; + + TABinaryManager *TABin = TABinaryManager::getInstance(); + if(TABin == NULL) { + LOGE(SIM_DAEMON, "Creating TABinaryManager Instance FAILED - "); + return TEEC_ERROR_GENERIC; + } + string TAUUID = TABin->getUUIDAsString(data.uuid); + string argvPort = TABin->getPort(TAUUID); + + if (argvPort != "") { + pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock); + multimap::iterator itr; + itr = TAFact->mTAInstanceMap.find(TAUUID); + if (itr != TAFact->mTAInstanceMap.end()) { + mTAInstance = itr->second; + LOGD(SIM_DAEMON, "KILL pid = %d", mTAInstance->getPID()); + mTAInstance->killTA(); + TAFact->mTAInstanceMap.erase(itr); + } + pthread_rwlock_unlock(&TAFact->mTAInstanceMapLock); + } + + // Get TA instance from TA Factory and update member variable mTAInstance + pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock); + mTAInstance = TAFact->getTAInstance(data.uuid, this); + pthread_rwlock_unlock(&TAFact->mTAInstanceMapLock); + if (!mTAInstance == true) { // failure + LOGE(SIM_DAEMON, "Creating Trusted Application Instance FAILED - " + "TA not launched/Create FAILED"); + return TEEC_ERROR_BAD_PARAMETERS; + } + + /* Check if TAInstance is newly created or an old instance is being re-used. + * If new instance then wait for CREATE command response from the TA, else + * directly send OpenSession request. + * TaInstance member variable isCreated is used to find if the TAInstance is + * newly created or re-used. + */ + if (mTAInstance->getCreated() == false) { + result = mTAInstance->receiveCreateResponse(); + if (TEEC_SUCCESS != result) { // failure + LOGE(SIM_DAEMON, "Create TA entry point FAILED"); + pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock); + multimap::iterator it; + for (it = TAFact->mTAInstanceMap.begin(); + it != TAFact->mTAInstanceMap.end(); ++it) { + if (it->second == mTAInstance) { + // Kill the TA process + mTAInstance->killTA(); + // Erase the instance from TAFactory's Instance map + TAFact->mTAInstanceMap.erase(it); + break; + } + } + pthread_rwlock_unlock(&TAFact->mTAInstanceMapLock); + return result; + } + + // Set the isCreated flag to true + mTAInstance->setCreated(true); + // Start asynchronous recieve from the TA + mTAInstance->receiveResponseFromTA(); + } + + // Generate OpenTASessionData to be sent to TA + OpenTASessionData tdata; + memset(&tdata, 0, sizeof(OpenTASessionData)); + tdata.sessionID = data.sessionID; + tdata.op.paramTypes = data.operation.paramTypes; + tdata.returnValue = data.returnValue; + tdata.returnOrigin = data.returnOrigin; + for (i = 0; i < 4; i++) { + type = ((data.operation.paramTypes) >> (8 * i)) & 0x7f; + if ((type == TEEC_VALUE_INPUT) || (type == TEEC_VALUE_OUTPUT) + || (type == TEEC_VALUE_INOUT)) { + tdata.op.params[i].value.a = data.operation.params[i].value.a; + tdata.op.params[i].value.b = data.operation.params[i].value.b; + } else if (type == TEEC_NONE) { + // No operation data + } else { + tdata.op.params[i].memref.size = data.operation.params[i].mem.size; + tdata.op.shmID[i] = data.operation.params[i].mem.shmKey; + } + } + // Send OPENSESSION request to TA + result = mTAInstance->sendRequestToTA(OPENSESSION, (void*)&tdata, + sizeof(OpenTASessionData)); + if (result != TEEC_SUCCESS) { // failure + LOGE(SIM_DAEMON, "OpenSession sendRequestToTA FAILED\n"); + } else { // success + cmdData sdata; + sdata.osdata = tdata; + // Add the command in TA Instance's command map + mTAInstance->insertCommand(OPENSESSION, sdata); + } + return result; +} + +/** + * Session command handler. Called for each InvokeCommand request in a session + * @param data InvokeCommandData type of data for invoking a command + */ +TEEC_Result Session::handleCommand(InvokeCommandData data) { + LOGD(SIM_DAEMON, "Entry"); + uint32_t i, type; + TEEC_Result result = TEEC_ERROR_GENERIC; + + // Generate InvokeTACommandData to be sent to TA + InvokeTACommandData idata; + memset(&idata, 0, sizeof(InvokeTACommandData)); + idata.commandID = data.commandID; + idata.returnOrigin = data.returnOrigin; + idata.returnValue = data.returnValue; + idata.sessionID = data.sessionID; + idata.op.operationID = data.operation.OperationID; + idata.op.paramTypes = data.operation.paramTypes; + + for (i = 0; i < 4; i++) { + type = ((data.operation.paramTypes) >> (8 * i)) & 0x7f; + if ((type == TEEC_VALUE_INPUT) || (type == TEEC_VALUE_OUTPUT) + || (type == TEEC_VALUE_INOUT)) { + idata.op.params[i].value.a = data.operation.params[i].value.a; + idata.op.params[i].value.b = data.operation.params[i].value.b; + } else if (type == TEEC_NONE) { + // No operation data + } else { + idata.op.params[i].memref.size = data.operation.params[i].mem.size; + idata.op.shmID[i] = data.operation.params[i].mem.shmKey; + } + } + + // Send INVOKECOMMAND request to TA + result = mTAInstance->sendRequestToTA(INVOKECOMMAND, (void*)&idata, + sizeof(InvokeTACommandData)); + if (result != TEEC_SUCCESS) { // failure + LOGE(SIM_DAEMON, "InvokeCommand sendRequestToTA FAILED"); + } else { // success + cmdData sdata; + sdata.icdata = idata; + // Add the command in TA Instance's command map + mTAInstance->insertCommand(INVOKECOMMAND, sdata); + } + return result; +} + +/** + * Session cancellation handler. Called for each RequestCancellation request + * in a session + * @param data ReqCancellationData type of data for cancelling an operation + */ +void Session::handleCancel(ReqCancellationData data) { + LOGD(SIM_DAEMON, "Entry"); + TEEC_Result result = TEEC_ERROR_GENERIC; + + // Generate RequestTACancelData to be sent to TA + RequestTACancelData rdata; + memset(&rdata, 0, sizeof(RequestTACancelData)); + rdata.returnOrigin = TEEC_ORIGIN_TEE; + rdata.returnValue = TEEC_ERROR_COMMUNICATION; + rdata.sessionID = data.sessionID; + rdata.operationID = data.operationID; + + // Send REQCANCEL request to TA + result = mTAInstance->sendRequestToTA(REQCANCEL, (void*)&rdata, + sizeof(RequestTACancelData)); + if (result != TEEC_SUCCESS) { // failure + LOGE(SIM_DAEMON, "Request Cancellation sendRequestToTA FAILED"); + } else { // success + cmdData sdata; + sdata.rcdata = rdata; + // Add the command in TA Instance's command map + mTAInstance->insertCommand(REQCANCEL, sdata); + } +} + +/** + * Session clean up. Called before Session destructor to clean the session + */ +TEEC_Result Session::finalize(uint32_t contextID) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + // Get TA Factory insatnce + TAFactory *TAFact = TAFactory::getInstance(); + // Generate CloseTASessionData to be sent to TA + CloseTASessionData cdata; + memset(&cdata, 0, sizeof(CloseTASessionData)); + cdata.sessionID = mSessionID; + if (contextID == 0) { + mContext = NULL; + } + // Send CLOSESESSION request to TA + result = mTAInstance->sendRequestToTA(CLOSESESSION, (void*)&cdata, + sizeof(CloseTASessionData)); + if (result != TEEC_SUCCESS) { //failure + LOGE(SIM_DAEMON, "CloseSession sendRequestToTA FAILED"); + + // remove the session from the TA Instance's Session Map + mTAInstance->takeSessionMapLock(); + mTAInstance->eraseSessionMap(mSessionID); + + multimap::iterator itTAMap; + + /* Check if this is the last session associated with the TA Instance. + * If it is the last instance then check for KeepAlive flag. + */ + pthread_rwlock_wrlock(&TAFact->mTAInstanceMapLock); + for (itTAMap = TAFact->mTAInstanceMap.begin(); + itTAMap != TAFact->mTAInstanceMap.end(); ++itTAMap) { + if (itTAMap->second == mTAInstance) { + /* If this is the last session associated with TA then check for + * KeepAlive flag else DESTROY command is anyways not to be sent + */ + if (mTAInstance->getSessionMapSize() == 0) { + /* Check if TAInstance is KeepAlive or not and if this is the last . + * If instance is KeepAlive then do not send DESTROY command else + * send DESTROY command to TA + * TaInstance member variable isKeepAlive is used to find if the + * TAInstance is KeepAlive or not. + */ + if (mTAInstance->checkKeepAlive() != true) { + // Generate DestroyTAEntryPointData to be sent to TA + DestroyTAEntryPointData ddata; + memset(&ddata, 0, sizeof(DestroyTAEntryPointData)); + ddata.sessionID = mSessionID; + + // Send DESTROY command to TA + result = mTAInstance->sendRequestToTA(DESTROY, (void*)&ddata, + sizeof(DestroyTAEntryPointData)); + if (result != TEEC_SUCCESS) { // failure + LOGE(SIM_DAEMON, "Destroy sendRequestToTA FAILED"); + mTAInstance->killTA(); + } + } else break; + } + // Erase TA Instance from TA FActory's Instance map + TAFact->mTAInstanceMap.erase(itTAMap); + break; + } + } + pthread_rwlock_unlock(&TAFact->mTAInstanceMapLock); + mTAInstance->releaseSessionMapLock(); + } else { // success + cmdData sdata; + sdata.csdata = cdata; + // Add the command in TA Instance's command map + mTAInstance->insertCommand(CLOSESESSION, sdata); + } + return result; +} + +/** + * Session destructor. Delete the Session instance + */ +Session::~Session() { + LOGD(SIM_DAEMON, "Entry"); +} diff --git a/simulatordaemon/src/SimulatorDaemon.cpp b/simulatordaemon/src/SimulatorDaemon.cpp new file mode 100755 index 0000000..560721c --- /dev/null +++ b/simulatordaemon/src/SimulatorDaemon.cpp @@ -0,0 +1,85 @@ +/* + * ===================================================================================== + * + * Filename: SimulatorDaemon.cpp + * + * Description: SimulatorDaemon main file + * + * Version: 1.0 + * Created: 16 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "path.h" +#include "SimulatorDaemonServer.h" + +/*----------------------------------------------------------------------------- + * Local functions + *-----------------------------------------------------------------------------*/ +/** + * Create shm file for shared memory implementation (IPC) + */ +void initializeShm() { + LOGD(SIM_DAEMON, "Entry"); + ::unlink(SHM_PATH); + int fd = creat(SHM_PATH, S_IRWXU); + if (-1 == fd) { + LOGE(SIM_DAEMON, "shm file creation failed"); + exit(0); + } + close(fd); +} + +/** + * Starts the Simulator Daemon as server which listens for connection from + * TEECLib + * @param io_service + */ +void startServer(boost::asio::io_service& io_service) { + LOGD(SIM_DAEMON, "Entry"); + try { + io_service.run(); + } catch (std::exception& e) { + LOGE(SIM_DAEMON, "Exception: %s", e.what()); + } +} + +/** + * Stops the Simulator Daemon server + */ +void stopServer(boost::asio::io_service& io_service) { + LOGD(SIM_DAEMON, "Entry"); + io_service.stop(); +} + +/** + * main function for Simulator Daemon + * @return + */ +int main() { + LOGD(SIM_DAEMON, "Entry"); + uint32_t result = 0; + try { + ::unlink(SIMDAEMON_PATH); + //initializeShm(); + SimulatorDaemonServer s(ioService::getInstance(), SIMDAEMON_PATH); + // Once the server is started, it exits only after the + // connection is lost or gracefully disconnected. + startServer(ioService::getInstance()); + syslog(LOG_INFO | LOG_USER, "Daemon stopped"); + } catch (std::exception& e) { + syslog(LOG_ERR | LOG_USER, "Exception: %s", e.what()); + LOGE(SIM_DAEMON, "Exception: %s", e.what()); + } + stopServer(ioService::getInstance()); + return result; +} diff --git a/simulatordaemon/src/SimulatorDaemonServer.cpp b/simulatordaemon/src/SimulatorDaemonServer.cpp new file mode 100755 index 0000000..7d06878 --- /dev/null +++ b/simulatordaemon/src/SimulatorDaemonServer.cpp @@ -0,0 +1,66 @@ +/* + * ===================================================================================== + * + * Filename: SimulatorDaemonServer.cpp + * + * Description: SimulatorDaemonServer class + * + * Version: 1.0 + * Created: 16 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "SimulatorDaemonServer.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Accepts a new connection from local machine on a UDS + * @param io_service provides OS abstraction for async communication + * @param file path to Unix Domain Socket represented by a local file + */ +SimulatorDaemonServer::SimulatorDaemonServer( + boost::asio::io_service& io_service, const std::string& file) : + mem_io_service(io_service), + acceptor(io_service, stream_protocol::endpoint(file)) { + startAccept(); +} + +/** + * Method to start accepting a new connection + * @param none + */ +void SimulatorDaemonServer::startAccept() { + LOGD(SIM_DAEMON, "Entry"); + ConnectionSession::session_ptr new_session = ConnectionSession::create( + acceptor.get_io_service()); + + acceptor.async_accept(new_session->socket(), + boost::bind(&SimulatorDaemonServer::handleAccept, this, new_session, + boost::asio::placeholders::error)); +} + +/** + * Call back for boost acceptor.async_accept() to handle a new connection + * @param new_session a pointer to a session + * @param error error code if any occurred + */ +void SimulatorDaemonServer::handleAccept( + ConnectionSession::session_ptr new_session, + const boost::system::error_code& error) { + LOGD(SIM_DAEMON, "Entry"); + if (!error) { + new_session->start(); + } + startAccept(); +} diff --git a/simulatordaemon/src/TABinaryManager/.cproject b/simulatordaemon/src/TABinaryManager/.cproject new file mode 100755 index 0000000..552414a --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/.cproject @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/simulatordaemon/src/TABinaryManager/.project b/simulatordaemon/src/TABinaryManager/.project new file mode 100755 index 0000000..51cfe9c --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/.project @@ -0,0 +1,64 @@ + + + TABinaryManager + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + include + 2 + virtual:/virtual + + + include/tee_command.h + 1 + PARENT-2-PROJECT_LOC/include/tee_command.h + + + include/tee_internal_api.h + 1 + PARENT-2-PROJECT_LOC/include/tee_internal_api.h + + + include/tee_sim_command.h + 1 + PARENT-2-PROJECT_LOC/include/tee_sim_command.h + + + include/tee_client_api.h + 1 + PARENT-2-PROJECT_LOC/include/tee_client_api.h + + + include/teec_data.h + 1 + PARENT-2-PROJECT_LOC/include/teec_data.h + + + include/teestub_command_data.h + 1 + PARENT-2-PROJECT_LOC/include/teestub_command_data.h + + + diff --git a/simulatordaemon/src/TABinaryManager/Config.h b/simulatordaemon/src/TABinaryManager/Config.h new file mode 100755 index 0000000..110e0bd --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Config.h @@ -0,0 +1,28 @@ +/* + * ===================================================================================== + * + * Filename: Config.h + * + * Description: Configuration details + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define TA_STORE_PATH "/tmp/tastore/" +#define TA_UUID_LIST_PATH "/tmp/tastore/uuidlist.list" + +#endif /* CONFIG_H_ */ diff --git a/simulatordaemon/src/TABinaryManager/Debug/TABinaryManager b/simulatordaemon/src/TABinaryManager/Debug/TABinaryManager new file mode 100755 index 0000000000000000000000000000000000000000..27a5b72a497abe596410fdcc343271df29a39bad GIT binary patch literal 380816 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

JOD^=yR*L9cCPbKlMXnymY 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 literal 0 HcmV?d00001 diff --git a/simulatordaemon/src/TABinaryManager/Debug/TABinaryManager.d b/simulatordaemon/src/TABinaryManager/Debug/TABinaryManager.d new file mode 100755 index 0000000..93160c3 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/TABinaryManager.d @@ -0,0 +1,13 @@ +TABinaryManager.d: ../TABinaryManager.cpp ../TABinaryManager.h \ + ../TAManifest.h ../TAUnpack.h ../Config.h \ + /home/krishna/TASDKCode/Simulator/TABinaryManager/TABinaryManager/../../include/tee_internal_api.h + +../TABinaryManager.h: + +../TAManifest.h: + +../TAUnpack.h: + +../Config.h: + +/home/krishna/TASDKCode/Simulator/TABinaryManager/TABinaryManager/../../include/tee_internal_api.h: diff --git a/simulatordaemon/src/TABinaryManager/Debug/TAManifest.d b/simulatordaemon/src/TABinaryManager/Debug/TAManifest.d new file mode 100755 index 0000000..aed1eaa --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/TAManifest.d @@ -0,0 +1,10 @@ +TAManifest.d: ../TAManifest.cpp ../TAManifest.h ../rapidxml/rapidxml.hpp \ + ../rapidxml/rapidxml_utils.hpp ../rapidxml/rapidxml.hpp + +../TAManifest.h: + +../rapidxml/rapidxml.hpp: + +../rapidxml/rapidxml_utils.hpp: + +../rapidxml/rapidxml.hpp: diff --git a/simulatordaemon/src/TABinaryManager/Debug/TAUnpack.d b/simulatordaemon/src/TABinaryManager/Debug/TAUnpack.d new file mode 100755 index 0000000..3c6b7be --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/TAUnpack.d @@ -0,0 +1,3 @@ +TAUnpack.d: ../TAUnpack.cpp ../TAUnpack.h + +../TAUnpack.h: diff --git a/simulatordaemon/src/TABinaryManager/Debug/TestMain.d b/simulatordaemon/src/TABinaryManager/Debug/TestMain.d new file mode 100755 index 0000000..9f653a9 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/TestMain.d @@ -0,0 +1,13 @@ +TestMain.d: ../TestMain.cpp ../TABinaryManager.h ../TAManifest.h \ + ../TAUnpack.h ../Config.h \ + /home/krishna/TASDKCode/Simulator/TABinaryManager/TABinaryManager/../../include/tee_internal_api.h + +../TABinaryManager.h: + +../TAManifest.h: + +../TAUnpack.h: + +../Config.h: + +/home/krishna/TASDKCode/Simulator/TABinaryManager/TABinaryManager/../../include/tee_internal_api.h: diff --git a/simulatordaemon/src/TABinaryManager/Debug/makefile b/simulatordaemon/src/TABinaryManager/Debug/makefile new file mode 100755 index 0000000..70390a8 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/makefile @@ -0,0 +1,58 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +-include ../makefile.init + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(CC_DEPS)),) +-include $(CC_DEPS) +endif +ifneq ($(strip $(C++_DEPS)),) +-include $(C++_DEPS) +endif +ifneq ($(strip $(C_UPPER_DEPS)),) +-include $(C_UPPER_DEPS) +endif +ifneq ($(strip $(CXX_DEPS)),) +-include $(CXX_DEPS) +endif +ifneq ($(strip $(CPP_DEPS)),) +-include $(CPP_DEPS) +endif +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: TABinaryManager + +# Tool invocations +TABinaryManager: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + g++ -o "TABinaryManager" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + +# Other Targets +clean: + -$(RM) $(CC_DEPS)$(C++_DEPS)$(EXECUTABLES)$(C_UPPER_DEPS)$(CXX_DEPS)$(OBJS)$(CPP_DEPS)$(C_DEPS) TABinaryManager + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: + +-include ../makefile.targets diff --git a/simulatordaemon/src/TABinaryManager/Debug/objects.mk b/simulatordaemon/src/TABinaryManager/Debug/objects.mk new file mode 100755 index 0000000..742c2da --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/objects.mk @@ -0,0 +1,8 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +USER_OBJS := + +LIBS := + diff --git a/simulatordaemon/src/TABinaryManager/Debug/sources.mk b/simulatordaemon/src/TABinaryManager/Debug/sources.mk new file mode 100755 index 0000000..a7f166f --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/sources.mk @@ -0,0 +1,27 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +C_UPPER_SRCS := +CXX_SRCS := +C++_SRCS := +OBJ_SRCS := +CC_SRCS := +ASM_SRCS := +CPP_SRCS := +C_SRCS := +O_SRCS := +S_UPPER_SRCS := +CC_DEPS := +C++_DEPS := +EXECUTABLES := +C_UPPER_DEPS := +CXX_DEPS := +OBJS := +CPP_DEPS := +C_DEPS := + +# Every subdirectory with source files must be described here +SUBDIRS := \ +. \ + diff --git a/simulatordaemon/src/TABinaryManager/Debug/subdir.mk b/simulatordaemon/src/TABinaryManager/Debug/subdir.mk new file mode 100755 index 0000000..8160197 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/Debug/subdir.mk @@ -0,0 +1,33 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +# Add inputs and outputs from these tool invocations to the build variables +CPP_SRCS += \ +../TABinaryManager.cpp \ +../TAManifest.cpp \ +../TAUnpack.cpp \ +../TestMain.cpp + +OBJS += \ +./TABinaryManager.o \ +./TAManifest.o \ +./TAUnpack.o \ +./TestMain.o + +CPP_DEPS += \ +./TABinaryManager.d \ +./TAManifest.d \ +./TAUnpack.d \ +./TestMain.d + + +# Each subdirectory must supply rules for building sources it contributes +%.o: ../%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -I"/home/krishna/TASDKCode/Simulator/TABinaryManager/TABinaryManager/../../include" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + + diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp new file mode 100755 index 0000000..7c15c5a --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.cpp @@ -0,0 +1,505 @@ +/* + * ===================================================================================== + * + * Filename: TABinaryManager.cpp + * + * Description: TABinaryManager class + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TABinaryManager.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +TABinaryManager *TABinaryManager::instance = NULL; +pthread_rwlock_t binaryMapLock; +map binaryMap; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Checks if a characters is part of base64 encoding character set + * @param c character to be verified + * @return true if conformant to base64 charset else false + */ +bool TABinaryManager::is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +/** + * Thanks to: René Nyffenegger + * Reused from: http://www.adp-gmbh.ch/cpp/common/base64.html + * License Notice: + * Copyright (C) 2004-2008 René Nyffenegger + * + * This source code is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this source code must not be misrepresented; you must not + * claim that you wrote the original source code. If you use this source code + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original source code. + * + * 3. This notice may not be removed or altered from any source distribution. + * + * René Nyffenegger rene.nyffenegger@adp-gmbh.ch + * + * @param encoded_string + * @return + */ +string TABinaryManager::base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && (encoded_string[in_] != '=') + && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; + in_++; + if (i == 4) { + for (i = 0; i < 4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + char_array_3[0] = (char_array_4[0] << 2) + + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + if (i) { + for (j = i; j < 4; j++) + char_array_4[j] = 0; + for (j = 0; j < 4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + for (j = 0; (j < i - 1); j++) + ret += char_array_3[j]; + } + return ret; +} + + +/** + * This is the constructor of TABinaryManger. + */ +TABinaryManager::TABinaryManager() { + //Stat for mod time + + /// Constant charset of base64 encoding + base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + struct stat attr; + if (stat(TA_UUID_LIST_PATH, &attr) == -1) { + LOGE(SIM_DAEMON, "stat FAILED %d", errno); + } + lastModTimeUUIDList = attr.st_mtime; + pthread_rwlock_init(&binaryMapLock, NULL); + pthread_mutex_init(&taLock, NULL); +} + +/** + * This function returns the TA Binary Manager instance if already created + * else creates the instance and returns it + */ +TABinaryManager* TABinaryManager::getInstance() { + if (NULL == instance) { + try { + instance = new TABinaryManager(); + }catch (std::bad_alloc &ba) { + return NULL; + } + } + return instance; +} + +/** + * This function reads UUID list file and unpacks files to their respective + * locations. + * @return On successful completion of above operations returns true else false. + * It is very important to check for return value from this function. + */ +bool TABinaryManager::readUUIDList() { + LOGD(SIM_DAEMON, ""); + string line; + struct flock fl = {F_RDLCK, SEEK_SET, 0, 0, 0}; + + fl.l_pid = getpid(); + + // Open file + int fd = open(TA_UUID_LIST_PATH, O_RDONLY); + + if (fd == -1) return false; + FILE *fp = fdopen(fd, "r"); + if (fcntl(fd, F_SETLKW, &fl) == -1) { + perror("fcntl"); + fclose(fp); + return false; + } + pthread_rwlock_wrlock(&binaryMapLock); + + //wh + std::ifstream uuidFileStream(TA_UUID_LIST_PATH); + std::string str; + if(uuidFileStream) { + getline(uuidFileStream, str); + line = line + str; + } + + /* + int ch = fgetc(fp); + while ((ch != '\n') && (ch != EOF)) { + line = line + ch; + ch = fgetc(fp); + }*/ + + while (line != "") { + line = line + "\0"; + StructBinaryInfo info; + + char* data = (char*)OsaMalloc((strlen(line.c_str()) + 1) * sizeof(char)); + char* uuid_data; + strncpy(data, line.c_str(), (strlen(line.c_str()) + 1) * sizeof(char)); + uuid_data = strtok(data, ","); + const string uuid(data); + if (uuid_data != NULL) { + char* port_data; + port_data = strtok(NULL, ","); + if (port_data != NULL) { + string port(port_data); + info.port = port; + } else info.port = ""; + } + //cout << "UUID: " << uuid << endl; + //cout << "port: " << info.port << endl; + // Open file + FILE *fpTA=fopen((string(TA_STORE_PATH) + "ta.tmp").c_str(),"r+"); + if (flock(fileno(fpTA),LOCK_EX) != 0) { // do an exclusive lock + LOGE(SIM_DAEMON, "Failed to lock the file"); + } + pthread_mutex_lock(&taLock); + if (unpackBinary(uuid, info)) { + binaryMap[uuid] = info; + } + pthread_mutex_unlock(&taLock); + if (flock(fileno(fpTA),LOCK_UN) != 0) { + LOGE(SIM_DAEMON, "Failed to unlock the file"); + } + fclose(fpTA); + OsaFree(data); + + line = ""; + + if(uuidFileStream) { + getline(uuidFileStream, str); + line = line + str; + } + + /* + ch = fgetc(fp); + while ((ch != '\n') && (ch != EOF)) { + line = line + ch; + ch = fgetc(fp); + }*/ + + } + pthread_rwlock_unlock(&binaryMapLock); + fl.l_type = F_UNLCK; + if (fcntl(fd, F_SETLKW, &fl) == -1) { + perror("fcntl"); + fclose(fp); + return false; + } + if(uuidFileStream) + uuidFileStream.close(); + fclose(fp); + return true; +} + +/** + * This function decrypts the TA Binary image + * @param uuid TA UUID in string format + * @param info TA Binary info + */ +void TABinaryManager::decryptImage(StructBinaryInfo& info) { + string cipher = "-aes-256-cbc"; + string secret = base64_decode (info.manifest.taencryption.model.plainkeydata); + string keyhashFilename = info.imagePath + ".keyhash"; + secret.erase(secret.size()-2); + string keyHash = "echo -n " + secret + " | openssl dgst -sha256 | awk '{print $2}' > " + keyhashFilename; + cout << keyHash << endl; + system(keyHash.c_str()); + + string line; + ifstream myfile(keyhashFilename.c_str()); + if (myfile.is_open()) { + getline(myfile, line); + //cout << "line " << line << endl; + myfile.close(); + } + + // hash of Keydata is not required. + string dec_command = "openssl enc " + cipher + " -d -nopad -nosalt -K " + secret + + " -in " + info.imagePath + " -out " + info.imagePath + + "_dec -iv 0000000000000000"; + //std::cout << dec_command << std::endl; + system(dec_command.c_str()); + string removeEncImage = "rm -f " + info.imagePath; + //std::cout << removeEncImage << std::endl; + system(removeEncImage.c_str()); + string renameDecImage = "mv " + info.imagePath + "_dec " + info.imagePath; + //std::cout << renameDecImage << std::endl; + system(renameDecImage.c_str()); + string removeKeyHash = "rm -f " + keyhashFilename; + //std::cout << removeEncImage << std::endl; + system(removeKeyHash.c_str()); +} + +/** + * This function reads unpacks files to their respective locations. + * It also reads manifest file and keeps it ready for queries on fields + * in manifest. + * @param uuid TA UUID in string format + * @param info TA Binary info + * @return On successful completion of above operations returns true else false. + * It is very important to check for return value from this function. + */ +bool TABinaryManager::unpackBinary(const string &uuid, StructBinaryInfo& info) { + TAUnpack* unpacker = TAUnpack::getInstance(); + bool ret = false; + LOGE(SIM_DAEMON, ""); + if (0 == unpacker->unpackTA(string(TA_STORE_PATH), uuid)) { + // 1. Set binary info + info.path = string(TA_STORE_PATH) + uuid; + info.extractpath = string(TA_STORE_PATH) + uuid + "-ext/"; + info.imagePath = info.extractpath + uuid + ".image"; + info.manifestPath = info.extractpath + uuid + ".manifest"; + // 2. Parse manifest and store results + info.manifest.processXML(info.manifestPath); + // 3. Decrypt image using secret value in manifest + if (info.manifest.properties.extension.launchMode == "debug") + decryptImage(info); + + string s = "chmod +x " + info.imagePath; + system(s.c_str()); + + ret = true; + } + return ret; +} + +/** + * This is the main function of TABinaryManger. This function reads UUID list file + * and unpacks files to their respective locations. It also reads manifest file and + * keeps it ready for queries on fields in manifest. + * @return On successful completion of above operations returns true else false. + * It is very important to check for return value from this function. + */ +bool TABinaryManager::initBinaryManager() { + LOGD(SIM_DAEMON, ""); + return readUUIDList(); +} + +/** + * Check if TA is single instance + * @param[in] uuid UUID of TA + * @param[out] isSingleInstance returns value from this parameter. + * @return -1 if uuid is not found else on success 0 + */ + +int TABinaryManager::isSingleInstance(string uuid, bool &SingleInstance) { + checkUUIDUpdate(); + pthread_rwlock_wrlock(&binaryMapLock); + map::iterator it = binaryMap.find(uuid); + StructBinaryInfo value; + int ret = -1; + if (it != binaryMap.end()) { + //element found; + value = it->second; + ret = 0; + SingleInstance = value.manifest.properties.general.singleInstance; + } + pthread_rwlock_unlock(&binaryMapLock); + return ret; +} + +/** + * Check if TA is KeepAlive + * @param[in] uuid UUID of TA + * @param[out] isKeepAlive returns value from this parameter. + * @return -1 if uuid is not found else on success 0 + */ + +int TABinaryManager::isKeepAlive(string uuid, bool &KeepAlive) { + checkUUIDUpdate(); + pthread_rwlock_wrlock(&binaryMapLock); + map::iterator it = binaryMap.find(uuid); + StructBinaryInfo value; + int ret = -1; + if (it != binaryMap.end()) { + //element found; + value = it->second; + ret = 0; + KeepAlive = value.manifest.properties.general.instanceKeepAlive; + } + pthread_rwlock_unlock(&binaryMapLock); + return ret; +} + +/** + * Check if TA is multi instance type + * @param[in] uuid UUID of TA + * @param[out] isMultipleSession returns value from this parameter. + * @return -1 if uuid is not found else on success 0 + */ +int TABinaryManager::isMultipleSession(string uuid, bool &MultipleSession) { + checkUUIDUpdate(); + pthread_rwlock_wrlock(&binaryMapLock); + map::iterator it = binaryMap.find(uuid); + StructBinaryInfo value; + int ret = -1; + if (it != binaryMap.end()) { + //element found; + value = it->second; + ret = 0; + MultipleSession = value.manifest.properties.general.multiSession; + } + pthread_rwlock_unlock(&binaryMapLock); + return ret; +} + +/** + * Get TA executable image path + * @param uuid UUID of TA + * @return Empty string if UUID doesn't exist, else path to TA + */ +string TABinaryManager::getImagePath(string uuid) { + checkUUIDUpdate(); + pthread_rwlock_wrlock(&binaryMapLock); + map::iterator it = binaryMap.find(uuid); + StructBinaryInfo value; + string ret = ""; + if (it != binaryMap.end()) { + //element found; + value = it->second; + ret = value.imagePath; + } + pthread_rwlock_unlock(&binaryMapLock); + return ret; +} + +/** + * Constant to TA Manifest object + * @param uuid UUID of TA + * @return NULL pointer if + */ +const TAManifest* TABinaryManager::getManifest(string uuid) { + checkUUIDUpdate(); + pthread_rwlock_wrlock(&binaryMapLock); + map::iterator it = binaryMap.find(uuid); + TAManifest *returnValue = NULL; + if (it != binaryMap.end()) { + //element found; + returnValue = &(it->second.manifest); + } + pthread_rwlock_unlock(&binaryMapLock); + return returnValue; +} + +/** + * Constant to port string + * @param uuid UUID of TA + * @return NULL pointer if + */ +string TABinaryManager::getPort(string uuid) { + pthread_rwlock_wrlock(&binaryMapLock); + map::iterator it = binaryMap.find(uuid); + string returnValue = ""; + if (it != binaryMap.end()) { + returnValue = it->second.port; + } + pthread_rwlock_unlock(&binaryMapLock); + return returnValue; +} + +/** + * Converts UUID from TEEC_UUID to a string + * @return string of TEEC_UUID + */ +string TABinaryManager::getUUIDAsString(TEEC_UUID uuid) { + checkUUIDUpdate(); + // E.g. returns a string in the format 79B7778897894a7aA2BEB60155EEF5F3 + std::stringstream strStream; + strStream << IntToHex(uuid.timeLow); + strStream << IntToHex(uuid.timeMid); + strStream << IntToHex(uuid.timeHiAndVersion); + for (int i = 0; i < 8; i++) { + strStream << IntToHex((short)uuid.clockSeqAndNode[i], 2); + } + return strStream.str(); +} + +/** + * This function checks for UUID update and reads the list in case of update + */ +void TABinaryManager::checkUUIDUpdate() { + struct stat attr; + if (stat(TA_UUID_LIST_PATH, &attr) == -1) { + LOGE(SIM_DAEMON, "stat FAILED"); + return; + } + if (lastModTimeUUIDList != attr.st_mtime) { + readUUIDList(); + if (stat(TA_UUID_LIST_PATH, &attr) == -1) { + LOGE(SIM_DAEMON, "stat FAILED"); + return; + } + lastModTimeUUIDList = attr.st_mtime; + } +} + +TABinaryManager::~TABinaryManager() { + pthread_rwlock_destroy(&binaryMapLock); + pthread_mutex_destroy(&taLock); + delete instance; +} diff --git a/simulatordaemon/src/TABinaryManager/TABinaryManager.h b/simulatordaemon/src/TABinaryManager/TABinaryManager.h new file mode 100755 index 0000000..00cfb90 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TABinaryManager.h @@ -0,0 +1,104 @@ +/* + * ===================================================================================== + * + * Filename: TABinaryManager.h + * + * Description: TABinaryManager header file + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TABINARYMANAGER_H_ +#define TABINARYMANAGER_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "OsaLinuxUser.h" +#include "tee_client_api.h" +#include "TAManifest.h" +#include "TAUnpack.h" +#include "Config.h" +#include "tee_internal_api.h" + +using namespace std; + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +typedef struct { + string path; + string extractpath; + string imagePath; + string manifestPath; + TAManifest manifest; + string port; +} StructBinaryInfo; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TABinaryManager { + +private: + static TABinaryManager *instance; + std::string base64_chars; + // map < string uuid, StructBinaryInfo> + map binaryMap; + time_t lastModTimeUUIDList; + TABinaryManager(); + bool readUUIDList(); + bool unpackBinary(const string &uuid, StructBinaryInfo& info); + template + std::string IntToHex(T i, int width = sizeof(T) * 2) { + std::stringstream stream; + stream << std::setfill('0') << std::setw(width) << std::hex << i; + return stream.str(); + } + void checkUUIDUpdate(); + void decryptImage(StructBinaryInfo& info); + string base64_decode(std::string const& encoded_string); + bool is_base64(unsigned char c); +public: + /** + * Gets pointer to singleton instance of TABinaryManager. + * Perform lazy creation of TABinaryManager. During lazy init, + * it also performs init of TABinaryManager where if UUID list XML is + * not readable then getInstance fails. + * @return Pointer to instance on successful initialization. + * Else null pointer on error + */ + pthread_mutex_t taLock; + static TABinaryManager* getInstance(); + bool initBinaryManager(); + + /* + * Query functions on Binary Manager + */ + int isSingleInstance(string uuid, bool &SingleInstance); + int isMultipleSession(string uuid, bool &MultipleSession); + string getImagePath(string uuid); + const TAManifest* getManifest(string uuid); + string getUUIDAsString(TEEC_UUID uuid); + string getPort(string uuid); + int isKeepAlive(string uuid, bool &KeepAlive); + + virtual ~TABinaryManager(); +}; + +#endif /* TABINARYMANAGER_H_ */ diff --git a/simulatordaemon/src/TABinaryManager/TAManifest.cpp b/simulatordaemon/src/TABinaryManager/TAManifest.cpp new file mode 100755 index 0000000..ae14cbe --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TAManifest.cpp @@ -0,0 +1,213 @@ +/* + * ===================================================================================== + * + * Filename: TAManifest.cpp + * + * Description: TAManifest class + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TAManifest.h" +#include "rapidxml/rapidxml.hpp" +#include "rapidxml/rapidxml_utils.hpp" +#include +#include + +using namespace rapidxml; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ + +TAManifest::TAManifest() { + +} + +bool TAManifest::processXML(const string &xmlManifestPath) { + + bool ret = false; + // Open file + std::ifstream xmlfile(xmlManifestPath.c_str()); + std::stringstream buffer; + buffer << xmlfile.rdbuf(); + xmlfile.close(); + std::string content(buffer.str()); + //cout << content << endl; + // Create xml DOM + xml_document<> doc; + // Parse XML from file and populate doc + doc.parse<0>((char*)content.c_str()); + try { + // 1. PROPERTIES + xml_node<> *node = doc.first_node("manifest")->first_node("properties"); + { + stringstream sstream; + // GENERAL + xml_node<> *propertiesGeneral = node->first_node("general"); + properties.general.appID = string( + propertiesGeneral->first_attribute("appID")->value()); + properties.general.singleInstance = + string(propertiesGeneral->first_attribute("singleInstance")->value()) + .compare("true") == 0 ? true : false; + properties.general.multiSession = + string(propertiesGeneral->first_attribute("multiSession")->value()) + .compare("true") == 0 ? true : false; + properties.general.instanceKeepAlive = + string( + propertiesGeneral->first_attribute("instanceKeepAlive")->value()) + .compare("true") == 0 ? true : false; + + sstream.clear(); + sstream.str( + string(propertiesGeneral->first_attribute("stackSize")->value())); + sstream >> properties.general.stackSize; + + sstream.clear(); + sstream.str( + string(propertiesGeneral->first_attribute("dataSize")->value())); + sstream >> properties.general.dataSize; + // EXTENSION + xml_node<> *propertiesExtension = node->first_node("extension"); + properties.extension.appName = string( + propertiesExtension->first_attribute("appName")->value()); + properties.extension.appVersion = string( + propertiesExtension->first_attribute("appVersion")->value()); + /*properties.extension.type = string( + propertiesExtension->first_attribute("type")->value()); + properties.extension.zone = string( + propertiesExtension->first_attribute("zone")->value());*/ + properties.extension.sdkVersion = string( + propertiesExtension->first_attribute("sdkVersion")->value()); + // Removed, taEncrypion flag used now + //properties.extension.secret = string( + // propertiesExtension->first_attribute("secret")->value()); + properties.extension.launchMode = string( + propertiesExtension->first_attribute("launchMode")->value()); + + } + // 2. POLICY + node = doc.first_node("manifest")->first_node("policy"); + { + // PRIVILEGE + xml_node<> *policyPrivilege = node->first_node("privilege"); + policy.privilegeName = string( + policyPrivilege->first_attribute("name")->value()); + // PROTECTION DOMAIN + xml_node<> *policyProtectionDomain = node->first_node("protectionDomain"); + policy.protectionDomain.createDomain = string( + policyProtectionDomain->first_node("createDomain")->first_attribute( + "name")->value()); + policy.protectionDomain.allowedDomain = string( + policyProtectionDomain->first_node("allowedDomain")->first_attribute( + "name")->value()); + // PERMISSION - vector + xml_node<> *policyPermission = node->first_node("permission"); + for (xml_node<> *childnode = policyPermission->first_node( + "uses-permission"); childnode; childnode = + childnode->next_sibling()) { + //std::cout << "[SIM_DAEMON] Permission vector: " << string(childnode->first_attribute("name")->value()) << endl; + policy.usesPermission.push_back( + string(childnode->first_attribute("name")->value())); + } + } + // 3. TA ENC + node = doc.first_node("manifest")->first_node("taEncryption"); + { + // MODEL + xml_node<> *model = node->first_node("model"); + taencryption.model.modelName = string( + model->first_node("modelName")->first_attribute("value")->value()); + taencryption.model.plainkeydata = string( + model->first_node("plainkeydata")->first_attribute("value")->value()); + } + // 4. INFORMATION + node = doc.first_node("manifest")->first_node("information"); + { + information.description = string( + node->first_node("description")->value()); + information.author = string(node->first_node("author")->value()); + information.terms = string(node->first_node("terms")->value()); + information.copyright = string(node->first_node("copyright")->value()); + + } + ret = true; + } + // Catch rapid xml errors + catch (rapidxml::parse_error &e) { + std::cout << "[SIM_DAEMON] RAPID_XML EXCEPTION" << e.what() << endl; + } + return ret; +} + +// This is just for debug +void TAManifest::printProcessedData() const { + std::cout << "[SIM_DAEMON] XML DUMP:" << endl; + std::cout << "[SIM_DAEMON] properties.general.appID: " + << properties.general.appID << endl; + std::cout << "[SIM_DAEMON] properties.general.dataSize: " + << properties.general.dataSize << endl; + std::cout << "[SIM_DAEMON] properties.general.instanceKeepAlive: " + << properties.general.instanceKeepAlive << endl; + std::cout << "[SIM_DAEMON] properties.general.multiSession: " + << properties.general.multiSession << endl; + std::cout << "[SIM_DAEMON] properties.general.singleInstance: " + << properties.general.singleInstance << endl; + std::cout << "[SIM_DAEMON] properties.general.stackSize: " + << properties.general.stackSize << endl << endl; + + std::cout << "[SIM_DAEMON] properties.general.singleInstance: " + << properties.extension.appName << endl; + std::cout << "[SIM_DAEMON] properties.extension.appVersion: " + << properties.extension.appVersion << endl; + std::cout << "[SIM_DAEMON] properties.extension.launchMode: " + << properties.extension.launchMode << endl; + std::cout << "[SIM_DAEMON] properties.extension.sdkVersion: " + << properties.extension.sdkVersion << endl; + // REMOVED + //std::cout << "[SIM_DAEMON] properties.extension.secret: " + // << properties.extension.secret << endl; + /*std::cout << "[SIM_DAEMON] properties.extension.type: " + << properties.extension.type << endl; + std::cout << "[SIM_DAEMON] properties.extension.zone: " + << properties.extension.zone << endl << endl;*/ + + std::cout << "[SIM_DAEMON] policy.privilegeName: " << policy.privilegeName + << endl; + std::cout << "[SIM_DAEMON] " << policy.protectionDomain.allowedDomain << endl; + std::cout << "[SIM_DAEMON] " << policy.protectionDomain.createDomain << endl; + for (unsigned int i = 0; i < policy.usesPermission.size(); i++) { + std::cout << "[SIM_DAEMON] \tpolicy.usesPermission: " + << policy.usesPermission[i] << endl; + } + cout << endl; + + std::cout << "[SIM_DAEMON] taencryption.model.modelName: " << taencryption.model.modelName + << endl; + std::cout << "[SIM_DAEMON] taencryption.model.plainkeydata: " << taencryption.model.plainkeydata + << endl; + std::cout << "[SIM_DAEMON] information.author: " << information.author + << endl; + std::cout << "[SIM_DAEMON] information.copyright: " << information.copyright + << endl; + std::cout << "[SIM_DAEMON] information.description: " + << information.description << endl; + std::cout << "[SIM_DAEMON] information.terms: " << information.terms << endl; + +} + +TAManifest::~TAManifest() { + +} + diff --git a/simulatordaemon/src/TABinaryManager/TAManifest.h b/simulatordaemon/src/TABinaryManager/TAManifest.h new file mode 100755 index 0000000..da7edcd --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TAManifest.h @@ -0,0 +1,104 @@ +/* + * ===================================================================================== + * + * Filename: TAManifest.h + * + * Description: TAManifest header file + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TAMANIFEST_H_ +#define TAMANIFEST_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +using namespace std; + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +typedef struct { + string appID; + bool singleInstance; + bool multiSession; + bool instanceKeepAlive; + unsigned int stackSize; + unsigned int dataSize; +} StructPropertiesGeneral; + +typedef struct { + string modelName; + string plainkeydata; +} StructModel; + +typedef struct { + StructModel model; +} StructTaEncryption; + +typedef struct { + string appName; + string appVersion; + //string type; + //string zone; + string sdkVersion; + //string secret; //Removed + string launchMode; +} StructPropertiesExtension; + + + +typedef struct { + StructPropertiesGeneral general; + StructPropertiesExtension extension; +} StructProperties; + +typedef struct { + string createDomain; + string allowedDomain; +} StructPolicyProtectionDomain; + +typedef struct { + string privilegeName; + StructPolicyProtectionDomain protectionDomain; + vector usesPermission; +} StructPolicy; + +typedef struct { + string description; + string author; + string terms; + string copyright; +} StructInformation; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ + +class TAManifest { + +public: + StructProperties properties; + StructPolicy policy; + StructTaEncryption taencryption; + StructInformation information; + +public: + TAManifest(); + bool processXML(const string &xmlManifest); + void printProcessedData() const; + virtual ~TAManifest(); + +}; +#endif /* TAMANIFEST_H_ */ diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.cpp b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp new file mode 100755 index 0000000..26c3da9 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.cpp @@ -0,0 +1,163 @@ +/* + * ===================================================================================== + * + * Filename: TAUnpack.cpp + * + * Description: TAUnpack class + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TAUnpack.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +TAUnpack *TAUnpack::instance = NULL; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +TAUnpack::TAUnpack() { + +} + +TAUnpack* TAUnpack::getInstance() { + if (instance == NULL) { + instance = new TAUnpack(); + } + return instance; +} + +/** + * Unpacks a TA from its package into header, image, manifest, cert and sign + * @param path path to directory where uuid is placed. path should end with trailing / + * @param uuid uuid of package + * @return -1 on error otherwise 0 + */ +int TAUnpack::unpackTA(string path, string uuid) { + LOGD(SIM_DAEMON, ""); + TAPackageHeaderV2 packageHeader; + memset(&packageHeader, 0, sizeof(TAPackageHeaderV2)); + // Open file + string path_to_file = path + uuid; + ifstream tapackage(path_to_file.c_str(), ios::in | ios::binary); + // Create directory for UUID + string extract_dir_path = path + uuid + "-ext/"; + struct stat info; + if (stat(extract_dir_path.c_str(), &info) != 0) { + if (0 != mkdir(extract_dir_path.c_str(), 0777)) { + LOGE(SIM_DAEMON, "mkdir failed"); + return -1; + } + } + + if (!tapackage.is_open()) { + LOGE(SIM_DAEMON, "Already open - failed"); + return -1; //> unable to open file + } + // 1. Read header + tapackage.read((char*)&packageHeader, sizeof(TAPackageHeaderV2)); + if (tapackage.fail()) { + LOGE(SIM_DAEMON, "Read failed"); + return -1; + } + // fixHeaderEndianness(&packageHeader); + // 2. Verify header + if (SECURITY_HEADER_MAGIC1 == packageHeader.magic1 && + SECURITY_HEADER_MAGIC2 == packageHeader.magic2) { + // 3. Read image and write to FS + tapackage.seekg(packageHeader.image_offset); + char *imagedump = new char[packageHeader.image_size]; + tapackage.read(imagedump, packageHeader.image_size); + if (tapackage.fail()) { + LOGE(SIM_DAEMON, "Read failed"); + return -1; + } + string removeImage = "rm -f " + extract_dir_path + uuid + ".image"; + system(removeImage.c_str()); + ofstream image((extract_dir_path + uuid + ".image").c_str(), + ios::out | ios::binary); + ofstream manifest((extract_dir_path + uuid + ".manifest").c_str(), + ios::out | ios::binary); + image.write(imagedump, packageHeader.image_size); + image.flush(); + delete[] imagedump; + + // 4. Read manifest and write to FS + tapackage.seekg(packageHeader.manifest_offset); + char *manifestdump = new char[packageHeader.manifest_size]; + tapackage.read(manifestdump, packageHeader.manifest_size); + if (tapackage.fail()) { + LOGE(SIM_DAEMON, "Read failed"); + return -1; + } + //manifest.write(manifestdump, sizeWithoutPadding(manifestdump, packageHeader.manifest_size)); + manifest.write(manifestdump, packageHeader.manifest_size); + manifest.flush(); + delete[] manifestdump; + } else { + LOGE(SIM_DAEMON, "Header verification failed"); + return -1; + } + + return 0; +} + +void TAUnpack::fixHeaderEndianness(TAPackageHeaderV2* header) { + + char* headerptr = (char*)header; + for (unsigned int i = 0; i < sizeof(TAPackageHeaderV2); i += + sizeof(unsigned int)) { + char temp1 = headerptr[i]; + char temp2 = headerptr[i + 1]; + headerptr[i] = headerptr[i + 3]; + headerptr[i + 1] = headerptr[i + 2]; + headerptr[i + 3] = temp1; + headerptr[i + 2] = temp2; + } + +} + +/** + * Returns unpadded data size + * @param paddedData + * @param paddedSize + * @return size of unpadded data = padded data size - padding size + */ +unsigned int TAUnpack::sizeWithoutPadding(const char* paddedData, + unsigned int paddedSize) { + + unsigned int paddingSize = 0; + + for (unsigned int i = paddedSize - 1; (i > 0 && 0 == paddedData[i]); i--) { + paddingSize++; + } + + return (paddedSize - paddingSize); +} + +TAUnpack::~TAUnpack() { + delete instance; +} + diff --git a/simulatordaemon/src/TABinaryManager/TAUnpack.h b/simulatordaemon/src/TABinaryManager/TAUnpack.h new file mode 100755 index 0000000..0602570 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TAUnpack.h @@ -0,0 +1,80 @@ +/* + * ===================================================================================== + * + * Filename: TAUnpack.h + * + * Description: TAUnpack header file + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef TAUNPACK_H_ +#define TAUNPACK_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +using namespace std; + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define PAGE_SIZE (1024) +#define SECURITY_HEADER_MAGIC1 (0x736D6153) +#define SECURITY_HEADER_MAGIC2 (0x2E676E75) + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +typedef struct { + unsigned int magic1; + unsigned int magic2; + unsigned int version; + unsigned int reserve; + unsigned int image_offset; + unsigned int image_size; + unsigned int sign_offset; + unsigned int sign_size; +} TAPackageHeaderV1; + +typedef struct { + unsigned int magic1; + unsigned int magic2; + unsigned int version; + unsigned int reserve; + unsigned int image_offset; + unsigned int image_size; + unsigned int manifest_offset; + unsigned int manifest_size; + unsigned int cert_offset; + unsigned int cert_size; + unsigned int sign_offset; + unsigned int sign_size; +} TAPackageHeaderV2; + +/*----------------------------------------------------------------------------- + * Class definitions + *-----------------------------------------------------------------------------*/ +class TAUnpack { +private: + TAUnpack(); + static TAUnpack *instance; + void fixHeaderEndianness(TAPackageHeaderV2 *header); + unsigned int sizeWithoutPadding(const char* paddedData, + unsigned int paddedSize); +public: + static TAUnpack* getInstance(); + int unpackTA(string path, string uuid); + virtual ~TAUnpack(); +}; + +#endif /* TAUNPACK_H_ */ diff --git a/simulatordaemon/src/TABinaryManager/TestMain.cpp b/simulatordaemon/src/TABinaryManager/TestMain.cpp new file mode 100755 index 0000000..5497925 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/TestMain.cpp @@ -0,0 +1,80 @@ +/* + * TestMain.cpp + * + * Created on: 05-May-2015 + * Author: krishna + */ + +#include +#include +#include "TABinaryManager.h" +#include "TAManifest.h" +#include "TAUnpack.h" +#include "Config.h" +using namespace std; + +int test_main() { + int inp = 100; + std::cout << "[SIM_DAEMON] 0. Exit" << std::endl; + std::cout << "[SIM_DAEMON] 1. Unpack TA" << std::endl; + std::cout << "[SIM_DAEMON] 2. Process and display manifest" << std::endl; + std::cout << "[SIM_DAEMON] 3. Execute image" << std::endl; + cout + << "4. TA Binary Manager (Read UUID List, unpack all of the binaries, keep meta data ready)" + << std::endl; + + try { + while (inp != 0) { + std::cout << "[SIM_DAEMON] Enter Choice: " << std::endl; + + scanf("%d", &inp); + + switch (inp) { + // Unpack TA + case 1: { + TAUnpack *unpacker = TAUnpack::getInstance(); + unpacker->unpackTA(TA_STORE_PATH, "0000-0000-0000-0000000000c7"); + break; + } + // Manifest test + case 2: { + TAManifest manifest; + manifest.processXML( + string( + TA_STORE_PATH"0000-0000-0000-0000000000c7-ext/0000-0000-0000-0000000000c7.manifest")); + manifest.printProcessedData(); + break; + } + // Execute image + case 3: { + + break; + } + // Test TA Binary Manager + case 4: { + TABinaryManager *bm = TABinaryManager::getInstance(); + if (bm->initBinaryManager()) { + std::cout << "[SIM_DAEMON] Binary Manager successfully initialized" + << std::endl; + std::cout + << "[SIM_DAEMON] Image Path of 0000-0000-0000-0000000000c7: " + << bm->getImagePath("0000-0000-0000-0000000000c7") << std::endl; + std::cout + << "[SIM_DAEMON] Image Path of 0000-0000-0000-0000001234d5: " + << bm->getImagePath("0000-0000-0000-0000001234d5") << std::endl; + std::cout + << "[SIM_DAEMON] Image Path of 0000-0000-0000-0000004567c8: " + << bm->getImagePath("0000-0000-0000-0000004567c8") << std::endl; + bm->getManifest("0000-0000-0000-0000004567c8")->printProcessedData(); + + } + break; + } + + } + } + } catch (std::exception& e) { + LOGE(SIM_DAEMON, "Exception: %s", e.what()); + } + return 0; +} diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp new file mode 100755 index 0000000..e3e8981 --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml.hpp @@ -0,0 +1,2396 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) +#include // For std::size_t +#include // For assert +#include // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //!

+ //! This function cannot return. If it does, the results are undefined. + //!

+ //! A very simple definition might look like that: + //!

+	//! void %rapidxml::%parse_error_handler(const char *what, void *where)
+	//! {
+	//!     LOGD(SIM_DAEMON, "Parse error: %s", what);
+	//!     std::abort();
+	//! }
+	//! 
+ //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml { + +//! Parse error exception. +//! This exception is thrown by the parser when an error occurs. +//! Use what() function to get human-readable error message. +//! Use where() function to get a pointer to position within source text where error was detected. +//!

+//! If throwing exceptions by the parser is undesirable, +//! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. +//! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. +//! This function must be defined by the user. +//!

+//! This class derives from std::exception class. +class parse_error: + public std::exception { + +public: + + //! Constructs parse error + parse_error(const char *what, void *where) : + m_what(what), m_where(where) { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw () { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template + Ch *where() const { + return reinterpret_cast(m_where); + } + +private: + + const char *m_what; + void *m_where; + +}; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE +// Size of static memory block of memory_pool. +// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. +// No dynamic memory allocations are performed by memory_pool until static memory is exhausted. +#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE +// Size of dynamic memory block of memory_pool. +// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. +// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. +#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT +// Memory allocation alignment. +// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. +// All memory allocations for nodes, attributes and strings will be aligned to this value. +// This must be a power of 2 and at least 1, otherwise memory_pool will not work. +#define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml { +// Forward declarations +template class xml_node; +template class xml_attribute; +template class xml_document; + +//! Enumeration listing all node types produced by the parser. +//! Use xml_node::type() function to query node type. +enum node_type { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. +}; + +/////////////////////////////////////////////////////////////////////// +// Parsing flags + +//! Parse flag instructing the parser to not create data nodes. +//! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_data_nodes = 0x1; + +//! Parse flag instructing the parser to not use text of first data node as a value of parent element. +//! Can be combined with other flags by use of | operator. +//! Note that child data nodes of element node take precendence over its value when printing. +//! That is, if element has one or more child data nodes and a value, the value will be ignored. +//! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. +//!

+//! See xml_document::parse() function. +const int parse_no_element_values = 0x2; + +//! Parse flag instructing the parser to not place zero terminators after strings in the source text. +//! By default zero terminators are placed, modifying source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_string_terminators = 0x4; + +//! Parse flag instructing the parser to not translate entities in the source text. +//! By default entities are translated, modifying source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_entity_translation = 0x8; + +//! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. +//! By default, UTF-8 handling is enabled. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_utf8 = 0x10; + +//! Parse flag instructing the parser to create XML declaration node. +//! By default, declaration node is not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_declaration_node = 0x20; + +//! Parse flag instructing the parser to create comments nodes. +//! By default, comment nodes are not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_comment_nodes = 0x40; + +//! Parse flag instructing the parser to create DOCTYPE node. +//! By default, doctype node is not created. +//! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_doctype_node = 0x80; + +//! Parse flag instructing the parser to create PI nodes. +//! By default, PI nodes are not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_pi_nodes = 0x100; + +//! Parse flag instructing the parser to validate closing tag names. +//! If not set, name inside closing tag is irrelevant to the parser. +//! By default, closing tags are not validated. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_validate_closing_tags = 0x200; + +//! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. +//! By default, whitespace is not trimmed. +//! This flag does not cause the parser to modify source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_trim_whitespace = 0x400; + +//! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. +//! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. +//! By default, whitespace is not normalized. +//! If this flag is specified, source text will be modified. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_normalize_whitespace = 0x800; + +// Compound flags + +//! Parse flags which represent default behaviour of the parser. +//! This is always equal to 0, so that all other flags can be simply ored together. +//! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. +//! This also means that meaning of each flag is a negation of the default setting. +//! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, +//! and using the flag will disable it. +//!

+//! See xml_document::parse() function. +const int parse_default = 0; + +//! A combination of parse flags that forbids any modifications of the source text. +//! This also results in faster parsing. However, note that the following will occur: +//!
    +//!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • +//!
  • entities will not be translated
  • +//!
  • whitespace will not be normalized
  • +//!
+//! See xml_document::parse() function. +const int parse_non_destructive = parse_no_string_terminators + | parse_no_entity_translation; + +//! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. +//!

+//! See xml_document::parse() function. +const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + +//! A combination of parse flags resulting in largest amount of data being extracted. +//! This usually results in slowest parsing. +//!

+//! See xml_document::parse() function. +const int parse_full = parse_declaration_node | parse_comment_nodes + | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + +/////////////////////////////////////////////////////////////////////// +// Internals + +//! \cond internal +namespace internal { + +// Struct that contains lookup tables for the parser +// It must be a template to allow correct linking (because it has static data members, which are defined in a header file). +template +struct lookup_tables { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters +}; + +// Find length of the string +template +inline std::size_t measure(const Ch *p) { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; +} + +// Compare strings for equality +template +inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, + std::size_t size2, bool case_sensitive) { + if (size1 != size2) return false; + if (case_sensitive) { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) return false; + } else { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] + != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) + return false; + } + return true; +} +} +//! \endcond + +/////////////////////////////////////////////////////////////////////// +// Memory pool + +//! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. +//! In most cases, you will not need to use this class directly. +//! However, if you need to create nodes manually or modify names/values of nodes, +//! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. +//! Not only is this faster than allocating them by using new operator, +//! but also their lifetime will be tied to the lifetime of document, +//! possibly simplyfing memory management. +//!

+//! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. +//! You can also call allocate_string() function to allocate strings. +//! Such strings can then be used as names or values of nodes without worrying about their lifetime. +//! Note that there is no free() function -- all allocations are freed at once when clear() function is called, +//! or when the pool is destroyed. +//!

+//! It is also possible to create a standalone memory_pool, and use it +//! to allocate nodes, whose lifetime will not be tied to any document. +//!

+//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. +//! Until static memory is exhausted, no dynamic memory allocations are done. +//! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, +//! by using global new[] and delete[] operators. +//! This behaviour can be changed by setting custom allocation routines. +//! Use set_allocator() function to set them. +//!

+//! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. +//! This value defaults to the size of pointer on target architecture. +//!

+//! To obtain absolutely top performance from the parser, +//! it is important that all nodes are allocated from a single, contiguous block of memory. +//! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. +//! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT +//! to obtain best wasted memory to performance compromise. +//! To do it, define their values before rapidxml.hpp file is included. +//! \param Ch Character type of created nodes. +template +class memory_pool { + +public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() : + m_alloc_func(0), m_free_func(0) { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node *allocate_node(node_type type, const Ch *name = 0, + const Ch *value = 0, std::size_t name_size = 0, + std::size_t value_size = 0) { + void *memory = allocate_aligned(sizeof(xml_node )); + xml_node *node = new (memory) xml_node(type); + if (name) { + if (name_size > 0) + node->name(name, name_size); + else node->name(name); + } + if (value) { + if (value_size > 0) + node->value(value, value_size); + else node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) { + void *memory = allocate_aligned(sizeof(xml_attribute )); + xml_attribute *attribute = new (memory) xml_attribute; + if (name) { + if (name_size > 0) + attribute->name(name, name_size); + else attribute->name(name); + } + if (value) { + if (value_size > 0) + attribute->value(value, value_size); + else attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) size = internal::measure(source) + 1; + Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); + if (source) for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node *clone_node(const xml_node *source, + xml_node *result = 0) { + // Prepare result node + if (result) { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } else result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node *child = source->first_node(); child; + child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute *attr = source->first_attribute(); attr; + attr = attr->next_attribute()) + result->append_attribute( + allocate_attribute(attr->name(), attr->value(), attr->name_size(), + attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() { + while (m_begin != m_static_memory) { + char *previous_begin = reinterpret_cast
(align(m_begin)) + ->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use longjmp() function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //!

+ //! User defined allocation functions must have the following forms: + //!
+ //!
void *allocate(std::size_t size); + //!
void free(void *pointer); + //!

+ //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + +private: + + struct header { + char *previous_begin; + }; + + void init() { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) { + std::size_t alignment = ((RAPIDXML_ALIGNMENT + - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) + & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } else { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast(memory); + } + + void *allocate_aligned(std::size_t size) { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast
(pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used +}; + +/////////////////////////////////////////////////////////////////////////// +// XML base + +//! Base class for xml_node and xml_attribute implementing common functions: +//! name(), name_size(), value(), value_size() and parent(). +//! \param Ch Character type to use +template +class xml_base { + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() : + m_name(0), m_value(0), m_parent(0) { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) { + m_name = const_cast(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //!

+ //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) { + m_value = const_cast(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node *parent() const { + return m_parent; + } + +protected: + + // Return empty string + static Ch *nullstr() { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node *m_parent; // Pointer to parent node, or 0 if none + +}; + +//! Class representing attribute node of XML document. +//! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). +//! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. +//! Thus, this text must persist in memory for the lifetime of attribute. +//! \param Ch Character type to use. +template +class xml_attribute: + public xml_base { + + friend class xml_node ; + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document *document() const { + if (xml_node *node = this->parent()) { + while (node->parent()) + node = node->parent(); + return + node->type() == node_document ? + static_cast *>(node) : 0; + } else return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *previous_attribute(const Ch *name = 0, + std::size_t name_size = 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_prev_attribute; attribute; + attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_next_attribute; attribute; + attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return this->m_parent ? m_next_attribute : 0; + } + +private: + + xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + +}; + +/////////////////////////////////////////////////////////////////////////// +// XML node + +//! Class representing a node of XML document. +//! Each node may have associated name and value strings, which are available through name() and value() functions. +//! Interpretation of name and value depends on type of the node. +//! Type of node can be determined by using type() function. +//!

+//! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. +//! Thus, this text must persist in the memory for the lifetime of node. +//! \param Ch Character type to use. +template +class xml_node: + public xml_base { + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) : + m_type(type), m_first_node(0), m_first_attribute(0) { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document *document() const { + xml_node *node = const_cast *>(this); + while (node->parent()) + node = node->parent(); + return + node->type() == node_document ? static_cast *>(node) : + 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *child = m_first_node; child; + child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, + name_size, case_sensitive)) return child; + return 0; + } else return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *child = m_last_node; child; + child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, + name_size, case_sensitive)) return child; + return 0; + } else return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *sibling = m_prev_sibling; sibling; + sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, + name_size, case_sensitive)) return sibling; + return 0; + } else return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *sibling = m_next_sibling; sibling; + sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, + name_size, case_sensitive)) return sibling; + return 0; + } else return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_first_attribute; attribute; + attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_last_attribute; attribute; + attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node *child) { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } else { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node *child) { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } else { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node *where, xml_node *child) { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() { + assert(first_node()); + xml_node *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() { + assert(first_node()); + xml_node *child = m_last_node; + if (child->m_prev_sibling) { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } else m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node *where) { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() { + for (xml_node *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute *attribute) { + assert(attribute && !attribute->parent()); + if (first_attribute()) { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } else { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute *attribute) { + assert(attribute && !attribute->parent()); + if (first_attribute()) { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } else { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute *where, + xml_attribute *attribute) { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() { + assert(first_attribute()); + xml_attribute *attribute = m_first_attribute; + if (attribute->m_next_attribute) { + attribute->m_next_attribute->m_prev_attribute = 0; + } else m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() { + assert(first_attribute()); + xml_attribute *attribute = m_last_attribute; + if (attribute->m_prev_attribute) { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } else m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute *where) { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() { + for (xml_attribute *attribute = first_attribute(); attribute; + attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + +private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + +}; + +/////////////////////////////////////////////////////////////////////////// +// XML document + +//! This class represents root of the DOM hierarchy. +//! It is also an xml_node and a memory_pool through public inheritance. +//! Use parse() function to build a DOM tree from a zero-terminated XML text string. +//! parse() function allocates memory for nodes and attributes by using functions of xml_document, +//! which are inherited from memory_pool. +//! To access root node of the document, use the document itself, as if it was an xml_node. +//! \param Ch Character type to use. +template +class xml_document: + public xml_node, public memory_pool { + +public: + + //! Constructs empty XML document + xml_document() : + xml_node(node_document) { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //!

+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //!

+ //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template + void parse(Ch *text) { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom(text); + + // Parse children + while (1) { + // Skip whitespace before node + skip(text); + if (*text == 0) break; + + // Parse and append new child + if (*text == Ch('<')) { + ++text; // Skip '<' + if (xml_node *node = parse_node(text)) + this->append_node(node); + } else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool::clear(); + } + +private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + } + }; + + // Detect node name character + struct node_name_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + } + }; + + // Detect attribute value character + template + struct attribute_value_pred { + static unsigned char test(Ch ch) { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template + struct attribute_value_pure_pred { + static unsigned char test(Ch ch) { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template + static void insert_coded_character(Ch *&text, unsigned long code) { + if (Flags & parse_no_utf8) { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast(code); + text += 1; + } else { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + text += 1; + } else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xC0); + text += 2; + } else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xE0); + text += 3; + } else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xF0); + text += 4; + } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template + static void skip(Ch *&text) { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template + static Ch *skip_and_expand_character_refs(Ch *&text) { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation + && !(Flags & parse_normalize_whitespace) + && !(Flags & parse_trim_whitespace)) { + skip(text); + return text; + } + + // Use simple skip until first modification is detected + skip(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) { + // Test if replacement is needed + if (src[0] == Ch('&')) { + switch (src[1]) { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') + && src[5] == Ch(';')) { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') + && src[5] == Ch(';')) { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) { + unsigned char digit = + internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) break; + code = code * 16 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } else { + unsigned long code = 0; + src += 2; // Skip &# + while (1) { + unsigned char digit = + internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) break; + code = code * 10 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) { + // Test if condensing is needed + if (whitespace_pred::test(*src)) { + *dest = Ch(' '); + ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template + void parse_bom(Ch *&text) { + // UTF-8? + if (static_cast(text[0]) == 0xEF + && static_cast(text[1]) == 0xBB + && static_cast(text[2]) == 0xBF) { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration ( + xml_node *parse_xml_declaration(Ch *&text) { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip(text); + + // Parse declaration attributes + parse_node_attributes(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template + xml_node *parse_doctype(Ch *&text) { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) { + // Determine character type + switch (*text) { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) { + switch (*text) { + case Ch('['): + ++depth; + break; + case Ch(']'): + --depth; + break; + case 0: + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) { + // Create a new doctype node + xml_node *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } else { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template + xml_node *parse_pi(Ch *&text) { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) { + // Create pi node + xml_node *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } else { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template + Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs(text); + else end = skip_and_expand_character_refs(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) { + if (Flags & parse_normalize_whitespace) { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) --end; + } else { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) { + xml_node *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template + xml_node *parse_cdata(Ch *&text) { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template + xml_node *parse_element(Ch *&text) { + // Create element node + xml_node *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip(text); + + // Parse attributes, if any + parse_node_attributes(text, element); + + // Determine ending type + if (*text == Ch('>')) { + ++text; + parse_node_contents(text, element); + } else if (*text == Ch('/')) { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template + xml_node *parse_node(Ch *&text) { + // Parse proper node type + switch (text[0]) { + + // <... + default: + // Parse and append element node + return parse_element(text); + + // (text); + } else { + // Parse PI + return parse_pi(text); + } + + // (text); + } + break; + + // (text); + } + break; + + // (text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with ')) { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template + void parse_node_contents(Ch *&text, xml_node *node) { + // For all children and text + while (1) { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) { + // Node closing + text += 2; // Skip '(text); + if (!internal::compare(node->name(), node->name_size(), + closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } else { + // No validation, just skip name + skip(text); + } + // Skip remaining whitespace after node name + skip(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } else { + // Child node + ++text; // Skip '<' + if (xml_node *child = parse_node(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data(node, text, contents_start); + goto after_data_node; + // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template + void parse_node_attributes(Ch *&text, xml_node *node) { + // For all attributes + while (attribute_name_pred::test(*text)) { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs, + attribute_value_pure_pred, AttFlags>(text); + else end = skip_and_expand_character_refs, + attribute_value_pure_pred, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip(text); + } + } + +}; + +//! \cond internal +namespace internal { + +// Whitespace (space \n \r \t) +template +const unsigned char lookup_tables::lookup_whitespace[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + +// Node name (anything but space \n \r \t / > ? \0) +template +const unsigned char lookup_tables::lookup_node_name[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) (anything but < \0) +template +const unsigned char lookup_tables::lookup_text[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled +// (anything but < \0 &) +template +const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled +// (anything but < \0 & space \n \r \t) +template +const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute name (anything but space \n \r \t / < > = ? ! \0) +template +const unsigned char lookup_tables::lookup_attribute_name[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with single quote (anything but ' \0) +template +const unsigned char lookup_tables::lookup_attribute_data_1[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with single quote that does not require processing (anything but ' \0 &) +template +const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with double quote (anything but " \0) +template +const unsigned char lookup_tables::lookup_attribute_data_2[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with double quote that does not require processing (anything but " \0 &) +template +const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Digits (dec and hex, 255 denotes end of numeric character reference) +template +const unsigned char lookup_tables::lookup_digits[256] = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 0 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 1 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, + 255, // 3 + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 4 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 5 + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 6 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 7 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 8 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 9 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // A + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // B + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // C + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // D + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // E + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255 // F + }; + +// Upper case conversion +template +const unsigned char lookup_tables::lookup_upcase[256] = { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, + 127, // 7 + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, // 8 + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, // 9 + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, // A + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, // B + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, // C + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, // D + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, // E + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 // F + }; +} +//! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_iterators.hpp b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_iterators.hpp new file mode 100755 index 0000000..478609a --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_iterators.hpp @@ -0,0 +1,151 @@ +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include "rapidxml.hpp" + +namespace rapidxml { + +//! Iterator of child nodes of xml_node +template +class node_iterator { + +public: + + typedef typename xml_node value_type; + typedef typename xml_node &reference; + typedef typename xml_node *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + node_iterator() : + m_node(0) { + } + + node_iterator(xml_node *node) : + m_node(node->first_node()) { + } + + reference operator *() const { + assert(m_node); + return *m_node; + } + + pointer operator->() const { + assert(m_node); + return m_node; + } + + node_iterator& operator++() { + assert(m_node); + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) { + node_iterator tmp = *this; + ++this; + return tmp; + } + + node_iterator& operator--() { + assert(m_node && m_node->previous_sibling()); + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) { + node_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const node_iterator &rhs) { + return m_node == rhs.m_node; + } + + bool operator !=(const node_iterator &rhs) { + return m_node != rhs.m_node; + } + +private: + + xml_node *m_node; + +}; + +//! Iterator of child attributes of xml_node +template +class attribute_iterator { + +public: + + typedef typename xml_attribute value_type; + typedef typename xml_attribute &reference; + typedef typename xml_attribute *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + attribute_iterator() : + m_attribute(0) { + } + + attribute_iterator(xml_node *node) : + m_attribute(node->first_attribute()) { + } + + reference operator *() const { + assert(m_attribute); + return *m_attribute; + } + + pointer operator->() const { + assert(m_attribute); + return m_attribute; + } + + attribute_iterator& operator++() { + assert(m_attribute); + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + attribute_iterator& operator--() { + assert(m_attribute && m_attribute->previous_attribute()); + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const attribute_iterator &rhs) { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator &rhs) { + return m_attribute != rhs.m_attribute; + } + +private: + + xml_attribute *m_attribute; + +}; + +} + +#endif diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_print.hpp b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_print.hpp new file mode 100755 index 0000000..8cc696f --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_print.hpp @@ -0,0 +1,426 @@ +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include "rapidxml.hpp" + +// Only include streams if not disabled +#ifndef RAPIDXML_NO_STREAMS +#include +#include +#endif + +namespace rapidxml { + +/////////////////////////////////////////////////////////////////////// +// Printing flags + +const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + +/////////////////////////////////////////////////////////////////////// +// Internal + +//! \cond internal +namespace internal { + +/////////////////////////////////////////////////////////////////////////// +// Internal character operations + +// Copy characters from given range to given output iterator +template +inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) { + while (begin != end) + *out++ = *begin++; + return out; +} + +// Copy characters from given range to given output iterator and expand +// characters into references (< > ' " &) +template +inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, + OutIt out) { + while (begin != end) { + if (*begin == noexpand) { + *out++ = *begin; // No expansion, copy character + } else { + switch (*begin) { + case Ch('<'): + *out++ = Ch('&'); + *out++ = Ch('l'); + *out++ = Ch('t'); + *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); + *out++ = Ch('g'); + *out++ = Ch('t'); + *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); + *out++ = Ch('a'); + *out++ = Ch('p'); + *out++ = Ch('o'); + *out++ = Ch('s'); + *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); + *out++ = Ch('q'); + *out++ = Ch('u'); + *out++ = Ch('o'); + *out++ = Ch('t'); + *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); + *out++ = Ch('a'); + *out++ = Ch('m'); + *out++ = Ch('p'); + *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; +} + +// Fill given output iterator with repetitions of the same character +template +inline OutIt fill_chars(OutIt out, int n, Ch ch) { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; +} + +// Find character +template +inline bool find_char(const Ch *begin, const Ch *end) { + while (begin != end) + if (*begin++ == ch) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////// +// Internal printing operations + +// Print node +template +inline OutIt print_node(OutIt out, const xml_node *node, int flags, + int indent) { + // Print proper node type + switch (node->type()) { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; + + // Return modified iterator + return out; +} + +// Print children of the node +template +inline OutIt print_children(OutIt out, const xml_node *node, int flags, + int indent) { + for (xml_node *child = node->first_node(); child; + child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; +} + +// Print attributes of the node +template +inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) { + for (xml_attribute *attribute = node->first_attribute(); attribute; + attribute = attribute->next_attribute()) { + if (attribute->name() && attribute->value()) { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), + attribute->name() + attribute->name_size(), out); + *out = Ch('='), ++out; + // Print attribute value using appropriate quote type + if (find_char(attribute->value(), + attribute->value() + attribute->value_size())) { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), + attribute->value() + attribute->value_size(), Ch('"'), out); + *out = Ch('\''), ++out; + } else { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), + attribute->value() + attribute->value_size(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + return out; +} + +// Print data node +template +inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_data); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), + Ch(0), out); + return out; +} + +// Print data node +template +inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_cdata); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); + ++out; + *out = Ch('!'); + ++out; + *out = Ch('['); + ++out; + *out = Ch('C'); + ++out; + *out = Ch('D'); + ++out; + *out = Ch('A'); + ++out; + *out = Ch('T'); + ++out; + *out = Ch('A'); + ++out; + *out = Ch('['); + ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch(']'); + ++out; + *out = Ch(']'); + ++out; + *out = Ch('>'); + ++out; + return out; +} + +// Print element node +template +inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value_size() == 0 && !node->first_node()) { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } else { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // Test if node contains a single data node only (and no other nodes) + xml_node *child = node->first_node(); + if (!child) { + // If node has no children, only print its value without indenting + out = copy_and_expand_chars(node->value(), + node->value() + node->value_size(), Ch(0), out); + } else if (child->next_sibling() == 0 && child->type() == node_data) { + // If node has a sole data child, only print its value without indenting + out = copy_and_expand_chars(child->value(), + child->value() + child->value_size(), Ch(0), out); + } else { + // Print all children with full indenting + if (!(flags & print_no_indenting)) *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch('>'), ++out; + } + return out; +} + +// Print declaration node +template +inline OutIt print_declaration_node(OutIt out, const xml_node *node, + int flags, int indent) { + // Print declaration start + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; +} + +// Print comment node +template +inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_comment); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; +} + +// Print doctype node +template +inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_doctype); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('>'), ++out; + return out; +} + +// Print pi node +template +inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, + int indent) { + assert(node->type() == node_pi); + if (!(flags & print_no_indenting)) out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; +} + +} +//! \endcond + +/////////////////////////////////////////////////////////////////////////// +// Printing + +//! Prints XML to given output iterator. +//! \param out Output iterator to print to. +//! \param node Node to be printed. Pass xml_document to print entire document. +//! \param flags Flags controlling how XML is printed. +//! \return Output iterator pointing to position immediately after last character of printed text. +template +inline OutIt print(OutIt out, const xml_node &node, int flags = 0) { + return internal::print_node(out, &node, flags, 0); +} + +#ifndef RAPIDXML_NO_STREAMS + +//! Prints XML to given output stream. +//! \param out Output stream to print to. +//! \param node Node to be printed. Pass xml_document to print entire document. +//! \param flags Flags controlling how XML is printed. +//! \return Output stream. +template +inline std::basic_ostream &print(std::basic_ostream &out, + const xml_node &node, int flags = 0) { + print(std::ostream_iterator < Ch > (out), node, flags); + return out; +} + +//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. +//! \param out Output stream to print to. +//! \param node Node to be printed. +//! \return Output stream. +template +inline std::basic_ostream &operator <<(std::basic_ostream &out, + const xml_node &node) { + return print(out, node); +} + +#endif + +} + +#endif diff --git a/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_utils.hpp b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_utils.hpp new file mode 100755 index 0000000..53fe0de --- /dev/null +++ b/simulatordaemon/src/TABinaryManager/rapidxml/rapidxml_utils.hpp @@ -0,0 +1,111 @@ +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include "rapidxml.hpp" +#include +#include +#include +#include + +namespace rapidxml { + +//! Represents data loaded from a file +template +class file { + +public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) { + using namespace std; + + // Open stream + basic_ifstream stream(filename, ios::binary); + if (!stream) throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream &stream) { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator < Ch > (stream), + istreambuf_iterator()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const { + return m_data.size(); + } + +private: + + std::vector m_data; // File data + +}; + +//! Counts children of node. Time complexity is O(n). +//! \return Number of children of node +template +inline std::size_t count_children(xml_node *node) { + xml_node *child = node->first_node(); + std::size_t count = 0; + while (child) { + ++count; + child = child->next_sibling(); + } + return count; +} + +//! Counts attributes of node. Time complexity is O(n). +//! \return Number of attributes of node +template +inline std::size_t count_attributes(xml_node *node) { + xml_attribute *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) { + ++count; + attr = attr->next_attribute(); + } + return count; +} + +} + +#endif diff --git a/simulatordaemon/src/TAFactory.cpp b/simulatordaemon/src/TAFactory.cpp new file mode 100755 index 0000000..2572bd8 --- /dev/null +++ b/simulatordaemon/src/TAFactory.cpp @@ -0,0 +1,440 @@ +/* + * ===================================================================================== + * + * Filename: TAFactory.cpp + * + * Description: TAFactory class + * + * Version: 1.0 + * Created: 28 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TAFactory.h" +#include "ResponseCommands/ResMakeCommand.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +// instLock for TA Factory instance +pthread_mutex_t instLock; +// Initialize TA Factory instance as NULL +TAFactory *TAFactory::instance = NULL; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * TAFactory constructer. TA Factory Instance is created + */ +TAFactory::TAFactory() { + // Starting value for TA Instance ID set to 101 + InstID = 101; + + /* Initialize the lock for TA Instance Map (mTAInstanceMap), instance ID + * (instID) and TA Factory instance (instance) + */ + pthread_rwlock_init(&mTAInstanceMapLock, NULL); + pthread_rwlock_init(&instIDLock, NULL); + pthread_mutex_init(&instLock, NULL); +} + +/** + * Get TA Factory Instance. If called for first time then create a TA Factory + * instance and return the instance else return the already created instance. + */ +TAFactory* TAFactory::getInstance() { + + LOGD(SIM_DAEMON, "Entry"); + pthread_mutex_lock(&instLock); + bool result; + + // Check if the instance is not yet craeted + if (NULL == instance) { + // Create a new instance of TA Binary Manager + TABinaryManager *TABin = TABinaryManager::getInstance(); + // Initialize TA Binary Manager + result = TABin->initBinaryManager(); + if (true != result) { + LOGD(SIM_DAEMON, "initBinaryManager FAILED"); + pthread_mutex_unlock(&instLock); + return instance; + } + // Create a new instance of TA Factory + instance = new TAFactory(); + } + pthread_mutex_unlock(&instLock); + return instance; +} + +/** + * Get a TA Instance for the UUID sent as the argument + * @param uuid TEEC_UUID for the TA instance to be returned + * @param session Session which requested the TA Instance to be associated + * with it + */ +TAInstancePtr TAFactory::getTAInstance(TEEC_UUID uuid, ISession* session) { + + TAInstancePtr TAInst; + bool result; + LOGD(SIM_DAEMON, "Entry"); + + // Get TA Binary Manager instance + TABinaryManager *TABin = TABinaryManager::getInstance(); + // Get TEEC_UUID format uuid converted to string form + string TAUUID = TABin->getUUIDAsString(uuid); + + // Change to upper char. TA list has upper char. + locale loc; + for (size_t i=0; iisSingleInstance(TAUUID, result) == 0) && (result == false))) { + /* TA instance is not already alive or is Multi Instance, Create a new TA + * Instance + */ + TAInst = createUninitalizedTAInstance(TAUUID, session); + if (!TAInst == true) { + LOGE(SIM_DAEMON, "Creating Trusted Application Instance FAILED"); + return TAInstancePtr(); + } + } else if ((TABin->isSingleInstance(TAUUID, result) == 0) + && (result == true)) { + // TA is Single Instance and alive + if (TABin->isMultipleSession(TAUUID, result) < 0) { + LOGE(SIM_DAEMON, "TA not in list"); + return TAInstancePtr(); + } else { + multimap::iterator it; + // Find alive TA Instance in TA Factory's Instance Map + it = mTAInstanceMap.find(TAUUID); + if (it != mTAInstanceMap.end()) { + TAInst = it->second; + TAInst->takeSessionMapLock(); + if ((result == true) + || ((result == false) && (it->second->getSessionMapSize() == 0))) { + /* TA is alive Single Instance and either it is MultiSession or + * has no session associated to it + */ + + if (!TAInst == true) { + LOGE(SIM_DAEMON, "Creating Trusted Application Instance FAILED"); + TAInst->releaseSessionMapLock(); + return TAInstancePtr(); + } + TAInst->releaseSessionMapLock(); + } else { + LOGE(SIM_DAEMON, "TA Single Instance Single Session - " + "multiple connections not supported"); + TAInst->releaseSessionMapLock(); + return TAInstancePtr(); + } + } else { + LOGE(SIM_DAEMON, "Trusted Application Instance not found."); + return TAInstancePtr(); + } + } + } else { + LOGE(SIM_DAEMON, "TA not in list"); + return TAInstancePtr(); + } + TAInst->takeSessionMapLock(); + // Add session to the Session Map of TA Instance + TAInst->insertSessionMap(session); + TAInst->releaseSessionMapLock(); + return TAInst; +} + +/** + * Check if TA already alive. Return true if it is present in the TA Instance + * Map else return false + * @param TAUUID TA UUID in string form + */ +bool TAFactory::checkIfTARunning(string TAUUID) { + + LOGD(SIM_DAEMON, "Entry"); + bool result = false; + + // Find TA UUID in the TA Instance Map + multimap::iterator itr; + itr = mTAInstanceMap.find(TAUUID); + if (itr != mTAInstanceMap.end()) result = true; + return result; +} + +/** + * Create a new TA Instance by launching the TA specified by TA UUID + * @param TAUUID TA UUID in string form + * @param session Session which requested the TA Instance to be associated + * with it + */ +TAInstancePtr TAFactory::createUninitalizedTAInstance(string TAUUID, + ISession* session) { + + LOGD(SIM_DAEMON, "Entry"); + + // Initialize PID to -1 + pid_t pid = -1; + // Set default values for TA configuration variables + bool debug = false; + bool alive = false; + bool singleInst = false; + TEEC_Result result = TEEC_ERROR_COMMUNICATION; + + TABinaryManager *TABin = TABinaryManager::getInstance(); + pthread_rwlock_wrlock(&instIDLock); + + /* Generate the endpoint name using UUID and Instance ID to be sent to + * TEEStub for socket connection + */ + std::stringstream str; + str << TAUUID << "-"; + str << InstID; + + if (launchTA(TAUUID, str, debug, pid)) { + // TA is launched successfully, Create a new instance of TAInstance class + + /* Check if TA is to be keep alive and accordingly set TAInstance's + * member variable isKeepAlive + */ + if (TABin->isSingleInstance(TAUUID, singleInst) < 0) { + LOGE(SIM_DAEMON, "TA not in list"); + pthread_rwlock_unlock(&instIDLock); + return TAInstancePtr(); + } else if (singleInst == true) { + /* If TA is single Instance and KeepAlive then set TAInstance's member + * variable isKeepAlive to true. + * Even if TA is KeepAlive but MultiInstance, set TAInstance's member + * variable isKeepAlive to false. + */ + if (TABin->isKeepAlive(TAUUID, alive) < 0) { + LOGE(SIM_DAEMON, "TA not in list"); + // Kill the launched TA + if (pid > 0) { + kill(pid, SIGKILL); + while (kill(pid, 0) != -1); + LOGD(SIM_DAEMON, "TA process exited"); + } + pthread_rwlock_unlock(&instIDLock); + return TAInstancePtr(); + } + } + + /* Update TAInstance's member variable isDebug according to the property + * set in manifest file for TA + * Update TAInstance's member variable mTAInstanceID with the assigned + * Instance ID + */ + + // Update TAInstance member variable mPID with the launched TA PID + TAInstancePtr TAInst; + TAInst = TAInstancePtr(new TAInstance(pid, alive, debug, InstID, ioService::getInstance())); + // Increment the Instance ID variable for assigning to next TA Instance + InstID++; + if (TEEC_SUCCESS != TAInst->connecttoTA(str)) { + LOGE(SIM_DAEMON, "Connection to TA FAILED"); + TAInst->killTA(); + pthread_rwlock_unlock(&instIDLock); + return TAInstancePtr(); + } + // Connected to TA through socket + + /* Check if TAInstance is newly created or an old instance is being re-used. + * If new instance then send CREATE command to the TA. + * TaInstance member variable isCreated is used to find if the TAInstance is + * newly created or re-used. + */ + if (TAInst->getCreated() == false) { + /* TA is launched uninitialised and CreateTAEntryPoint has not been + * called yet for this TA Instance, send request for CreateTAEntryPoint + */ + CreateTAEntryPointData cdata; + memset(&cdata, 0, sizeof(CreateTAEntryPointData)); + cdata.sessionID = session->getSessionID(); + cdata.returnValue = TEE_ERROR_GENERIC; + + // Send CREATE command to TA + result = TAInst->sendRequestToTA(CREATE, (void*)&cdata, + sizeof(CreateTAEntryPointData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Create sendRequestToTA FAILED\n"); + // Kill the launched TA + TAInst->killTA(); + pthread_rwlock_unlock(&instIDLock); + return TAInstancePtr(); + } + } + pthread_rwlock_unlock(&instIDLock); + + // Add the TAInstance in the TA Factory's TA Instance Map + mTAInstanceMap.insert(pair(TAUUID, TAInst)); + return TAInst; + } + pthread_rwlock_unlock(&instIDLock); + return TAInstancePtr(); +} + +/** + * Thread routine for handling TA exit (immature/mature exit) + * @param pid pointer to the PID of the launched TA + */ +void* TAFactory::waitForChild(void *pid) { + + pid_t PID = *(pid_t*)pid; + int32_t childStatus; + + // Wait for PID to exit + waitpid(PID, &childStatus, 0); + LOGD(SIM_DAEMON, "PID %d exited", PID); + if (instance != NULL) { + // Clean (handle immature termination of) TA + instance->cleanupTAInstance(PID); + } + return NULL; +} + +/** + * Clean (handle immature termination of) TA by sending response for all the + * pending commands for the TA and deleting the TA instance + * @param pid pointer to the PID of the exited TA + */ +void TAFactory::cleanupTAInstance(pid_t PID) { + + LOGD(SIM_DAEMON, "Entry"); + TAInstancePtr Inst; + + // Find the TA instance associated with the argument PID + multimap::iterator itInstanceMap; + for (itInstanceMap = mTAInstanceMap.begin(); + itInstanceMap != mTAInstanceMap.end(); itInstanceMap++) { + if (itInstanceMap->second->getPID() == PID) { + Inst = itInstanceMap->second; + break; + } + } + + if (!Inst == false) { + /* TA instance is found for the PID argument. + * Check if there are any commands pending for TA response and send the + * failure response back to CA if the response is pending and TA has exited + */ + Inst->cleanup(); + // Remove the TA Instance from the TA Instance Map maintained in TA Factory + pthread_rwlock_wrlock(&mTAInstanceMapLock); + multimap::iterator itMap; + for (itMap = mTAInstanceMap.begin(); itMap != mTAInstanceMap.end(); + ++itMap) { + if (itMap->second == Inst) { + mTAInstanceMap.erase(itMap); + break; + } + } + pthread_rwlock_unlock(&mTAInstanceMapLock); + } +} + +/** + * Launch the TA instance + * @param TAUUID TA UUID is string format + * @param str string containing the endpoint name to be passed as an argument + * to TA while launching + * @param debug debug flag + * @param pid PID to be update for launched TA + */ +bool TAFactory::launchTA(string TAUUID, std::stringstream& str, bool debug, + pid_t& pid) { + + int32_t result = -1; + pthread_t thread; + LOGD(SIM_DAEMON, "Entry"); + + // Get TABinaryManager instance + TABinaryManager *TABin = TABinaryManager::getInstance(); + // Get TA Image path for launching + string argvPath = TABin->getImagePath(TAUUID); + if ("" == argvPath) { + LOGE(SIM_DAEMON, "Trusted Application does not exist"); + return false; + } + char *envp[1]; + + // Argument to be passed to TA main (TEEStub main) + string argvName = str.str().c_str(); + + // Get the port to be assigned to TA if TA is to be launched in debug mode + string argvPort = TABin->getPort(TAUUID); + + pthread_mutex_lock(&TABin->taLock); + //Check if the TA is to be launched in debug mode or release mode + if (argvPort != "") { // DEBUG MODE + debug = true; + char *argv[5]; + string argvGDB = "/usr/bin/gdbserver"; + string argvHost = "localhost:" + argvPort; + + argv[0] = &argvGDB[0]; + argv[1] = &argvHost[0]; + argv[2] = &argvPath[0]; + argv[3] = &argvName[0]; + argv[4] = NULL; + + // fork TA with GDB + pid = fork(); + if (0 == pid) { + LOGD(SIM_DAEMON, "In Child Process"); + execv(argv[0], argv); + LOGE(SIM_DAEMON, "Launching Trusted Application FAILED"); + pthread_mutex_unlock(&TABin->taLock); + return false; + } + LOGD(SIM_DAEMON, "In Parent Process"); + } else { //RELEASE MODE + char *argv[3]; + argv[0] = &argvPath[0]; + argv[1] = &argvName[0]; + argv[2] = NULL; + envp[0] = NULL; + + // Spawn TA + result = posix_spawn(&pid, argv[0], NULL, NULL, argv, envp); + if (result == 0) { + LOGD(SIM_DAEMON, "TA pid: %i\n", pid); + LOGD(SIM_DAEMON, "Launched Trusted Application"); + } else { + LOGE(SIM_DAEMON, "Launching Trusted Application FAILED"); + pthread_mutex_unlock(&TABin->taLock); + return false; + } + } + pthread_mutex_unlock(&TABin->taLock); + // Create a thread to wait for TA exit + pthread_attr_t attr; + int s = pthread_attr_init(&attr); + if (s != 0) + LOGE(SIM_DAEMON, "pthread_attr_init"); + s = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (s != 0) + LOGE(SIM_DAEMON, "pthread_attr_setdetachstate"); + pthread_create(&thread, &attr, TAFactory::waitForChild, (void *)&pid); + return true; +} + +TAFactory::~TAFactory() { + /* Destroy the locks created for TAInstance map (mTAInstanceMap), Instance + * Id (InstID) and TA Factory Instance (instance) + */ + pthread_rwlock_destroy(&mTAInstanceMapLock); + pthread_rwlock_destroy(&instIDLock); + pthread_mutex_destroy(&instLock); +} diff --git a/simulatordaemon/src/TAInstance.cpp b/simulatordaemon/src/TAInstance.cpp new file mode 100755 index 0000000..f8733a7 --- /dev/null +++ b/simulatordaemon/src/TAInstance.cpp @@ -0,0 +1,444 @@ +/* + * ===================================================================================== + * + * Filename: TAInstance.cpp + * + * Description: TAInstance class + * + * Version: 1.0 + * Created: 28 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TAInstance.h" +#include "ResponseCommands/ResMakeCommand.h" + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * TAInstance constructer. TA Instance is created for each launched TA instance + * @param client_io_service IO service to handle the connection with TA + */ +TAInstance::TAInstance(uint32_t pid, bool alive, bool debug, uint32_t InstID, boost::asio::io_service& client_io_service) : +mTAConnectionSocket(client_io_service) { + LOGD(SIM_DAEMON, "Entry"); + + // Initialize the lock for Session map (mSessionMap) + pthread_rwlock_init(&mSessionMapLock, NULL); + // Initialize the lock for Command map (mCommandMap) + pthread_rwlock_init(&mCommandMapLock, NULL); + // Initialize the lock for sendRequesttoTA (sendLock) + pthread_mutex_init(&sendLock, NULL); + // Set the config variables to default + isCreated = false; + isKeepAlive = alive; + isDebug = debug; + mPID = pid; + mTAInstanceID = InstID; + mCommandMap.clear(); +} + +bool TAInstance::checkKeepAlive() { + return isKeepAlive; +} + +bool TAInstance::getCreated() { + return isCreated; +} + +void TAInstance::setCreated(bool value) { + isCreated = value; +} + +pid_t TAInstance::getPID() { + return mPID; +} + +void TAInstance::takeSessionMapLock() { + pthread_rwlock_wrlock(&mSessionMapLock); +} + +void TAInstance::releaseSessionMapLock() { + pthread_rwlock_unlock(&mSessionMapLock); +} + +void TAInstance::eraseSessionMap(uint32_t sessID) { + map::iterator it; + // remove the session from the TA Instance's Session Map + it = mSessionMap.find(sessID); + mSessionMap.erase(it); +} + +uint32_t TAInstance::getSessionMapSize() { + return mSessionMap.size(); +} + +void TAInstance::insertSessionMap(ISession* session) { + mSessionMap[session->getSessionID()] = session; +} + +void TAInstance::insertCommand(SIM_COMMAND cmd, cmdData data) { + pthread_rwlock_wrlock(&mCommandMapLock); + mCommandMap.insert(pair(cmd, data)); + pthread_rwlock_unlock(&mCommandMapLock); +} + +void TAInstance::eraseCommand(SIM_COMMAND cmd, uint32_t sessID) { + multimap::iterator it; + pthread_rwlock_wrlock(&mCommandMapLock); + for (it = mCommandMap.begin(); + it != mCommandMap.end(); ++it) { + if ((it->first == cmd) && (it->second.csdata.sessionID == sessID)) { + mCommandMap.erase(it); + break; + } + } + pthread_rwlock_unlock(&mCommandMapLock); +} + +void TAInstance::killTA() { + if (mPID > 0) { + kill(mPID, SIGKILL); + while (kill(mPID, 0) != -1); + LOGD(SIM_DAEMON, "TA process exited"); + } +} + +void TAInstance::cleanup() { + LOGD(SIM_DAEMON, "Entry"); + multimap::iterator it; + for (it = mCommandMap.begin(); mCommandMap.size() != 0;) { + ResCommandBasePtr ptr; + /* Switch case to find the command which is pending and accordingly + * obtain the handle (ResMakeCommandPtr) to send the reponse to CA + */ + switch (it->first) { + case OPENSESSION: + it->second.osdata.returnValue = TEEC_ERROR_TARGET_DEAD; + ptr = ResMakeCommand::getCommand(it->first, + reinterpret_cast(&(it->second.osdata)), + &mSessionMap); + break; + case INVOKECOMMAND: + it->second.icdata.returnValue = TEEC_ERROR_TARGET_DEAD; + ptr = ResMakeCommand::getCommand(it->first, + reinterpret_cast(&(it->second.icdata)), + &mSessionMap); + break; + case REQCANCEL: + ptr = ResMakeCommand::getCommand(it->first, + reinterpret_cast(&(it->second.rcdata)), + &mSessionMap); + break; + case CLOSESESSION: + ptr = ResMakeCommand::getCommand(it->first, + reinterpret_cast(&(it->second.csdata)), + &mSessionMap); + break; + case COMMANDINVALID: + case CREATE: + case DESTROY: + default: + LOGE(SIM_DAEMON, "Invalid Command"); + break; + } + if (!ptr == false) { + // Call the Session object to handle commands + ptr->execute(); + } else { + LOGE(SIM_DAEMON, "Command not found"); + } + } +} + +/** + * Connect to TA as a client using the socket name created from UUID and + * Instance ID + * @param str Socket name + */ +TEEC_Result TAInstance::connecttoTA(std::stringstream& str) { + + unsigned long int retry_count = 0; + try { + boost::system::error_code error = boost::asio::error::host_not_found; + stream_protocol::endpoint ep(string("/tmp/") + str.str()); + + LOGD(SIM_DAEMON, "Connect to TEEStub"); + // Try to connect to TA RETRY_COUNT number of times + while (error && (retry_count < RETRY_COUNT)) { +#if 0 + LOGD(SIM_DAEMON, "Trying to connect to TEEStub"); + LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); + LOGE(SIM_DAEMON, "Response returned with error code %s", + error.category().name()); +#endif + mTAConnectionSocket.close(); + mTAConnectionSocket.connect(ep, error); + retry_count++; + } + if (retry_count < RETRY_COUNT) { + // Connection successful + LOGD(SIM_DAEMON, "Connected to TEEStub"); + return TEEC_SUCCESS; + } else { + // Retry count exceeded, connection failed + LOGE(SIM_DAEMON, "Connection to TEEStub timed out"); + return TEEC_ERROR_COMMUNICATION; + } + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << "\n"; + return TEEC_ERROR_COMMUNICATION; + } +} + +/** + * Send data to TA instance + * @param cmd Command enum + * @param data Data to be sent to TA + * @param size Size of data + */ +TEEC_Result TAInstance::sendRequestToTA(SIM_COMMAND cmd, void* data, + uint32_t size) { + + LOGD(SIM_DAEMON, "Instance ID: %d", mTAInstanceID); + TEEC_Result result = TEEC_ERROR_TARGET_DEAD; + boost::system::error_code error = boost::asio::error::host_not_found; + + pthread_mutex_lock (&sendLock); + // Send command to TEEStub for TA + boost::asio::write(mTAConnectionSocket, + boost::asio::buffer((char*)&cmd, sizeof(char)), error); + if ((!error) && (size != 0)) { + // Send command data to TEEStub for TA + boost::asio::write(mTAConnectionSocket, + boost::asio::buffer((char*)data, size), error); + if (!error) + result = TEEC_SUCCESS; + else { + LOGE(SIM_DAEMON, "Error in writing Data to TA"); + LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); + LOGE(SIM_DAEMON, "Response returned with error code %s", + error.category().name()); + } + } else { + LOGE(SIM_DAEMON, "Error in writing Command to TA"); + LOGE(SIM_DAEMON, "Response returned with error code %d", error.value()); + LOGE(SIM_DAEMON, "Response returned with error code %s", + error.category().name()); + } + pthread_mutex_unlock(&sendLock); + return result; +} + +/** + * Register an asynchronous callback to continuously receive data from TA + */ +void TAInstance::receiveResponseFromTA() { + + currentState = CMD_READ; + /* Register an asynchronous callback 'handleRead' to continuously receive + * data from TA */ + boost::asio::async_read(mTAConnectionSocket, boost::asio::buffer(readData), + boost::asio::transfer_exactly(1), + boost::bind(&TAInstance::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); +} + +/** + * On asynchronously reading from socket, this call back is executed. + * @param error Boost error code and error message object + * @param bytes_transferred Number of bytes read from the socket + */ +void TAInstance::handleRead(const boost::system::error_code& error, + size_t bytes_transferred) { + + if (!error) { + /** + * A simple small state machine to parse command and handle its + * call back to TEECLib interface + * The state machine identifies the command. If valid, finds out how + * many bytes of data to be read further else if invalid, exits the + * Simulator Daemon. + * + * Later, exact number of identified size of data is read from + * stream and stored. + */ + switch (currentState) { + case CMD_READ: { + // Identify command + command = (SIM_COMMAND)readData.at(0); + LOGD(SIM_DAEMON, "Command received: %d", (uint32_t )command); + + /* Calculate pending numbers of bytes pending to be read only for + * commands + */ + int32_t data_size = ResMakeCommand::getDataSize(command); + + if (data_size > 0) { + currentState = DATA_READ; + // read remaining bytes related to received valid command + boost::asio::async_read(mTAConnectionSocket, + boost::asio::buffer(readData), + boost::asio::transfer_exactly(data_size), + boost::bind(&TAInstance::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + else if (-1 == data_size) { + // else case is invalid command + /* TODO: Identify the correct behavior; + * what to do when invalid command is received? + */ + LOGE(SIM_DAEMON, "Invalid command received!"); + } else if (0 == data_size) { + // reset state to read new command + currentState = CMD_READ; + // read command and register callback to read data + boost::asio::async_read(mTAConnectionSocket, + boost::asio::buffer(readData), boost::asio::transfer_exactly(1), + boost::bind(&TAInstance::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + break; + } //case + + case DATA_READ: { + // At this pouint32_t data is completely read + // clear the vector for the first time and copy server data received + commandData.clear(); + for (uint32_t i = 0; i < readData.size(); i++) { + commandData.push_back(readData.at(i)); + } + string tempData(commandData.begin(), commandData.end()); + + // Get the Session object + ResCommandBasePtr ptr = ResMakeCommand::getCommand(command, + (void*)tempData.c_str(), &mSessionMap); + + if (!ptr == false) { + // Call the Session object to handle commands + ptr->execute(); + } else { + LOGE(SIM_DAEMON, "Command not found"); + } + + // reset state to read new command + currentState = CMD_READ; + // read command and register callback to read data + boost::asio::async_read(mTAConnectionSocket, + boost::asio::buffer(readData), boost::asio::transfer_exactly(1), + boost::bind(&TAInstance::handleRead, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + + break; + } //case + } //switch + } +} + +/** + * Function call to set socket receive timeout + * @param timeout Timeout value to be set for the socket receive + */ +int32_t TAInstance::setSocketOpt(struct timeval timeout) { + + int32_t result = 0; + if (isDebug == false) { + LOGD(SIM_DAEMON, "Entry"); + //Set socket timeout for mTAConnectionSocket + result = setsockopt(mTAConnectionSocket.native(), SOL_SOCKET, SO_RCVTIMEO, + (char*)&timeout, sizeof(timeout)); + if (result < 0) { + LOGE(SIM_DAEMON, "setsockopt timeout = %d FAILED", timeout.tv_usec); + } + } + return result; +} + +/** + * Function call to receive create command response from TA instance + */ +TEEC_Result TAInstance::receiveCreateResponse() { + + TEEC_Result result = TEEC_ERROR_COMMUNICATION; + boost::system::error_code ec = boost::asio::error::host_not_found; + struct timeval timeout; + + //Set Socket timeout to 30 ms for receiving Create response + timeout.tv_sec = 0; + timeout.tv_usec = 30000; + + LOGD(SIM_DAEMON, "Entry"); + if (!setSocketOpt(timeout)) { + // If no error is setting socket timeout, receive response command + boost::asio::read(mTAConnectionSocket, boost::asio::buffer(readData), + boost::asio::transfer_exactly(1), ec); + if (!ec) { + /* If no error is receiving create command response command, + * receive response data */ + boost::asio::read(mTAConnectionSocket, boost::asio::buffer(readData), + boost::asio::transfer_exactly(sizeof(CreateTAEntryPointData)), ec); + if (!ec) + result = TEEC_SUCCESS; + else + LOGE(SIM_DAEMON, "read data FAILED"); + } else + LOGE(SIM_DAEMON, "read command FAILED"); + } else { + LOGE(SIM_DAEMON, "Setting timeout failed"); + return result; + } + //Set Socket timeout to default after receiving Create response + timeout.tv_usec = 0; + if (0 != setSocketOpt(timeout)) { + result = TEEC_ERROR_COMMUNICATION; + LOGE(SIM_DAEMON, "Setting timeout failed"); + } + return result; +} + +/** + * Function call to close socket connection with TA + */ +void TAInstance::closeConnectionToTA() { + LOGD(SIM_DAEMON, "Entry"); + TEEC_Result result = TEEC_ERROR_COMMUNICATION; + + boost::system::error_code ec; + + mTAConnectionSocket.close(ec); + if(!ec) + result = TEEC_SUCCESS; + else + LOGE(SIM_DAEMON, "TA Connection close FAILED"); +} + +/** + * TAInstance destructer. TA Instance is deleted when TA destroy command is + * called. + */ +TAInstance::~TAInstance() { + LOGD(SIM_DAEMON, "Entry"); + + // Close connection with TA + closeConnectionToTA(); + // Destroy the lock created for Session map (mSessionMap) + pthread_rwlock_destroy (&mSessionMapLock); + // Destroy the lock created for Command map (mCommandMap) + pthread_rwlock_destroy (&mCommandMapLock); + // Destory the lock for sendRequesttoTA (sendLock) + pthread_mutex_destroy (&sendLock); +} diff --git a/simulatordaemon/src/TEEContext.cpp b/simulatordaemon/src/TEEContext.cpp new file mode 100755 index 0000000..3e352f7 --- /dev/null +++ b/simulatordaemon/src/TEEContext.cpp @@ -0,0 +1,544 @@ +/* + * ===================================================================================== + * + * Filename: TEEContext.cpp + * + * Description: TEEContext class + * + * Version: 1.0 + * Created: 16 April 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "TEEContext.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +pthread_rwlock_t sessIDLock = PTHREAD_RWLOCK_INITIALIZER; +uint32_t sessID = 51; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * TEEContext constructer. TA Context is created for each InitContext API + * call from CA + * @param contextID ID for Context reference + * @param connSession ConnectionSession instance associated with the context + */ +TEEContext::TEEContext(uint32_t contextID, IConnectionSession* connSession) { + + LOGD(SIM_DAEMON, "ContextID: %d", contextID); + + /* Initialize the locks for shared memory list (mShmList) and Session map + * (mSessionMap) */ + pthread_rwlock_init(&mShmListLock, NULL); + pthread_rwlock_init(&mSessionMapLock, NULL); + + mConnSess = connSession; + mContextID = contextID; + isInternal = false; + /* Clear the shared memory list (mShmList) and Session map (mSessionMap) */ + mSessionMap.clear(); + mShmList.clear(); +} + +/** + * On InitContext API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for InitContext + */ +TEEC_Result TEEContext::initContext(InitContextData* data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + + LOGD(SIM_DAEMON, "Entry"); + + /* Initialize Context is a request from CA, so the member variable + * isInternal of TEEContext is set to false. + */ + isInternal = false; + + /* Check if the TEEName is proper or not */ + if (data->nameLength != 0) { + string TName(data->TEEName); + + if (TName.compare(TEENAME) != 0) { + data->returnValue = TEEC_ERROR_BAD_PARAMETERS; + /* Write the response back to TEECLIB in case of failure */ + result = mConnSess->write(INITIALIZE_CONTEXT, (char*)data, + sizeof(InitContextData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Initialize Context response write to CA FAILED"); + } + return result; + } + } + data->contextID = mContextID; + data->returnValue = TEEC_SUCCESS; + + /* Write the response back to TEECLIB */ + result = mConnSess->write(INITIALIZE_CONTEXT, (char*)data, + sizeof(InitContextData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Initialize Context response write to CA FAILED"); + } + return result; +} + +/** + * On FinalizeContext API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for FinalizeContext + */ +void TEEContext::finContext(FinalizeContextData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + /* Check if the Session map is empty i.e. if all the Sessions have + * been closed. If not closed, print an error, close the sessions in the + * list and clear the list. + */ + pthread_rwlock_wrlock(&mSessionMapLock); + if (!mSessionMap.empty()) { + LOGE(SIM_DAEMON, "Session running in the context\n"); + pthread_rwlock_unlock(&mSessionMapLock); + map::iterator it; + for (it = mSessionMap.begin(); it != mSessionMap.end(); ++it) { + CloseSessionData cdata; + cdata.contextID = data.contextID; + cdata.sessionID = it->first; + result = closeSession(cdata); + if (TEE_SUCCESS != result) { + LOGE(SIM_DAEMON, "Finalize Context - close session FAILED Session ID = %d\n", it->first); + } + } + pthread_rwlock_wrlock(&mSessionMapLock); + mSessionMap.clear(); + } + pthread_rwlock_unlock(&mSessionMapLock); + + /* Check if the Shared memory list is empty i.e. if all the memories have + * been released. If not released, print an error and clear the list. + */ + pthread_rwlock_wrlock(&mShmListLock); + if (!mShmList.empty()) { + LOGE(SIM_DAEMON, "WSM not released"); + mShmList.clear(); + } + pthread_rwlock_unlock(&mShmListLock); + + if (data.contextID != 0) { + /* Write the response back to TEECLIB */ + result = mConnSess->write(FINALIZE_CONTEXT, (char*)&data, + sizeof(FinalizeContextData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Finalize Context response write to CA FAILED"); + } + } +} + +/** + * On OpenSession API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for OpenSession + */ +TEEC_Result TEEContext::openSession(OpenSessionData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + + LOGD(SIM_DAEMON, "Entry"); + data.returnOrigin = TEEC_ORIGIN_TEE; + data.returnValue = TEEC_ERROR_GENERIC; + pthread_rwlock_wrlock(&sessIDLock); + data.sessionID = sessID; + sessID++; + pthread_rwlock_unlock(&sessIDLock); + + /* Create a new Session instance */ + ISession *mSession = new Session(this); + + /* Call session createSession function to handle open session request */ + result = mSession->createSession(data); + if (TEEC_SUCCESS != result) { + LOGE(SIM_DAEMON, "Open Command FAILED"); + delete mSession; + data.returnValue = result; + + /* Write the response back to TEECLIB in case of failure */ + result = mConnSess->write(OPEN_SESSION, (char*)&data, + sizeof(OpenSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Open Session response write to CA FAILED"); + } + return result; + } + if (mSession->getTAInstance() == NULL) { + LOGE(SIM_DAEMON, "Creating Trusted Application Instance FAILED"); + delete mSession; + data.returnValue = TEEC_ERROR_BAD_PARAMETERS; + + /* Write the response back to TEECLIB in case of failure */ + result = mConnSess->write(OPEN_SESSION, (char*)&data, + sizeof(OpenSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Open Session response write to CA FAILED"); + } + return result; + } + /* Write the response back to TEECLIB in case of failure */ + pthread_rwlock_wrlock(&mSessionMapLock); + mSessionMap[data.sessionID] = mSession; + pthread_rwlock_unlock(&mSessionMapLock); + return result; +} + +/** + * On InvokeCommand API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for InvokeCommand + */ +TEEC_Result TEEContext::invokeCommand(InvokeCommandData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + data.returnOrigin = TEEC_ORIGIN_TEE; + data.returnValue = TEEC_ERROR_GENERIC; + + /* Find the Session instance in the session map */ + map::iterator it; + pthread_rwlock_wrlock(&mSessionMapLock); + it = mSessionMap.find(data.sessionID); + if (it == mSessionMap.end()) { + LOGE(SIM_DAEMON, "Session not found"); + pthread_rwlock_unlock(&mSessionMapLock); + return result; + } + pthread_rwlock_unlock(&mSessionMapLock); + + /* Call session handleCommand function to handle invoke command request */ + if (NULL != it->second) { + LOGD(SIM_DAEMON, "Entry"); + result = it->second->handleCommand(data); + if (TEEC_SUCCESS == result) { + return result; + } + } else { + result = TEEC_ERROR_TARGET_DEAD; + } + LOGE(SIM_DAEMON, "Invoke Command FAILED"); + data.returnValue = result; + /* Write the response back to TEECLIB in case of failure */ + result = mConnSess->write(INVOKE_COMMAND, (char*)&data, + sizeof(InvokeCommandData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Invoke Command response write to CA FAILED"); + } + return result; +} + +/** + * On RequestCancellation API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for RequestCancellation + */ +void TEEContext::reqCancel(ReqCancellationData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + /* Find the Session instance in the session map */ + map::iterator it; + pthread_rwlock_wrlock(&mSessionMapLock); + it = mSessionMap.find(data.sessionID); + if (it == mSessionMap.end()) { + LOGE(SIM_DAEMON, "Session not found"); + pthread_rwlock_unlock(&mSessionMapLock); + return; + } + + /* Call session handleCancel function to handle cancellation request */ + pthread_rwlock_unlock(&mSessionMapLock); + if (NULL != it->second) { + LOGD(SIM_DAEMON, "Entry"); + it->second->handleCancel(data); + } + + /* Write the response back to TEECLIB */ + result = mConnSess->write(REQUEST_CANCELLATION, (char*)&data, + sizeof(ReqCancellationData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Request Cancellation response write to CA FAILED"); + } +} + +/** + * On CloseSession API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for CloseSession + */ +TEEC_Result TEEContext::closeSession(CloseSessionData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + /* Find the Session instance in the session map */ + map::iterator it; + pthread_rwlock_wrlock(&mSessionMapLock); + it = mSessionMap.find(data.sessionID); + if (it == mSessionMap.end()) { + LOGE(SIM_DAEMON, "Session not found"); + pthread_rwlock_unlock(&mSessionMapLock); + return result; + } + LOGE(SIM_DAEMON, "Session pointer 0x%x", it->second); + + /* Call session finalize function to handle close session request */ + if (NULL != it->second) { + LOGD(SIM_DAEMON, "Entry"); + result = it->second->finalize(data.contextID); + if (result == TEEC_SUCCESS) { + return result; + } else { + it->second = NULL; + } + } else { + result = TEEC_ERROR_TARGET_DEAD; + } + + LOGE(SIM_DAEMON, "Close Command FAILED"); + delete it->second; + if (data.contextID != 0) { + /* Write the response back to TEECLIB in case of failure */ + result = mConnSess->write(CLOSE_SESSION, (char*)&data, + sizeof(CloseSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Close Session response write to CA FAILED"); + } + } + pthread_rwlock_unlock(&mSessionMapLock); + return result; +} + +/** + * On OpenTASession API call from TA, SSFLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from SSFLib + * @param data data sent from SSFLib for OpenTASession + */ +TEEC_Result TEEContext::openTASession(IntTAOpenSessionData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + /* OpenTASession is a request from TA, so the member variable isInternal of + * TEEContext is set to true + */ + isInternal = true; + OpenSessionData sdata; + sdata.returnOrigin = data.returnOrigin = TEEC_ORIGIN_TEE; + sdata.returnValue = data.returnValue = TEEC_ERROR_GENERIC; + + /* Assign a Session ID number to the Session instance to be created */ + pthread_rwlock_wrlock(&sessIDLock); + sdata.sessionID = data.session = sessID; + sessID++; + pthread_rwlock_unlock(&sessIDLock); + + sdata.connMeth = TEEC_LOGIN_PUBLIC; + sdata.operation = data.operation; + memcpy(&sdata.uuid, &data.destination, sizeof(TEEC_UUID)); + + /* Create a new Session instance */ + ISession *mSession = new Session(this); + + /* Call session createSession function to handle open session request */ + result = mSession->createSession(sdata); + if (TEEC_SUCCESS != result) { + LOGE(SIM_DAEMON, "Open TA command FAILED"); + delete mSession; + data.returnValue = result; + + /* Write the response back to SSFLIB in case of failure */ + result = mConnSess->write(OPEN_TA_SESSION, (char*)&data, + sizeof(IntTAOpenSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Open TA Session response write to CA FAILED"); + } + return result; + } + if (mSession->getTAInstance() == NULL) { + LOGE(SIM_DAEMON, "Creating Trusted Application Instance FAILED"); + delete mSession; + data.returnValue = TEEC_ERROR_BAD_PARAMETERS; + /* Write the response back to SSFLIB in case of failure */ + result = mConnSess->write(OPEN_TA_SESSION, (char*)&data, + sizeof(IntTAOpenSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Open TA Session response write to CA FAILED"); + } + return result; + } + /* Add the Session instance in the session map */ + pthread_rwlock_wrlock(&mSessionMapLock); + mSessionMap[sdata.sessionID] = mSession; + pthread_rwlock_unlock(&mSessionMapLock); + return result; +} + +/** + * On CloseTASession API call from TA, SSFLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from SSFLib + * @param data data sent from SSFLib for CloseTASession + */ +void TEEContext::closeTASession(IntTACloseSessionData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + map::iterator it; + LOGD(SIM_DAEMON, "Entry"); + + /* Find the Session instance in the session map */ + pthread_rwlock_wrlock(&mSessionMapLock); + it = mSessionMap.find(data.session); + if (it == mSessionMap.end()) { + LOGE(SIM_DAEMON, "Session not found"); + pthread_rwlock_unlock(&mSessionMapLock); + return; + } + + /* Call session finalize function to handle close session request */ + result = it->second->finalize(mContextID); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Close TA Command FAILED"); + delete it->second; + /* Write the response back to SSFLIB */ + result = mConnSess->write(CLOSE_TA_SESSION, (char*)&data, + sizeof(IntTACloseSessionData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Close TA Session response write to CA FAILED"); + } + } + /* Remove the Session instance from the session map */ + mSessionMap.erase(it); + pthread_rwlock_unlock(&mSessionMapLock); +} + +/** + * On InvokeTACommand API call from TA, SSFLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from SSFLib + * @param data data sent from SSFLib for InvokeTACommand + */ +TEEC_Result TEEContext::invokeTACommand(IntTAInvokeCommandData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + data.returnOrigin = TEEC_ORIGIN_TEE; + data.returnValue = TEEC_ERROR_GENERIC; + + InvokeCommandData idata; + idata.commandID = data.commandID; + idata.operation = data.operation; + idata.returnOrigin = TEEC_ORIGIN_TEE; + idata.returnValue = TEEC_ERROR_GENERIC; + idata.sessionID = data.session; + + /* Find the Session instance in the session map */ + map::iterator it; + pthread_rwlock_wrlock(&mSessionMapLock); + it = mSessionMap.find(data.session); + if (it == mSessionMap.end()) { + LOGE(SIM_DAEMON, "Session not found"); + pthread_rwlock_unlock(&mSessionMapLock); + return result; + } + pthread_rwlock_unlock(&mSessionMapLock); + + /* Call session handle command function to handle invoke command request */ + result = it->second->handleCommand(idata); + if (TEEC_SUCCESS != result) { + LOGE(SIM_DAEMON, "Invoke TA Command FAILED"); + data.returnValue = result; + /* Write the response back to SSFLIB */ + result = mConnSess->write(INVOKE_TA_COMMAND, (char*)&data, + sizeof(IntTAInvokeCommandData)); + if (result != TEEC_SUCCESS) { + LOGE(SIM_DAEMON, "Invoke TA Session response write to CA FAILED"); + } + } + return result; +} + +/** + * On RegisterSharedMemory API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for RegisterSharedMemory + */ +TEEC_Result TEEContext::registerSharedMemory(RegSharedMemData data) { + + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + /* Add the shared memory in the list */ + pthread_rwlock_wrlock(&mShmListLock); + mShmList.push_back(data.sharedMem.shmKey); + pthread_rwlock_unlock(&mShmListLock); + data.returnValue = TEEC_SUCCESS; + + /* Write the response back to TEECLib */ + result = mConnSess->write(REGISTER_SHARED_MEMORY, (char*)&data, + sizeof(RegSharedMemData)); + return result; +} + +/** + * On ReleaseSharedMemory API call from CA, TEECLib sends command and data to + * Simulator Daemon, on this command this function is executed with the data + * sent from TEECLib + * @param data data sent from TEECLib for ReleaseSharedmemory + */ +TEEC_Result TEEContext::releaseSharedMemory(RelSharedMemData data) { + TEEC_Result result = TEEC_ERROR_GENERIC; + LOGD(SIM_DAEMON, "Entry"); + + /* Remove the shared memory for the list */ + pthread_rwlock_wrlock(&mShmListLock); + mShmList.remove(data.sharedMem.shmKey); + pthread_rwlock_unlock(&mShmListLock); + + /* Write the response back to TEECLib */ + result = mConnSess->write(RELEASE_SHARED_MEMORY, (char*)&data, + sizeof(RelSharedMemData)); + return result; +} + +/** + * TEEContext destructer. + */ +TEEContext::~TEEContext() { + LOGD(SIM_DAEMON, "ContextID: %d", mContextID); + /* Destroy the locks created for shared memory list (mShmList) and + * Session map (mSessionMap). */ + pthread_rwlock_destroy(&mShmListLock); + pthread_rwlock_destroy(&mSessionMapLock); +} diff --git a/simulatordaemon/src/ioService.cpp b/simulatordaemon/src/ioService.cpp new file mode 100755 index 0000000..f20061c --- /dev/null +++ b/simulatordaemon/src/ioService.cpp @@ -0,0 +1,39 @@ +/* + * ===================================================================================== + * + * Filename: ioService.cpp + * + * Description: ioService class + * + * Version: 1.0 + * Created: 05 May 2015 12:42:03 IST + * Revision: Original + * Compiler: gcc + * + * Author: CHERYL (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +boost::asio::io_service ioService::io_service; + +/*----------------------------------------------------------------------------- + * Member functions + *-----------------------------------------------------------------------------*/ +/** + * Get ioService Instance. + * return the io_service instance. + */ +boost::asio::io_service& ioService::getInstance() { + // return the io_service instance + return io_service; +} diff --git a/simulatordaemon/src/rapidxml/rapidxml.hpp b/simulatordaemon/src/rapidxml/rapidxml.hpp new file mode 100755 index 0000000..234f577 --- /dev/null +++ b/simulatordaemon/src/rapidxml/rapidxml.hpp @@ -0,0 +1,2396 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) +#include // For std::size_t +#include // For assert +#include // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //!

+ //! This function cannot return. If it does, the results are undefined. + //!

+ //! A very simple definition might look like that: + //!
+	//! void %rapidxml::%parse_error_handler(const char *what, void *where)
+	//! {
+	//!     LOGE(SIM_DAEMON, "Parse error: %s", what);
+	//!     std::abort();
+	//! }
+	//! 
+ //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml { + +//! Parse error exception. +//! This exception is thrown by the parser when an error occurs. +//! Use what() function to get human-readable error message. +//! Use where() function to get a pointer to position within source text where error was detected. +//!

+//! If throwing exceptions by the parser is undesirable, +//! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. +//! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. +//! This function must be defined by the user. +//!

+//! This class derives from std::exception class. +class parse_error: + public std::exception { + +public: + + //! Constructs parse error + parse_error(const char *what, void *where) : + m_what(what), m_where(where) { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw () { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template + Ch *where() const { + return reinterpret_cast(m_where); + } + +private: + + const char *m_what; + void *m_where; + +}; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE +// Size of static memory block of memory_pool. +// Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. +// No dynamic memory allocations are performed by memory_pool until static memory is exhausted. +#define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE +// Size of dynamic memory block of memory_pool. +// Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. +// After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. +#define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT +// Memory allocation alignment. +// Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. +// All memory allocations for nodes, attributes and strings will be aligned to this value. +// This must be a power of 2 and at least 1, otherwise memory_pool will not work. +#define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml { +// Forward declarations +template class xml_node; +template class xml_attribute; +template class xml_document; + +//! Enumeration listing all node types produced by the parser. +//! Use xml_node::type() function to query node type. +enum node_type { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. +}; + +/////////////////////////////////////////////////////////////////////// +// Parsing flags + +//! Parse flag instructing the parser to not create data nodes. +//! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_data_nodes = 0x1; + +//! Parse flag instructing the parser to not use text of first data node as a value of parent element. +//! Can be combined with other flags by use of | operator. +//! Note that child data nodes of element node take precendence over its value when printing. +//! That is, if element has one or more child data nodes and a value, the value will be ignored. +//! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. +//!

+//! See xml_document::parse() function. +const int parse_no_element_values = 0x2; + +//! Parse flag instructing the parser to not place zero terminators after strings in the source text. +//! By default zero terminators are placed, modifying source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_string_terminators = 0x4; + +//! Parse flag instructing the parser to not translate entities in the source text. +//! By default entities are translated, modifying source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_entity_translation = 0x8; + +//! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. +//! By default, UTF-8 handling is enabled. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_no_utf8 = 0x10; + +//! Parse flag instructing the parser to create XML declaration node. +//! By default, declaration node is not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_declaration_node = 0x20; + +//! Parse flag instructing the parser to create comments nodes. +//! By default, comment nodes are not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_comment_nodes = 0x40; + +//! Parse flag instructing the parser to create DOCTYPE node. +//! By default, doctype node is not created. +//! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_doctype_node = 0x80; + +//! Parse flag instructing the parser to create PI nodes. +//! By default, PI nodes are not created. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_pi_nodes = 0x100; + +//! Parse flag instructing the parser to validate closing tag names. +//! If not set, name inside closing tag is irrelevant to the parser. +//! By default, closing tags are not validated. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_validate_closing_tags = 0x200; + +//! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. +//! By default, whitespace is not trimmed. +//! This flag does not cause the parser to modify source text. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_trim_whitespace = 0x400; + +//! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. +//! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. +//! By default, whitespace is not normalized. +//! If this flag is specified, source text will be modified. +//! Can be combined with other flags by use of | operator. +//!

+//! See xml_document::parse() function. +const int parse_normalize_whitespace = 0x800; + +// Compound flags + +//! Parse flags which represent default behaviour of the parser. +//! This is always equal to 0, so that all other flags can be simply ored together. +//! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. +//! This also means that meaning of each flag is a negation of the default setting. +//! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, +//! and using the flag will disable it. +//!

+//! See xml_document::parse() function. +const int parse_default = 0; + +//! A combination of parse flags that forbids any modifications of the source text. +//! This also results in faster parsing. However, note that the following will occur: +//!
    +//!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • +//!
  • entities will not be translated
  • +//!
  • whitespace will not be normalized
  • +//!
+//! See xml_document::parse() function. +const int parse_non_destructive = parse_no_string_terminators + | parse_no_entity_translation; + +//! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. +//!

+//! See xml_document::parse() function. +const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + +//! A combination of parse flags resulting in largest amount of data being extracted. +//! This usually results in slowest parsing. +//!

+//! See xml_document::parse() function. +const int parse_full = parse_declaration_node | parse_comment_nodes + | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + +/////////////////////////////////////////////////////////////////////// +// Internals + +//! \cond internal +namespace internal { + +// Struct that contains lookup tables for the parser +// It must be a template to allow correct linking (because it has static data members, which are defined in a header file). +template +struct lookup_tables { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters +}; + +// Find length of the string +template +inline std::size_t measure(const Ch *p) { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; +} + +// Compare strings for equality +template +inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, + std::size_t size2, bool case_sensitive) { + if (size1 != size2) return false; + if (case_sensitive) { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) return false; + } else { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] + != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) + return false; + } + return true; +} +} +//! \endcond + +/////////////////////////////////////////////////////////////////////// +// Memory pool + +//! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. +//! In most cases, you will not need to use this class directly. +//! However, if you need to create nodes manually or modify names/values of nodes, +//! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. +//! Not only is this faster than allocating them by using new operator, +//! but also their lifetime will be tied to the lifetime of document, +//! possibly simplyfing memory management. +//!

+//! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. +//! You can also call allocate_string() function to allocate strings. +//! Such strings can then be used as names or values of nodes without worrying about their lifetime. +//! Note that there is no free() function -- all allocations are freed at once when clear() function is called, +//! or when the pool is destroyed. +//!

+//! It is also possible to create a standalone memory_pool, and use it +//! to allocate nodes, whose lifetime will not be tied to any document. +//!

+//! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. +//! Until static memory is exhausted, no dynamic memory allocations are done. +//! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, +//! by using global new[] and delete[] operators. +//! This behaviour can be changed by setting custom allocation routines. +//! Use set_allocator() function to set them. +//!

+//! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. +//! This value defaults to the size of pointer on target architecture. +//!

+//! To obtain absolutely top performance from the parser, +//! it is important that all nodes are allocated from a single, contiguous block of memory. +//! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. +//! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT +//! to obtain best wasted memory to performance compromise. +//! To do it, define their values before rapidxml.hpp file is included. +//! \param Ch Character type of created nodes. +template +class memory_pool { + +public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() : + m_alloc_func(0), m_free_func(0) { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node *allocate_node(node_type type, const Ch *name = 0, + const Ch *value = 0, std::size_t name_size = 0, + std::size_t value_size = 0) { + void *memory = allocate_aligned(sizeof(xml_node )); + xml_node *node = new (memory) xml_node(type); + if (name) { + if (name_size > 0) + node->name(name, name_size); + else node->name(name); + } + if (value) { + if (value_size > 0) + node->value(value, value_size); + else node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) { + void *memory = allocate_aligned(sizeof(xml_attribute )); + xml_attribute *attribute = new (memory) xml_attribute; + if (name) { + if (name_size > 0) + attribute->name(name, name_size); + else attribute->name(name); + } + if (value) { + if (value_size > 0) + attribute->value(value, value_size); + else attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) size = internal::measure(source) + 1; + Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); + if (source) for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node *clone_node(const xml_node *source, + xml_node *result = 0) { + // Prepare result node + if (result) { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } else result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node *child = source->first_node(); child; + child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute *attr = source->first_attribute(); attr; + attr = attr->next_attribute()) + result->append_attribute( + allocate_attribute(attr->name(), attr->value(), attr->name_size(), + attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() { + while (m_begin != m_static_memory) { + char *previous_begin = reinterpret_cast
(align(m_begin)) + ->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use longjmp() function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //!

+ //! User defined allocation functions must have the following forms: + //!
+ //!
void *allocate(std::size_t size); + //!
void free(void *pointer); + //!

+ //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + +private: + + struct header { + char *previous_begin; + }; + + void init() { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) { + std::size_t alignment = ((RAPIDXML_ALIGNMENT + - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) + & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } else { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast(memory); + } + + void *allocate_aligned(std::size_t size) { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast
(pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used +}; + +/////////////////////////////////////////////////////////////////////////// +// XML base + +//! Base class for xml_node and xml_attribute implementing common functions: +//! name(), name_size(), value(), value_size() and parent(). +//! \param Ch Character type to use +template +class xml_base { + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() : + m_name(0), m_value(0), m_parent(0) { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

+ //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) { + m_name = const_cast(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

+ //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

+ //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //!

+ //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) { + m_value = const_cast(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node *parent() const { + return m_parent; + } + +protected: + + // Return empty string + static Ch *nullstr() { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node *m_parent; // Pointer to parent node, or 0 if none + +}; + +//! Class representing attribute node of XML document. +//! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). +//! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. +//! Thus, this text must persist in memory for the lifetime of attribute. +//! \param Ch Character type to use. +template +class xml_attribute: + public xml_base { + + friend class xml_node ; + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document *document() const { + if (xml_node *node = this->parent()) { + while (node->parent()) + node = node->parent(); + return + node->type() == node_document ? + static_cast *>(node) : 0; + } else return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *previous_attribute(const Ch *name = 0, + std::size_t name_size = 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_prev_attribute; attribute; + attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_next_attribute; attribute; + attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return this->m_parent ? m_next_attribute : 0; + } + +private: + + xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + +}; + +/////////////////////////////////////////////////////////////////////////// +// XML node + +//! Class representing a node of XML document. +//! Each node may have associated name and value strings, which are available through name() and value() functions. +//! Interpretation of name and value depends on type of the node. +//! Type of node can be determined by using type() function. +//!

+//! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. +//! Thus, this text must persist in the memory for the lifetime of node. +//! \param Ch Character type to use. +template +class xml_node: + public xml_base { + +public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) : + m_type(type), m_first_node(0), m_first_attribute(0) { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document *document() const { + xml_node *node = const_cast *>(this); + while (node->parent()) + node = node->parent(); + return + node->type() == node_document ? static_cast *>(node) : + 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *child = m_first_node; child; + child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, + name_size, case_sensitive)) return child; + return 0; + } else return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *child = m_last_node; child; + child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, + name_size, case_sensitive)) return child; + return 0; + } else return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *sibling = m_prev_sibling; sibling; + sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, + name_size, case_sensitive)) return sibling; + return 0; + } else return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, + bool case_sensitive = true) const { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_node *sibling = m_next_sibling; sibling; + sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, + name_size, case_sensitive)) return sibling; + return 0; + } else return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_first_attribute; attribute; + attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = + 0, bool case_sensitive = true) const { + if (name) { + if (name_size == 0) name_size = internal::measure(name); + for (xml_attribute *attribute = m_last_attribute; attribute; + attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, + name_size, case_sensitive)) return attribute; + return 0; + } else return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node *child) { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } else { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node *child) { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } else { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node *where, xml_node *child) { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() { + assert(first_node()); + xml_node *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() { + assert(first_node()); + xml_node *child = m_last_node; + if (child->m_prev_sibling) { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } else m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node *where) { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() { + for (xml_node *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute *attribute) { + assert(attribute && !attribute->parent()); + if (first_attribute()) { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } else { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute *attribute) { + assert(attribute && !attribute->parent()); + if (first_attribute()) { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } else { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute *where, + xml_attribute *attribute) { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() { + assert(first_attribute()); + xml_attribute *attribute = m_first_attribute; + if (attribute->m_next_attribute) { + attribute->m_next_attribute->m_prev_attribute = 0; + } else m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() { + assert(first_attribute()); + xml_attribute *attribute = m_last_attribute; + if (attribute->m_prev_attribute) { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } else m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute *where) { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() { + for (xml_attribute *attribute = first_attribute(); attribute; + attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + +private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + +}; + +/////////////////////////////////////////////////////////////////////////// +// XML document + +//! This class represents root of the DOM hierarchy. +//! It is also an xml_node and a memory_pool through public inheritance. +//! Use parse() function to build a DOM tree from a zero-terminated XML text string. +//! parse() function allocates memory for nodes and attributes by using functions of xml_document, +//! which are inherited from memory_pool. +//! To access root node of the document, use the document itself, as if it was an xml_node. +//! \param Ch Character type to use. +template +class xml_document: + public xml_node, public memory_pool { + +public: + + //! Constructs empty XML document + xml_document() : + xml_node(node_document) { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //!

+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //!

+ //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template + void parse(Ch *text) { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom(text); + + // Parse children + while (1) { + // Skip whitespace before node + skip(text); + if (*text == 0) break; + + // Parse and append new child + if (*text == Ch('<')) { + ++text; // Skip '<' + if (xml_node *node = parse_node(text)) + this->append_node(node); + } else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool::clear(); + } + +private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + } + }; + + // Detect node name character + struct node_name_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred { + static unsigned char test(Ch ch) { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + } + }; + + // Detect attribute value character + template + struct attribute_value_pred { + static unsigned char test(Ch ch) { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template + struct attribute_value_pure_pred { + static unsigned char test(Ch ch) { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template + static void insert_coded_character(Ch *&text, unsigned long code) { + if (Flags & parse_no_utf8) { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast(code); + text += 1; + } else { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + text += 1; + } else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xC0); + text += 2; + } else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xE0); + text += 3; + } else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); + code >>= 6; + text[0] = static_cast(code | 0xF0); + text += 4; + } else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template + static void skip(Ch *&text) { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template + static Ch *skip_and_expand_character_refs(Ch *&text) { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation + && !(Flags & parse_normalize_whitespace) + && !(Flags & parse_trim_whitespace)) { + skip(text); + return text; + } + + // Use simple skip until first modification is detected + skip(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) { + // Test if replacement is needed + if (src[0] == Ch('&')) { + switch (src[1]) { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') + && src[5] == Ch(';')) { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') + && src[5] == Ch(';')) { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) { + unsigned char digit = + internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) break; + code = code * 16 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } else { + unsigned long code = 0; + src += 2; // Skip &# + while (1) { + unsigned char digit = + internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) break; + code = code * 10 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) { + // Test if condensing is needed + if (whitespace_pred::test(*src)) { + *dest = Ch(' '); + ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template + void parse_bom(Ch *&text) { + // UTF-8? + if (static_cast(text[0]) == 0xEF + && static_cast(text[1]) == 0xBB + && static_cast(text[2]) == 0xBF) { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration ( + xml_node *parse_xml_declaration(Ch *&text) { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip(text); + + // Parse declaration attributes + parse_node_attributes(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template + xml_node *parse_doctype(Ch *&text) { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) { + // Determine character type + switch (*text) { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) { + switch (*text) { + case Ch('['): + ++depth; + break; + case Ch(']'): + --depth; + break; + case 0: + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) { + // Create a new doctype node + xml_node *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } else { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template + xml_node *parse_pi(Ch *&text) { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) { + // Create pi node + xml_node *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } else { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template + Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs(text); + else end = skip_and_expand_character_refs(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) { + if (Flags & parse_normalize_whitespace) { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) --end; + } else { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) { + xml_node *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template + xml_node *parse_cdata(Ch *&text) { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template + xml_node *parse_element(Ch *&text) { + // Create element node + xml_node *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip(text); + + // Parse attributes, if any + parse_node_attributes(text, element); + + // Determine ending type + if (*text == Ch('>')) { + ++text; + parse_node_contents(text, element); + } else if (*text == Ch('/')) { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template + xml_node *parse_node(Ch *&text) { + // Parse proper node type + switch (text[0]) { + + // <... + default: + // Parse and append element node + return parse_element(text); + + // (text); + } else { + // Parse PI + return parse_pi(text); + } + + // (text); + } + break; + + // (text); + } + break; + + // (text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with ')) { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template + void parse_node_contents(Ch *&text, xml_node *node) { + // For all children and text + while (1) { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) { + // Node closing + text += 2; // Skip '(text); + if (!internal::compare(node->name(), node->name_size(), + closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } else { + // No validation, just skip name + skip(text); + } + // Skip remaining whitespace after node name + skip(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } else { + // Child node + ++text; // Skip '<' + if (xml_node *child = parse_node(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data(node, text, contents_start); + goto after_data_node; + // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template + void parse_node_attributes(Ch *&text, xml_node *node) { + // For all attributes + while (attribute_name_pred::test(*text)) { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs, + attribute_value_pure_pred, AttFlags>(text); + else end = skip_and_expand_character_refs, + attribute_value_pure_pred, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip(text); + } + } + +}; + +//! \cond internal +namespace internal { + +// Whitespace (space \n \r \t) +template +const unsigned char lookup_tables::lookup_whitespace[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + +// Node name (anything but space \n \r \t / > ? \0) +template +const unsigned char lookup_tables::lookup_node_name[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) (anything but < \0) +template +const unsigned char lookup_tables::lookup_text[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) that does not require processing when ws normalization is disabled +// (anything but < \0 &) +template +const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled +// (anything but < \0 & space \n \r \t) +template +const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute name (anything but space \n \r \t / < > = ? ! \0) +template +const unsigned char lookup_tables::lookup_attribute_name[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with single quote (anything but ' \0) +template +const unsigned char lookup_tables::lookup_attribute_data_1[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with single quote that does not require processing (anything but ' \0 &) +template +const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with double quote (anything but " \0) +template +const unsigned char lookup_tables::lookup_attribute_data_2[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Attribute data with double quote that does not require processing (anything but " \0 &) +template +const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + +// Digits (dec and hex, 255 denotes end of numeric character reference) +template +const unsigned char lookup_tables::lookup_digits[256] = { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 0 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 1 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, + 255, // 3 + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 4 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 5 + 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 6 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 7 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 8 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // 9 + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // A + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // B + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // C + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // D + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, // E + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255 // F + }; + +// Upper case conversion +template +const unsigned char lookup_tables::lookup_upcase[256] = { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, + 127, // 7 + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, // 8 + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, + 159, // 9 + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, + 175, // A + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, // B + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, // C + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, // D + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, + 239, // E + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 // F + }; +} +//! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/simulatordaemon/src/scripts/update_uuid_list.sh b/simulatordaemon/src/scripts/update_uuid_list.sh new file mode 100755 index 0000000..590b3aa --- /dev/null +++ b/simulatordaemon/src/scripts/update_uuid_list.sh @@ -0,0 +1,1189 @@ +#!/bin/sh +# This script creates a uuidlist.list file and populates it with TA UUID packages names. +# Ths file is populated based on the existing files in directory /tmp/tastore/ +# UUID pattern is: ....-....-....-............ +# This script should be executed once all the TA packages are transferred to /tmp/tastore + +# Author: Krishna Devale +# Samsung R & D Institute, Bangalore +# 7 May 2015 + +#uuidfile="./tastore/uuidlist.list"; +uuidfile="/tmp/tastore/uuidlist.list"; + +retval="" +file="/tmp/fileLock" + +S=< $uuidfile + + # just for testing script input + #echo $@ >> $uuidfile + + #if port exists, test if it is blocked + if [ -n "$port" ] + then + #Test if port number is blocked + process=`netstat -nlp | grep $port | awk '{print $7}' | cut -d '/' -f 1` + + # check if port is blocked and find empty port by looping + if [ -n "$process" ]; then + while [ -n "$process" ] + do + port=`expr $port + 1` + process=`netstat -nlp | grep $port | awk '{print $7}' | cut -d '/' -f 1` + var="$uuid,$port" + done + retval="$retval#$var" + fi + fi + + echo $var >> $uuidfile +done +sed '/^$/d' $uuidfile > $uuidfile.temp && mv $uuidfile.temp $uuidfile +echo $S 1 | openssl base64 -d +echo $retval + +# OLD SCRIPT FILE BACKUP + +#uuidfile="/tmp/tastore/uuidlist.list"; +#rm -f $uuidfile; + +#for filename in $(find /tmp/tastore/ -maxdepth 1 -regex ".*/[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]" ! -name "*ext"); do +#strip off the complete path, retain only the file names +#(echo "${filename:13}" >> $uuidfile); +#done diff --git a/ssflib/.cproject b/ssflib/.cproject new file mode 100755 index 0000000..61f06db --- /dev/null +++ b/ssflib/.cproject @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ssflib/.gitignore b/ssflib/.gitignore new file mode 100755 index 0000000..3df573f --- /dev/null +++ b/ssflib/.gitignore @@ -0,0 +1 @@ +/Debug/ diff --git a/ssflib/.project b/ssflib/.project new file mode 100755 index 0000000..ae8262f --- /dev/null +++ b/ssflib/.project @@ -0,0 +1,27 @@ + + + ssflib + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/ssflib/.settings/org.eclipse.cdt.core.prefs b/ssflib/.settings/org.eclipse.cdt.core.prefs new file mode 100755 index 0000000..5f794a6 --- /dev/null +++ b/ssflib/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,31 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/CWD/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/CWD/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/CWD/value=${ProjDirPath}/Debug_Windows +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\Program Files (x86)\\Java\\jre1.8.0_45\\bin;C\:\\Program Files\\eclipse;C\:/Program Files/Java/jre1.8.0_31/bin/server;C\:/Program Files/Java/jre1.8.0_31/bin;C\:/Program Files/Java/jre1.8.0_31/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\csvn\\bin\\;C\:\\csvn\\Python25\\;C\:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files\\Diskeeper Corporation\\ExpressCache\\;C\:\\Program Files (x86)\\Windows Live\\Shared;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\3.0\\bin\\x64;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files (x86)\\WinSCP\\;C\:\\Program Files (x86)\\PuTTY;C\:\\Program Files\\Microsoft\\Web Platform Installer\\;C\:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Binn\\;C\:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;C\:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;C\:\\Program Files (x86)\\doxygen\\bin;C\:\\Program Files (x86)\\sfk168;C\:\\Program Files (x86)\\vlc-2.1.0;C\:\\Python27\\Scripts;C\:\\Program Files (x86)\\GnuWin32\\bin;C\:\\Python27;C\:\\Program Files (x86)\\Subversion\\bin;c\:\\Program Files\\Synergy;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\MinGW\\lib\\gcc\\mingw32\\4.8.1;C\:\\Program Files (x86)\\Windows Kits\\8.1\\Windows Performance Toolkit\\;C\:\\Program Files (x86)\\GitExtensions\\;C\:\\Program Files\\Perforce;c\:\\Program Files\\Java\\jre1.8.0_31\\bin\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;D\:\\samsung-tv-sdk\\ide;D\:\\samsung-tv-sdk\\tasdk_ide\\tasdk_tools\\i386-linux-gnueabi-gcc-4.6\\bin;D\:\\samsung-tv-sdk\\tasdk_ide\\tasdk_tools\\mingw\\bin;D\:\\samsung-tv-sdk\\tasdk_ide\\tasdk_tools\\mingw\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/PWD/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/PWD/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/PWD/value=${ProjDirPath}/Debug_Windows +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/append=true +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484.12338249/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/CWD/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/CWD/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/CWD/value=${ProjDirPath}/Debug_Windows +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/PATH/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/PATH/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/PATH/value=C\:/Program Files/Java/jre1.8.0_45/bin/server;C\:/Program Files/Java/jre1.8.0_45/bin;C\:/Program Files/Java/jre1.8.0_45/lib/amd64;C\:\\ProgramData\\Oracle\\Java\\javapath;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\Intel\\iCLS Client\\;C\:\\Program Files\\Intel\\iCLS Client\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C\:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x86;C\:\\Program Files (x86)\\Intel\\OpenCL SDK\\2.0\\bin\\x64;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\Intel\\WiFi\\bin\\;C\:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files (x86)\\GitExtensions\\;D\:\\Tizen\\tizen-sdk\\tools;D\:\\Android\\android-sdk\\platform-tools;D\:\\Android\\android-ndk-r10c;C\:\\Program Files\\Perforce;D\:\\eclipse\\eclipse-rcp-luna-SR1-win32-x86_64;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\bin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\mingbin;${PWD}\\..\\..\\..\\toolchain\\windows\\i386-linux-gnueabi-gcc-4.6\\msys\\1.0\\bin +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/PWD/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/PWD/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/PWD/value=${ProjDirPath}/Debug_Windows +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/append=true +environment/project/cdt.managedbuild.config.gnu.so.debug.345774484/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/CWD/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/CWD/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/CWD/value=${ProjDirPath}/Release_Windows +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/PWD/delimiter=; +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/PWD/operation=replace +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/PWD/value=${ProjDirPath}/Release_Windows +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/append=true +environment/project/cdt.managedbuild.config.gnu.so.release.1065319080/appendContributed=true diff --git a/ssflib/dep/cryptocore/include/CC_API.h b/ssflib/dep/cryptocore/include/CC_API.h new file mode 100755 index 0000000..dd04a73 --- /dev/null +++ b/ssflib/dep/cryptocore/include/CC_API.h @@ -0,0 +1,243 @@ +/** + * \file CC_API.h + * @brief API of samsung Crypto Library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jae Heung Lee + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/06 + */ + +#ifndef _CRYPTOCORE_API_H +#define _CRYPTOCORE_API_H + +#include "CryptoCore.h" + +typedef union +{ + SDRM_X931Context *x931ctx; //RNG : ANSI X9.31 Context + SDRM_MD5Context *md5ctx; //Hash : MD5 Hash Context + SDRM_SHA1Context *sha1ctx; //Hash : SHA1 Hash Context + SDRM_SHA224Context *sha224ctx; //Hash : SHA224 Hash Context + SDRM_SHA256Context *sha256ctx; //Hash : SHA256 Hash Context +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context *sha384ctx; //Hash : SHA384 Hash Context + SDRM_SHA512Context *sha512ctx; //Hash : SHA512 Hash Context +#endif //_OP64_NOTSUPPORTED + SDRM_CMACContext *cmacctx; //MAC : C-MAC Context + SDRM_HMACContext *hmacctx; //MAC : Hash MAC + SDRM_DHContext *dhctx; //Key Exchange : DH Key Exchange Protocol + SDRM_ECDHContext *ecdhctx; //Key Exchange : EC-DH Key Exchange Protocol + SDRM_AESContext *aesctx; //Symmetric Encryption : AES Encryption Context + SDRM_DESContext *desctx; //Symmetric Encryption : DES Encryption Context + SDRM_TDESContext *tdesctx; //Symmetric Encryption : Triple DES Encryption Context + SDRM_RC4Context *rc4ctx; //Symmetric Encryption : RC4 Encryption Context + SDRM_SNOW2Context *snow2ctx; //Symmetric Encryption : SNOW2 Encryption Context + SDRM_RSAContext *rsactx; //Asymmetric Encryption and Signature : RSA Context + SDRM_DSAContext *dsactx; //Digital Signature : DSA Signature Context + SDRM_ECDSAContext *ecdsactx; //Digital Signature : EC-DSA Signature Context +} CryptoCoreCTX; + + +/** + * @brief Parameter sturcture + * + * Crypto Library¸¦ ½±°Ô »ç¿ëÇϱâ À§ÇØ »ç¿ëÇÏ´Â Parameter structure + */ +typedef struct _CryptoCoreContainer +{ + int alg; /**< Algorithm */ + CryptoCoreCTX *ctx; /**< Algorithm */ + + // Pseudo Random Number Generation (ANSI X9.17) + int (*PRNG_seed) (struct _CryptoCoreContainer *crt, cc_u8 *seed); + int (*PRNG_get) (struct _CryptoCoreContainer *crt, cc_u32 bitlength, cc_u8 *data); + + // Message Digest (MD5, SHA-1) + int (*MD_init) (struct _CryptoCoreContainer *crt); + int (*MD_update) (struct _CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + int (*MD_final) (struct _CryptoCoreContainer *crt, cc_u8 *output); + int (*MD_getHASH) (struct _CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + + // Message Authentication Code (CMAC, HMAC MD5, HMAC SHA-1) + int (*MAC_init) (struct _CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen); + int (*MAC_update) (struct _CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen); + int (*MAC_final) (struct _CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen); + int (*MAC_getMAC) (struct _CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen); + + // Key Exchange (DH, ECDH) + int (*DH_GenerateParam) (struct _CryptoCoreContainer *crt, cc_u8* pPrime, cc_u32 nPrimeLen, cc_u8* pGenerator); + int (*DH_SetParam) (struct _CryptoCoreContainer *crt, cc_u8* pPrime, cc_u32 nPrimeLen, cc_u8* nGenerator, cc_u32 nGeneratorLen); + int (*DH_Gen1stPhaseKey) (struct _CryptoCoreContainer *crt, cc_u8* pPriv, cc_u8* pPub); + int (*DH_GenAuthKey) (struct _CryptoCoreContainer *crt, cc_u8* pPriv, cc_u8* pPub, cc_u8* pSharedSecret); + int (*ECDH_Gen1stPhaseKey) (struct _CryptoCoreContainer *crt, cc_u8* pDH_Xk, cc_u8* pDH1stPhaseKey); + int (*ECDH_GenAuthKey) (struct _CryptoCoreContainer *crt, cc_u8* pchXk, cc_u8* pchYv, cc_u8* pchKauth); + + // Symmetric Encryption (DES, 3DES, AES, RC4, SNOW) + // mode example : ENC_ECB, DEC_ECB, ENC_CBC, DEC_CBC, ... + int (*SE_init) (struct _CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV); + int (*SE_process) (struct _CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + int (*SE_final) (struct _CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen); + // Simple AES Function + int (*SE_EncryptOneBlock) (cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey); + int (*SE_DecryptOneBlock) (cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey); + + // Asymmetric Encryption (RSA, Elgamal, EC-Elgamal) + int (*AE_encrypt) (struct _CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + int (*AE_decrypt) (struct _CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + int (*AE_decryptByCRT) (struct _CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + + // Digital Signature (DSA, EC-DSA) + int (*DS_sign) (struct _CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen); + int (*DS_verify) (struct _CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result); + int (*DSA_genParam)( + struct _CryptoCoreContainer *crt, cc_u32 T_Siz, + cc_u8 *DSA_P_Data, cc_u32 *DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 *DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 *DSA_G_Len + ); + int (*DSA_setParam)( + struct _CryptoCoreContainer *crt, + cc_u8 *DSA_P_Data, cc_u32 DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 DSA_G_Len + ); + int (*DSA_genKeypair)( + struct _CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 *DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 *DSA_X_Len + ); + int (*DSA_setKeyPair)( + struct _CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 DSA_X_Len + ); + + // RSA Support Functions + int (*RSA_genKeypair)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len + ); + int (*RSA_genKeypairWithEforCRT)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + cc_u8* RSA_DP_Data, cc_u32 *RSA_DP_Len, + cc_u8* RSA_DQ_Data, cc_u32 *RSA_DQ_Len, + cc_u8* RSA_QP_Data, cc_u32 *RSA_QP_Len + ); + int (*RSA_genKeypairWithE)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len + ); + int (*RSA_genKeyDWithPQE)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len + ); + int (*RSA_genKeypairForCRT)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + cc_u8* RSA_DmodP1_Data, cc_u32 *RSA_DmodP1_Len, + cc_u8* RSA_DmodQ1_Data, cc_u32 *RSA_DmodQ1_Len, + cc_u8* RSA_iQmodP_Data, cc_u32 *RSA_iQmodP_Len + ); + + int (*RSA_setKeypair)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 RSA_D_Len + ); + int (*RSA_setKeypairForCRT)( + struct _CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + cc_u8* RSA_DmodP1_Data, cc_u32 RSA_DmodP1_Len, + cc_u8* RSA_DmodQ1_Data, cc_u32 RSA_DmodQ1_Len, + cc_u8* RSA_iQmodP_Data, cc_u32 RSA_iQmodP_Len + ); + + // ECC Support Functions (EC-DSA, EC-Dlgamal) + int (*EC_setCurve)( + struct _CryptoCoreContainer *crt, cc_u16 Dimension, + cc_u8* ECC_P_Data, cc_u32 ECC_P_Len, + cc_u8* ECC_A_Data, cc_u32 ECC_A_Len, + cc_u8* ECC_B_Data, cc_u32 ECC_B_Len, + cc_u8* ECC_G_X_Data, cc_u32 ECC_G_X_Len, + cc_u8* ECC_G_Y_Data, cc_u32 ECC_G_Y_Len, + cc_u8* ECC_R_Data, cc_u32 ECC_R_Len + ); + int (*EC_genKeypair)( + struct _CryptoCoreContainer *crt, + cc_u8 *PrivateKey, cc_u32 *PrivateKeyLen, + cc_u8 *PublicKey_X, cc_u32 *PublicKey_XLen, + cc_u8 *PublicKey_Y, cc_u32 *PublicKey_YLen + ); + int (*EC_setKeypair)( + struct _CryptoCoreContainer *crt, + cc_u8* PRIV_Data, cc_u32 PRIV_Len, + cc_u8* PUB_X_Data, cc_u32 PUB_X_Len, + cc_u8* PUB_Y_Data, cc_u32 PUB_Y_Len + ); + +} CryptoCoreContainer; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn create_CryptoCoreContainer + * @brief memory allocation and initialize the CryptoCoreContainer sturcture + * + * @param algorithm [in]algorithm want to use + * + * @return address of created sturcture + */ +CryptoCoreContainer ECRYPTO_API *create_CryptoCoreContainer(cc_u32 algorithm); + +/* + * @fn destroy_CryptoCoreContainer + * @brief free allocated memory + * + * @param crt [in]CryptoCoreContainer context + * + * @return void + */ +void ECRYPTO_API destroy_CryptoCoreContainer(CryptoCoreContainer* crt); + +/* + * @fn CCMalloc + * @brief memory allocation and initialize for CryptoCore + * + * @param crt [in]size + */ +void ECRYPTO_API *CCMalloc(int siz); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/CC_Constants.h b/ssflib/dep/cryptocore/include/CC_Constants.h new file mode 100755 index 0000000..9195fe3 --- /dev/null +++ b/ssflib/dep/cryptocore/include/CC_Constants.h @@ -0,0 +1,162 @@ +/** + * \file CC_Constants.h + * @brief define constants for crypto library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon, Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/09/28 + * $Id$ + */ + +#ifndef _DRM_CONSTANTS_H +#define _DRM_CONSTANTS_H + +#define SDRM_SHIFT_HALF 16 /**< common value at both of 32-bit and 64-bit machine */ +#define SDRM_HIGH_HALF(A) ((A) >> SDRM_SHIFT_HALF) +#define SDRM_LOW_HALF(A) ((A) & ((1 << SDRM_SHIFT_HALF) - 1)) + +//////////////////////////////////////////////////////////////////////////// +// Algorithm Identifier +//////////////////////////////////////////////////////////////////////////// +enum CryptoAlgorithm { + /*! @brief RNG Module */ + ID_X931 = 1011, + + /*! @brief Hash Algorithms */ + ID_MD5 = 1021, + ID_SHA1 = 1022, + ID_SHA160 = 1022, + ID_SHA256 = 1023, +#ifndef _OP64_NOTSUPPORTED + ID_SHA384 = 1024, + ID_SHA512 = 1025, +#endif //_OP64_NOTSUPPORTED + ID_SHA224 = 1026, + + /*! @brief MAC Algorithms */ + ID_CMAC = 1031, + ID_HMD5 = 1032, + ID_HSHA1 = 1033, + ID_HSHA160 = 1033, + ID_HSHA256 = 1034, +#ifndef _OP64_NOTSUPPORTED + ID_HSHA384 = 1035, + ID_HSHA512 = 1036, +#endif //_OP64_NOTSUPPORTED + ID_HSHA224 = 1037, + + /*! @brief Symmetric Encryption Algorithms */ + ID_AES = 1041, + ID_AES128 = 1041, + ID_AES192 = 1047, + ID_AES256 = 1048, + ID_DES = 1042, + ID_TDES = 1043, + ID_TDES_EDE2 = 1043, + ID_TDES_EDE3 = 1044, + ID_RC4 = 1045, + ID_SNOW2 = 1046, + + /*! @brief Asymmetric Encryption Algorithms */ + ID_RSA = 1051, + ID_RSA512 = 1057, + ID_RSA1024 = 1054, + ID_RSA2048 = 1055, + ID_RSA3072 = 1056, + ID_ELGAMAL = 1052, + ID_ECELGAMAL = 1053, + + /*! @brief Signature Algorithms */ + ID_DSA = 1061, + ID_ECDSA = 1062, + + /*! @brief Key Exchange Algorithms */ + ID_DH = 1071, + ID_ECDH = 1072, + + /*! @brief Encryption/Decryption Mode of Operations */ + ID_ENC_ECB = 1111, + ID_ENC_CBC = 1112, + ID_ENC_CFB = 1113, + ID_ENC_OFB = 1114, + ID_ENC_CTR = 1115, + + ID_DEC_ECB = 1121, + ID_DEC_CBC = 1122, + ID_DEC_CFB = 1123, + ID_DEC_OFB = 1124, + ID_DEC_CTR = 1125, + + /*! @brief Symmetric Encryption/Decryption Padding Methods */ + ID_PKCS5 = 1201, + ID_SSL_PADDING = 1202, + ID_ZERO_PADDING = 1203, + ID_NO_PADDING = 1204, + + /*! @brief Asymmetric Encryption/Decryption Padding Methods */ + ID_RSAES_PKCS15 = 1131, + + ID_RSAES_OAEP = 1132, + ID_RSAES_OAEP_MD5 = ID_RSAES_OAEP + (ID_MD5 << SDRM_SHIFT_HALF), + ID_RSAES_OAEP_SHA1 = ID_RSAES_OAEP + (ID_SHA1 << SDRM_SHIFT_HALF), + ID_RSAES_OAEP_SHA160 = ID_RSAES_OAEP + (ID_SHA160 << SDRM_SHIFT_HALF), + ID_RSAES_OAEP_SHA224 = ID_RSAES_OAEP + (ID_SHA224 << SDRM_SHIFT_HALF), + ID_RSAES_OAEP_SHA256 = ID_RSAES_OAEP + (ID_SHA256 << SDRM_SHIFT_HALF), +#ifndef _OP64_NOTSUPPORTED + ID_RSAES_OAEP_SHA384 = ID_RSAES_OAEP + (ID_SHA384 << SDRM_SHIFT_HALF), + ID_RSAES_OAEP_SHA512 = ID_RSAES_OAEP + (ID_SHA512 << SDRM_SHIFT_HALF), +#endif + + ID_RSASSA_PKCS15 = 1133, + ID_RSASSA_PKCS15_MD5 = ID_RSASSA_PKCS15 + (ID_MD5 << SDRM_SHIFT_HALF), + ID_RSASSA_PKCS15_SHA1 = ID_RSASSA_PKCS15 + (ID_SHA1 << SDRM_SHIFT_HALF), + ID_RSASSA_PKCS15_SHA160 = ID_RSASSA_PKCS15 + (ID_SHA160 << SDRM_SHIFT_HALF), + ID_RSASSA_PKCS15_SHA224 = ID_RSASSA_PKCS15 + (ID_SHA224 << SDRM_SHIFT_HALF), + ID_RSASSA_PKCS15_SHA256 = ID_RSASSA_PKCS15 + (ID_SHA256 << SDRM_SHIFT_HALF), +#ifndef _OP64_NOTSUPPORTED + ID_RSASSA_PKCS15_SHA384 = ID_RSASSA_PKCS15 + (ID_SHA384 << SDRM_SHIFT_HALF), + ID_RSASSA_PKCS15_SHA512 = ID_RSASSA_PKCS15 + (ID_SHA512 << SDRM_SHIFT_HALF), +#endif + + ID_RSASSA_PSS = 1134, + ID_RSASSA_PSS_MD5 = ID_RSASSA_PSS + (ID_MD5 << SDRM_SHIFT_HALF), + ID_RSASSA_PSS_SHA1 = ID_RSASSA_PSS + (ID_SHA1 << SDRM_SHIFT_HALF), + ID_RSASSA_PSS_SHA160 = ID_RSASSA_PSS + (ID_SHA160 << SDRM_SHIFT_HALF), + ID_RSASSA_PSS_SHA224 = ID_RSASSA_PSS + (ID_SHA224 << SDRM_SHIFT_HALF), + ID_RSASSA_PSS_SHA256 = ID_RSASSA_PSS + (ID_SHA256 << SDRM_SHIFT_HALF), +#ifndef _OP64_NOTSUPPORTED + ID_RSASSA_PSS_SHA384 = ID_RSASSA_PSS + (ID_SHA384 << SDRM_SHIFT_HALF), + ID_RSASSA_PSS_SHA512 = ID_RSASSA_PSS + (ID_SHA512 << SDRM_SHIFT_HALF) +#endif +}; + +//////////////////////////////////////////////////////////////////////////// +// Constants Definitions +//////////////////////////////////////////////////////////////////////////// +/*! @brief Endianness */ +#define CRYPTO_LITTLE_ENDIAN 0 +#define CRYPTO_BIG_ENDIAN 1 + +//////////////////////////////////////////////////////////////////////////// +// Crypto Error Code +//////////////////////////////////////////////////////////////////////////// +#define CRYPTO_SUCCESS 0 /**< no error is occured */ +#define CRYPTO_ERROR -3000 /**< error is occured */ +#define CRYPTO_MEMORY_ALLOC_FAIL -3001 /**< malloc is failed */ +#define CRYPTO_NULL_POINTER -3002 /**< parameter is null pointer */ +#define CRYPTO_INVALID_ARGUMENT -3003 /**< argument is not correct */ +#define CRYPTO_MSG_TOO_LONG -3004 /**< length of input message is too long */ +#define CRYPTO_VALID_SIGN CRYPTO_SUCCESS /**< valid sign */ +#define CRYPTO_INVALID_SIGN -3011 /**< invalid sign */ +#define CRYPTO_ISPRIME CRYPTO_SUCCESS /**< prime number */ +#define CRYPTO_INVERSE_NOT_EXIST -3012 /**< inverse is no exists */ +#define CRYPTO_NEGATIVE_INPUT -3013 /**< argument is negative */ +#define CRYPTO_INFINITY_INPUT -3014 /**< input is infinity */ +#define CRYPTO_BUFFER_TOO_SMALL -3015 /**< buffer to small */ + +#endif + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/CC_Context.h b/ssflib/dep/cryptocore/include/CC_Context.h new file mode 100755 index 0000000..6d37833 --- /dev/null +++ b/ssflib/dep/cryptocore/include/CC_Context.h @@ -0,0 +1,387 @@ +/** + * \file CC_Context.h + * @brief context definitions for samsung Crypto Library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon, Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/07 + */ + +#ifndef _DRM_CONTEXT_H +#define _DRM_CONTEXT_H + +#include "CC_Type.h" + +//////////////////////////////////////////////////////////////////////////// +// constant & context for Big Number Operation +//////////////////////////////////////////////////////////////////////////// +/** + * @brief Big number structure + * + * used for big number representation + */ +typedef struct { + cc_u32 sign; /**< 0 for positive, 1 for negative number */ + cc_u32 Length; /**< number of valid integers */ + cc_u32 Size; /**< unsigned long size of allocated memory */ + cc_u32 *pData; /**< unsigned long array */ +} SDRM_BIG_NUM; + +/** + * @brief Parameter sturcture + * + * Montgomery ¾Ë°í¸®ÁòÀ» »ç¿ëÇϱâ À§ÇØ »ç¿ëÇÏ´Â Parameter structure + */ +typedef struct { /**< Structure to keep parameters for Montgomery */ + cc_u32 ri; /**< Length of Modulus */ + SDRM_BIG_NUM *R; /**< R^2 mod m */ + SDRM_BIG_NUM *Mod; /**< modulus */ + SDRM_BIG_NUM *Inv_Mod; /**< Inverse of Modulus */ + cc_u32 N0; /**< m' */ +} SDRM_BIG_MONT; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for Elliptic Curve Crypto System +//////////////////////////////////////////////////////////////////////////// +#define SDRM_ECC_BN_BUFSIZE 19 //allows max 256 bit curve(uint32_len * 2 + 3) +#define SDRM_ECC_ALLOC_SIZE (sizeof(SDRM_BIG_NUM) + SDRM_ECC_BN_BUFSIZE * SDRM_SIZE_OF_DWORD) + +/** + * @brief EC Point structure + * + * used for representation of one point at ECC curve + */ +typedef struct { + cc_u32 IsInfinity; /**< if infinity , then 1 else 0 */ + SDRM_BIG_NUM *x; /**< prime(1024 + 128i bits i=0..8) */ + SDRM_BIG_NUM *y; /**< subprime(128 + 32j bits j=0..4) */ + SDRM_BIG_NUM *z; + SDRM_BIG_NUM *z2; + SDRM_BIG_NUM *z3; +} SDRM_EC_POINT; + +/** + * @brief ECC Context structure + * + * used for parameters for ECC curve + */ +typedef struct { + cc_u32 uDimension; /**< Dimension */ + SDRM_BIG_NUM *ECC_p; /**< GF(p) */ + SDRM_BIG_NUM *ECC_a; /**< y^2 = x^3 + ax + b */ + SDRM_BIG_NUM *ECC_b; + SDRM_BIG_NUM *ECC_n; /**< order of base point */ + SDRM_EC_POINT *ECC_G; /**< Base point */ + SDRM_BIG_NUM *PRIV_KEY; /**< private key */ + SDRM_EC_POINT *PUBLIC_KEY; +} SDRM_ECC_CTX; + +typedef SDRM_ECC_CTX SDRM_ECDSAContext; +typedef SDRM_ECC_CTX SDRM_ECELContext; +typedef SDRM_ECC_CTX SDRM_ECDHContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for ANSI X9.31 PRNG +//////////////////////////////////////////////////////////////////////////// +#define SDRM_X931_SEED_SIZ 16 + +/** + * @brief X931 Context structure + * + * used for maintain seed vaule for random number generation + */ +typedef struct { + cc_u8 Seed[SDRM_X931_SEED_SIZ]; /**< Seed */ +} SDRM_X931Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for AES-128 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_AES_BLOCK_SIZ 16 + +/** + * @brief AES Context structure + * + * used for aes parameters + */ +typedef struct { + cc_u32 moo; /**< mode of operations */ + cc_u32 padding; /**< padding method */ + cc_u8 IV[SDRM_AES_BLOCK_SIZ]; /**< Initial Vector */ + cc_u8 Block[SDRM_AES_BLOCK_SIZ]; /**< remained msg block */ + cc_u32 BlockLen; /**< length of Block */ + cc_u8 RoundKey[16*(14 + 1)]; /**< round key */ + cc_u32 CTR_Count; /**< counter for CTR mode */ +} SDRM_AESContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for SHA-1 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_SHA1_BLOCK_SIZ 20 +#define SDRM_SHA1_DATA_SIZE 64 +/** + * @brief SHA1 Context structure + * + * used for SHA1 parameters + */ +typedef struct { + cc_u32 digest[SDRM_SHA1_BLOCK_SIZ / 4]; /**< Message digest */ + cc_u32 countLo, countHi; /**< 64-bit bit count */ + cc_u32 data[16]; /**< SHS data buffer */ + int Endianness; +} SDRM_SHA1Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for SHA-256 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_SHA256_BLOCK_SIZ 32 +#define SDRM_SHA256_DATA_SIZE (512 / 8) +/** + * @brief SHA256 Context structure + * + * used for SHA256 parameters + */ +typedef struct { + cc_u32 tot_len; + cc_u32 len; + cc_u8 block[2 * SDRM_SHA256_DATA_SIZE]; + cc_u32 h[8]; +} SDRM_SHA256Context; + +#ifndef _OP64_NOTSUPPORTED + +//////////////////////////////////////////////////////////////////////////// +// constant & context for SHA-384 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_SHA384_BLOCK_SIZ 48 +#define SDRM_SHA384_DATA_SIZE (1024 / 8) +/** + * @brief SHA384 Context structure + * + * used for SHA384 parameters + */ +typedef struct { + cc_u32 tot_len; + cc_u32 len; + cc_u8 block[2 * SDRM_SHA384_DATA_SIZE]; + cc_u64 h[8]; +} SDRM_SHA384Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for SHA-512 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_SHA512_BLOCK_SIZ 64 +#define SDRM_SHA512_DATA_SIZE SDRM_SHA384_DATA_SIZE +/** + * @brief SHA512 Context structure + * + * used for SHA512 parameters + */ +typedef SDRM_SHA384Context SDRM_SHA512Context; + +#endif //_OP64_NOTSUPPORTED + +//////////////////////////////////////////////////////////////////////////// +// constant & context for SHA-224 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_SHA224_BLOCK_SIZ 28 +#define SDRM_SHA224_DATA_SIZE SDRM_SHA256_DATA_SIZE +/** + * \brief SHA224 Context structure + * + * used for SHA224 parameters + */ +typedef SDRM_SHA256Context SDRM_SHA224Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for MD5 +//////////////////////////////////////////////////////////////////////////// +#define SDRM_MD5_BLOCK_SIZ 16 +#define SDRM_MD5_DATA_SIZE 64 +/** + * @brief MD5 Context structure + * + * used for MD5 parameters + */ +typedef struct { + cc_u32 state[4]; /**< state *ABCD */ + cc_u32 count[2]; /**< number of bits, modulo 2^64 (lsb first) */ + cc_u8 buffer[64]; /**< input buffer */ +} SDRM_MD5Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for C-MAC Generation +//////////////////////////////////////////////////////////////////////////// +/** + * @brief C-MAC Context structure + * + * used for aes parameters + */ +typedef struct { + cc_u8 IV[SDRM_AES_BLOCK_SIZ]; /**< Initial Vector */ + cc_u8 Block[SDRM_AES_BLOCK_SIZ]; /**< remained msg block */ + cc_u32 BlockLen; /**< length of Block */ + cc_u8 K1[SDRM_AES_BLOCK_SIZ]; + cc_u8 K2[SDRM_AES_BLOCK_SIZ]; + cc_u8 RoundKey[16*(10 + 1)]; +} SDRM_CMACContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for H-MAC Generation +//////////////////////////////////////////////////////////////////////////// +/** + * @brief C-MAC Context structure + * + * used for aes parameters + */ +typedef struct { + cc_u32 algorithm; /**< algorithm */ + SDRM_SHA1Context *sha1_ctx; /**< SHA-160 context */ + SDRM_SHA224Context *sha224_ctx; /**< SHA-224 context */ + SDRM_SHA256Context *sha256_ctx; /**< SHA-256 context */ +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context *sha384_ctx; /**< SHA-384 context */ + SDRM_SHA512Context *sha512_ctx; /**< SHA-512 context */ +#endif //_OP64_NOTSUPPORTED + SDRM_MD5Context *md5_ctx; /**< MD5 context */ + + cc_u32 B; + cc_u8 *k0; +} SDRM_HMACContext; + +//////////////////////////////////////////////////////////////////// +// constant & context for RSA +//////////////////////////////////////////////////////////////////////////// +#define SDRM_RSA_BN_BUFSIZE (RSA_KeyByteLen / 2 + 1) +#define SDRM_RSA_ALLOC_SIZE (sizeof(SDRM_BIG_NUM) + SDRM_RSA_BN_BUFSIZE * SDRM_SIZE_OF_DWORD) + +/** + * @brief RSA Context structure + * + * used for rsa parameters + */ +typedef struct { + SDRM_BIG_NUM* n; /**< n value */ + SDRM_BIG_NUM* e; /**< public key */ + SDRM_BIG_NUM* d; /**< private key */ + SDRM_BIG_NUM* p; /**< p */ + SDRM_BIG_NUM* q; /**< q */ + SDRM_BIG_NUM* dmodp1; /**< d mod p-1 */ + SDRM_BIG_NUM* dmodq1; /**< d mod q-1 */ + SDRM_BIG_NUM* iqmodp; /**< q^-1 mod p */ + + cc_u32 crt_operation; /**< CRT Algorithm indicator */ + cc_u32 k; /**< byte-length of n */ + cc_u32 pm; /**< padding method */ + cc_u32 hash_algorithm; /**< used hash algorithm for pkcs padding */ +} SDRM_RSAContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for DSA +//////////////////////////////////////////////////////////////////////////// +#define SDRM_DSA_BN_BUFSIZE (128 / 2 + 1) +#define SDRM_DSA_ALLOC_SIZE (sizeof(SDRM_BIG_NUM) + SDRM_DSA_BN_BUFSIZE * SDRM_SIZE_OF_DWORD) + +/** + * @brief Parameter sturcture + * + * used for DSA parameters + */ +typedef struct { + SDRM_BIG_NUM* p; /**< 'p' value - prime modulus */ + SDRM_BIG_NUM* q; /**< 'q' value - prime Divisor */ + SDRM_BIG_NUM* al; /**< 'alpha' value - generator */ + SDRM_BIG_NUM* y; /**< 'y' value - public key */ + SDRM_BIG_NUM* a; /**< 'a' value - private key */ +} SDRM_DSAContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for RC4 +//////////////////////////////////////////////////////////////////////////// +typedef struct { + cc_u32 keyLen; + + cc_u32 i; + cc_u32 j; + + cc_u8 s[256]; + cc_u8 key[32]; +} SDRM_RC4Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for SNOW2 +//////////////////////////////////////////////////////////////////////////// +typedef struct { + cc_u32 s[16]; + cc_u32 r1; + cc_u32 r2; + cc_u32 keyStream; + cc_u32 usedKeyLen; + + cc_u32 t; + cc_u32 endian; //0 if little endian, 1 if bigendian + +} SDRM_SNOW2Context; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for DES +//////////////////////////////////////////////////////////////////////////// +#define SDRM_DES_BLOCK_SIZ 8 + +/** + * @brief DES Context structure + * + * used for aes parameters + */ +typedef struct { + cc_u32 moo; //mode of operations + cc_u32 padding; + cc_u8 IV[SDRM_DES_BLOCK_SIZ]; //Initial Vector + cc_u8 UserKey[SDRM_DES_BLOCK_SIZ]; + cc_u8 Block[SDRM_DES_BLOCK_SIZ]; + cc_u32 BlockLen; + cc_u32 RoundKey[16][2]; //each round key, expanded + cc_u32 CTR_Count; +} SDRM_DESContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for Triple DES +//////////////////////////////////////////////////////////////////////////// +#define SDRM_TDES_BLOCK_SIZ SDRM_DES_BLOCK_SIZ + +/** + * @brief DES Context structure + * + * used for aes parameters + */ +typedef struct { + cc_u32 moo; //mode of operations + cc_u32 padding; + cc_u8 IV[SDRM_DES_BLOCK_SIZ]; //Initial Vector + cc_u8 UserKey[SDRM_DES_BLOCK_SIZ * 3]; + cc_u8 Block[SDRM_DES_BLOCK_SIZ]; + cc_u32 BlockLen; + cc_u32 RoundKey[48][2]; //each round key, expanded + cc_u32 CTR_Count; +} SDRM_TDESContext; + +//////////////////////////////////////////////////////////////////////////// +// constant & context for Deffie-Hellman protocol +//////////////////////////////////////////////////////////////////////////// +/** + * @brief Diffie-Hellman Context structure + * + * used for dh parameters + */ +typedef struct { + unsigned int PrimeLen; /**< length of prime */ + SDRM_BIG_NUM* p; /**< Prime */ + SDRM_BIG_NUM* g; /**< generator */ +} SDRM_DHContext; + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/CC_Type.h b/ssflib/dep/cryptocore/include/CC_Type.h new file mode 100755 index 0000000..1de5240 --- /dev/null +++ b/ssflib/dep/cryptocore/include/CC_Type.h @@ -0,0 +1,38 @@ +/** + * \file CC_Type.h + * @brief data types for CryptoCore library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2008/08/26 + */ + +#ifndef _CC_TYPE_H_ +#define _CC_TYPE_H_ + +/*! @brief 1-byte data type */ +typedef unsigned char cc_u8; + +/*! @brief 2-byte data type */ +typedef unsigned short cc_u16; + +/*! @brief 4-byte data type */ +typedef unsigned int cc_u32; + +#ifndef _OP64_NOTSUPPORTED + +/*! @brief 8-byte data type */ +#ifdef _WIN32 + typedef unsigned __int64 cc_u64; +#else + typedef unsigned long long cc_u64; +#endif //_WIN32 + +#endif //_OP64_NOTSUPPORTED + +#endif //_CC_TYPE_H_ + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/CryptoCore.h b/ssflib/dep/cryptocore/include/CryptoCore.h new file mode 100755 index 0000000..0b50f13 --- /dev/null +++ b/ssflib/dep/cryptocore/include/CryptoCore.h @@ -0,0 +1,51 @@ +/** + * \file CryptoCore.h + * @brief main header file of crypto library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/02 + */ + +#ifndef _CRYPTOCORE_H +#define _CRYPTOCORE_H + +#ifdef _USRDLL + #if defined(CRYPTOLIB_EXPORTS) + #define ECRYPTO_API __declspec(dllexport) + #elif defined(CRYPTOLIB_IMPORTS) + #define ECRYPTO_API __declspec(dllimport) + #else + #define ECRYPTO_API + #endif +#else + #define ECRYPTO_API +#endif + +//////////////////////////////////////////////////////////////////////////// +// Header File Include +//////////////////////////////////////////////////////////////////////////// +#include +#include +#include "CC_Type.h" +#include "drm_macro.h" +#include "CC_Constants.h" +#include "CC_Context.h" + +#ifdef _WIN32_WCE + #include +#else + #include +#endif + +//////////////////////////////////////////////////////////////////////////// +// Global Variable +//////////////////////////////////////////////////////////////////////////// + +#endif + +/***************************** End of File *****************************/ + diff --git a/ssflib/dep/cryptocore/include/base/cc_ANSI_x931.h b/ssflib/dep/cryptocore/include/base/cc_ANSI_x931.h new file mode 100755 index 0000000..4353322 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_ANSI_x931.h @@ -0,0 +1,49 @@ +/** + * \file ANSI_x931.h + * @brief Pseudorandom number generator based on a design described in ANSI X9.31 + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Junbum Shin + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/23 + */ + + +#ifndef _CCANSI_X931_H +#define _CCANSI_X931_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "CryptoCore.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_RNG_X931 + * @brief generate random number with seed + * + * @param Seed [in]seed for RNG System + * @param bitLength [in]bit length of data to generate + * @param data [out]generated data + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_RNG_X931(cc_u8 *Seed, cc_u32 bitLength, cc_u8 *data); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_aes.h b/ssflib/dep/cryptocore/include/base/cc_aes.h new file mode 100755 index 0000000..d969f74 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_aes.h @@ -0,0 +1,171 @@ +/** + * rijndael-alg-fst.h + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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 _CCAES_H +#define _CCAES_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_rijndaelKeySetupEnc + * @brief Expand the cipher key into the encryption key schedule + * + * @param rk [out]expanded round key + * @param cipherKey [in]user key + * @param keyBits [in]bit-length of cipherKey + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_rijndaelKeySetupEnc(cc_u32 rk[/*4*(Nr + 1)*/], const cc_u8 cipherKey[], int keyBits); + +/* + * @fn SDRM_rijndaelKeySetupDec + * @brief Expand the cipher key into the decryption key schedule + * + * @param rk [out]expanded round key + * @param cipherKey [in]user key + * @param keyBits [in]bit-length of cipherKey + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_rijndaelKeySetupDec(cc_u32 rk[/*4*(Nr + 1)*/], const cc_u8 cipherKey[], int keyBits); + +/* + * @fn SDRM_rijndaelEncrypt + * @brief 16 byte AES Encryption with round key + * + * @param rk [in]expanded round key + * @param Nr [in]numer of rounds + * @param pt [in]plain text + * @param ct [out]cipher text + * + * @return void + */ +void SDRM_rijndaelEncrypt(const cc_u32 rk[/*4*(Nr + 1)*/], int Nr, const cc_u8 pt[16], cc_u8 ct[16]); + +/* + * @fn SDRM_rijndaelDecrypt + * @brief 16 byte AES Decryption with round key + * + * @param rk [in]expanded round key + * @param Nr [in]numer of rounds + * @param ct [in]cipher text + * @param pt [out]plain text + * + * @return void + */ +void SDRM_rijndaelDecrypt(const cc_u32 rk[/*4*(Nr + 1)*/], int Nr, const cc_u8 ct[16], cc_u8 pt[16]); + +/* + * @fn SDRM_AES128_Encryption + * @brief AES-128 Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES128_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey); + +/* + * @fn SDRM_AES128_Decryption + * @brief AES-128 Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES128_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey); + +/* + * @fn SDRM_AES192_Encryption + * @brief AES-192 Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES192_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey); + +/* + * @fn SDRM_AES192_Decryption + * @brief AES-192 Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES192_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey); + +/* + * @fn SDRM_AES256_Encryption + * @brief AES-256 Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES256_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey); + +/* + * @fn SDRM_AES256_Decryption + * @brief AES-256 Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES256_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_bignum.h b/ssflib/dep/cryptocore/include/base/cc_bignum.h new file mode 100755 index 0000000..57dc235 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_bignum.h @@ -0,0 +1,697 @@ +/** + * \file bignum.h + * @brief big number library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/03 + */ + + +#ifndef _CCBIGNUM_H +#define _CCBIGNUM_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" + +//////////////////////////////////////////////////////////////////////////// +// Parameters and Bit-wise Macros +//////////////////////////////////////////////////////////////////////////// +/*! @brief byte-length of single cc_u32 */ +#define SDRM_SIZE_OF_DWORD 4 +/*! @brief bit-length of single cc_u32 */ +#define SDRM_BitsInDWORD (8 * SDRM_SIZE_OF_DWORD) +/*! @brief num_hex_simbols of single cc_u32 */ +#define SDRM_SIZE_BLOCK (2 * SDRM_SIZE_OF_DWORD) + +/*! @brief get k-th bit form cc_u32 array A */ +#define SDRM_CheckBitUINT32(A, k) (0x01 & ((A)[(k) >> 5] >> ((k) & 31))) + +/*! @brief get k-th byte from cc_u32 array A */ +#define SDRM_CheckByteUINT32(A, k) (cc_u8)(0xff & (A[(k) >> 2] >> (((k) & 3 ) << 3))) +#define SDRM_isEven0(X) (((X)[0] & 0x01) == 0) +#define SDRM_isOdd0(X) (((X)[0] & 0x01) == 1) + +/*! @brief increase 1 from Byte Array A, byte-length of B */ +#define SDRM_INC_BA(A, B) do { \ + for (i = 0; i < (B); i++) { \ + if (++A[i] != 0) break; \ + } \ + } while(0) \ + +//////////////////////////////////////////////////////////////////////////// +// MACROs for cc_u32 Evaluation +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_DIGIT_Mul(Dest, Src1, Src2) + * @brief Double-width UINT32 Multiplication + * @param Dest [out]destination, 2-cc_u32-size array + * @param Src1 [in]first element + * @param Src2 [in]second element + * + * @return void + */ +#ifndef _OP64_NOTSUPPORTED +#define SDRM_DIGIT_Mul(Dest, Src1, Src2) do { \ + (Dest)[0] = (cc_u32) ((cc_u64)(Src1) * (Src2)); \ + (Dest)[1] = (cc_u32)(((cc_u64)(Src1) * (Src2)) >> SDRM_BitsInDWORD); \ + } while(0) +#else +void SDRM_DIGIT_Mul(cc_u32 *Dest, cc_u32 Src1, cc_u32 Src2); +#endif + +/* + * @fn SDRM_DIGIT_Div(Src1, Src2, Div) + * @brief Doublue-width DWROD Division + * + * @param Src1 [in]upper-digit of dividend + * @param Src2 [in]lower-digit of dividend + * @param Div [in]divisor + */ +#ifndef _OP64_NOTSUPPORTED +#define SDRM_DIGIT_Div(Src1, Src2, Div) (cc_u32)((((cc_u64)(Src1) << SDRM_BitsInDWORD) ^ (Src2)) / (Div)) +#else +cc_u32 SDRM_DIGIT_Div(cc_u32 Src1, cc_u32 Src2, cc_u32 Div); +#endif + +/* + * @fn SDRM_DIGIT_Mod(Src1, Src2, Div) + * @brief Doublue-width DWROD Modular + * + * @param Src1 [in]upper-digit of dividend + * @param Src2 [in]lower-digit of dividend + * @param Div [in]divisor + */ +#ifndef _OP64_NOTSUPPORTED +#define SDRM_DIGIT_Mod(Src1, Src2, Div) (cc_u32)((((cc_u64)(Src1) << SDRM_BitsInDWORD) ^ (Src2)) % (Div)) +#else +cc_u32 SDRM_DIGIT_Mod(cc_u32 Src1, cc_u32 Src2, cc_u32 Div); +#endif + +/* + * @fn SDRM_DWD_Copy(Dest, Src, Size) + * @brief Copy Digit Array + * + * @param Dest [in]destination, cc_u32 array + * @param Src [in]source, cc_u32 array + * @param Size [in]length of dSrc + */ +#define SDRM_DWD_Copy(Dest, Src, Size) do { \ + memcpy(Dest, Src, SDRM_SIZE_OF_DWORD * Size); \ + } while(0) + +//////////////////////////////////////////////////////////////////////////// +// MACROs for Big Number +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_BN_IS_ODD(a) + * @brief check big number a is an odd number + */ +#define SDRM_BN_IS_ODD(a) ((a)->pData[0] & 1) + +/* + * @fn SDRM_BN_FREE(X) + * @brief free allocated memory + */ +#define SDRM_BN_FREE(X) do {if (X) free(X);} while(0) + +/* + * @fn SDRM_BN_OPTIMIZE_LENGTH(BN + * @brief optimize SDRM_BIG_NUM's length member + */ +#define SDRM_BN_OPTIMIZE_LENGTH(BN) do { \ + while((BN)->Length > 0) \ + if((BN)->pData[(BN)->Length - 1]) \ + break; \ + else \ + (BN)->Length--; \ + } while(0) +/* + * @fn SDRM_IS_BN_NEGATIVE(X) + * @brief check big number's sign + */ +#define SDRM_IS_BN_NEGATIVE(X) ((X)->sign) + +/*! @brief calc cc_u32-length when byte array is converted to cc_u32 array */ +#define SDRM_B2DLEN(X) ((X) > 0 ? (((X) - 1) >> 2) + 1 : 0) + +/*! @brief count byte-length of big number */ +#define SDRM_BN_GETBYTELEN(X, A) do { \ + if (!((X)->Length)) (A) = 0; \ + else { \ + (A) = (X)->Length * 4; \ + while(SDRM_CheckByteUINT32((X)->pData, (A) - 1) == 0) {(A) -= 1;} \ + } \ + } while(0) + +/*! @brief count bit-length of big number */ +#define SDRM_BN_GETBITLEN(X, A) do { \ + if (!((X)->Length)) (A) = 0; \ + else { \ + (A) = (X)->Length * SDRM_BitsInDWORD; \ + while(SDRM_CheckBitUINT32((X)->pData, (A) - 1) == 0) {(A) -= 1;} \ + } \ + } while(0) + +//////////////////////////////////////////////////////////////////////////// +// Global Variables +//////////////////////////////////////////////////////////////////////////// +/*! @brief some special big numbers */ +extern SDRM_BIG_NUM *BN_Zero, *BN_One; + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +int SDRM_DWD_Classical_REDC(cc_u32 *pdDest, cc_u32 DstLen, cc_u32 *pdModulus, cc_u32 ModLen); + +/* + * @fn int SDRM_BN2OS(SDRM_BIG_NUM *BN_Src, cc_u32 dDstLen, cc_u8 *pbDst) + * @brief Convert Big Number to Octet String + * + * @param BN_Src [in]source integer + * @param dDstLen [in]Byte-length of pbDst + * @param pbDst [out]output octet string + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if arrary is too small + */ +int SDRM_BN2OS(SDRM_BIG_NUM *BN_Src, cc_u32 dDstLen, cc_u8 *pbDst); + +/* + * @fn int SDRM_OS2BN(cc_u8* pbSrc, cc_u32 dSrcLen, SDRM_BIG_NUM *BN_Dst) + * @brief Convert Octet String to Big Number + * + * @param pbSrc [in]source octet string + * @param dSrcLen [in]Byte-length of pbSrc + * @param BN_Dst [out]output big number + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if arrary is too small + */ +int SDRM_OS2BN(cc_u8* pbSrc, cc_u32 dSrcLen, SDRM_BIG_NUM *BN_Dst); + +/* + * @fn int SDRM_I2OSP(SDRM_BIG_NUM *BN_Src, cc_u32 dDstLen, cc_u8 *pbDst) + * @brief Converts a nonnonegative integer to an octet string of a specified length + * + * @param BN_Src [in]nonnegative integer to be converted + * @param dDstLen [in]intended length of the resulting octet string + * @param pbDst [out]corresponding octet string of length dDstLen + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_I2OSP(SDRM_BIG_NUM *BN_Src, cc_u32 dDstLen, cc_u8 *pbDst); + +/* + * @fn int SDRM_BN_Clr(SDRM_BIG_NUM* BN_Src) + * @brief Clear the SDRM_BIG_NUM structure + * + * @param BN_Src [in]source + * + * @return CRYPTO_SUCCESS + */ +int SDRM_BN_Clr(SDRM_BIG_NUM* BN_Src); + +/* + * @fn int SDRM_BN_Copy(SDRM_BIG_NUM* BN_Dest, SDRM_BIG_NUM* BN_Src) + * @brief copy SDRM_BIG_NUM + * + * @param BN_Dest [out]destination + * @param BN_Src [in]source + * + * @return CRYPTO_SUCCESS + */ +int SDRM_BN_Copy(SDRM_BIG_NUM* BN_Dest, SDRM_BIG_NUM* BN_Src); + +/* + * @fn SDRM_BIG_NUM *SDRM_BN_Alloc(cc_u8* pbSrc, cc_u32 dSize) + * @brief allocate big number from buffer + * + * @param pbSrc [in]start pointer of buffer + * @param dSize [in]buffer size of big number + * + * @return pointer of SDRM_BIG_NUM structure + */ +SDRM_BIG_NUM *SDRM_BN_Alloc(cc_u8* pbSrc, cc_u32 dSize); + +/* + * @fn SDRM_BIG_NUM *SDRM_BN_Init(cc_u32 dSize) + * @brief Allocate a new big number object + * + * @param dSize [in]buffer size of big number + * + * @return pointer of SDRM_BIG_NUM structure + * \n NULL if memory allocation is failed + */ +SDRM_BIG_NUM *SDRM_BN_Init(cc_u32 dSize); + +/* + * @fn int SDRM_BN_Cmp(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) + * @brief Compare two Big Number + * + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return 1 if BN_Src1 is larger than pdSrc2 + * \n 0 if same + * \n -1 if BN_Src2 is larger than pdSrc1 + */ +int SDRM_BN_Cmp(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2); + +/* + * @fn int SDRM_BN_Cmp_sign(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) + * @brief Compare two Big Number considering sign + * + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return 1 if BN_Src1 is larger than pdSrc2 + * \n 0 if same + * \n -1 if BN_Src2 is larger than pdSrc1 + */ +int SDRM_BN_Cmp_sign(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2); + +/* + * @fn int SDRM_BN_Rand(SDRM_BIG_NUM *BN_Dst, cc_u32 BitLen) + * @brief Generate simple random number + * + * @param BN_Dst [out]destination + * @param BitLen [in]bit-length of generated random number + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_BN_Rand(SDRM_BIG_NUM *BN_Dst, cc_u32 BitLen); + +/* + * @fn int SDRM_BN_SHL(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, cc_u32 NumOfShift) + * @brief Big Number Shift Left + * + * @param BN_Dst [out]destination + * @param BN_Src [in]source + * @param NumOfShift [in]shift amount + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_BN_SHL(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, cc_u32 NumOfShift); + +/* + * @fn int SDRM_BN_SHR(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, cc_u32 NumOfShift) + * @brief Big Number Shift Right + * + * @param BN_Dst [out]destination + * @param BN_Src [in]source + * @param NumOfShift [in]shift amount + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_BN_SHR(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, cc_u32 NumOfShift); + +/* + * @fn int SDRM_BN_Add(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) + * @brief Big Number Addition + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Add(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2); + +/* + * @fn int SDRM_BN_Sub(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) + * @brief Big Number Subtraction + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Sub(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2); + +/* + * @fn int SDRM_BN_Mul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) + * @brief Big Number Multiplication + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Mul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2); + +/* + * @fn int SDRM_BN_Div(SDRM_BIG_NUM *BN_Quotient, SDRM_BIG_NUM *BN_Remainder, SDRM_BIG_NUM *BN_Dividend, SDRM_BIG_NUM *BN_Divisor) + * @brief Big Number Division + * + * @param BN_Quotient [out]quotient + * @param BN_Remainder [out]remainder + * @param BN_Dividend [in]dividend + * @param BN_Divisor [in]divisor + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Div(SDRM_BIG_NUM *BN_Quotient, SDRM_BIG_NUM *BN_Remainder, SDRM_BIG_NUM *BN_Dividend, SDRM_BIG_NUM *BN_Divisor); + +/* + * @fn int SDRM_BN_ModAdd(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Addition + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element of addition + * @param BN_Src2 [in]second element of addition + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModAdd(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn int SDRM_BN_ModSub(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Subtraction + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element of subtraction + * @param BN_Src2 [in]second element of subtraction + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModSub(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn int SDRM_BN_ModRed(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Reduction + * + * @param BN_Dst [out]destination + * @param BN_Src [in]source + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModRed(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn int SDRM_BN_ModMul(SDRM_BIG_NUM *BN_Res, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Multiplication + * + * @param BN_Res [out]destination + * @param BN_Src1 [in]first element of multiplication + * @param BN_Src2 [in]second element of multipliation + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModMul(SDRM_BIG_NUM *BN_Res, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn int SDRM_BN_ModInv(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Inverse + * + * @param BN_Dst [out]destination + * @param BN_Src [in]soure + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + * \n CRYPTO_NEGATIVE_INPUT if source is negative value + * \n CRYPTO_INVERSE_NOT_EXIST if inverse is not exists + */ +int SDRM_BN_ModInv(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn int SDRM_BN_ModExp(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Base, SDRM_BIG_NUM *BN_Exponent, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Exponentiation + * + * @param BN_Dst [out]destination + * @param BN_Base [in]base + * @param BN_Exponent [in]exponent + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_BN_ModExp(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Base, SDRM_BIG_NUM *BN_Exponent, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn int SDRM_BN_ModExp2(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Base, SDRM_BIG_NUM *BN_Exponent, SDRM_BIG_NUM *BN_Modulus) + * @brief Big Number Modular Exponentiation2 - Karen's method + * + * @param BN_Dst [out]destination + * @param BN_Base [in]base + * @param BN_Exponent [in]exponent + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_BN_ModExp2(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Base, SDRM_BIG_NUM *BN_Exponent, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn void SDRM_PrintBN(const char* s, SDRM_BIG_NUM* bn) + * @brief Show out a Big Number + * + * @param level [in]log level + * @param s [in]title + * @param bn [in]big number to show out + * + * @return void + */ +void SDRM_PrintBN(const char* s, SDRM_BIG_NUM* bn); + +int SDRM_BN_num_bits_index(SDRM_BIG_NUM *BN_Src, cc_u32 bitIndex); +int SDRM_UINT32_num_bits_index(cc_u32 *pdSrc, cc_u32 bitIndex); + + +/* + * @fn int SDRM_BN_num_bits(SDRM_BIG_NUM *BN_Src) + * @brief Calc bit-length of Big Number + * + * @param BN_Src [in]source + * + * @return bit-length + */ +int SDRM_BN_num_bits(SDRM_BIG_NUM *BN_Src); + +/* + * @fn int SDRM_UINT32_num_bits(cc_u32 *pdSrc) + * @brief Calc bit-length of cc_u32 + * + * @param pdSrc [in]source + * + * @return bit-length + */ +int SDRM_UINT32_num_bits(cc_u32 *pdSrc); + +/* + * @fn int SDRM_INT_num_bits(int Src) + * @brief Calc bit-length of integer + * + * @param Src [in]source + * + * @return bit-length + */ +int SDRM_INT_num_bits(int Src); + +/* + * @fn int SDRM_MONT_Mul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_MONT *Mont) + * @brief Montgomery Multiplication + * + * @param BN_Dst [out]destination, montgomery number + * @param BN_Src1 [in]first element, montgomery number + * @param BN_Src2 [in]second element, montgomery number + * @param Mont [in]montgomery parameters + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_MONT_Mul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_MONT *Mont); + +/* + * @fn SDRM_MONT_Zn2rzn(DST, SRC1, MONT) + * @brief Convert normal number to Montgomery number + * @param Dst [out]destination, montgomery number + * @param SRC1 [in]source, normal number + * @param MONT [in]montgomery parameters + * @return CRYPTO_SUCCESS if no error occured + */ +#define SDRM_MONT_Zn2rzn(DST, SRC1, MONT) SDRM_MONT_Mul(DST, SRC1, (MONT)->R, MONT) + +/* + * @fn int SDRM_MONT_Rzn2zn(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_MONT *Mont) + * @brief Convert Montgomery number to normal number + * + * @param BN_Dst [out]destination, normal number + * @param BN_Src1 [in]source, montgomery number + * @param Mont [in]montgomery parameters + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_MONT_Rzn2zn(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_MONT *Mont); + +/* + * @fn SDRM_BIG_MONT *SDRM_MONT_Init(cc_u32 dSize) + * @brief Allocate new momory for Montgomery parameter + * + * @param dSize [in]size of buffer of big number + * + * @return Pointer to created structure + * \n NULL if malloc failed + */ +SDRM_BIG_MONT *SDRM_MONT_Init(cc_u32 dSize); + +/* + * @fn int SDRM_MONT_Set(SDRM_BIG_MONT *Mont, SDRM_BIG_NUM *BN_Modulus) + * @brief Set Montgomery parameters + * + * @param Mont [out]montgomery parameter + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n BN_NOT_ENOUGHT_BUFFER if malloc is failed + * \n CRYPTO_INVERSE_NOT_EXIST if inverse is not exists + */ +int SDRM_MONT_Set(SDRM_BIG_MONT *Mont, SDRM_BIG_NUM *BN_Modulus); + +/* + * @fn void SDRM_MONT_Free(SDRM_BIG_MONT *Mont) + * @brief Free allocated memory for montgomery paramter + * + * @param Mont [in]montgomery parameters + * + * @return void + */ +void SDRM_MONT_Free(SDRM_BIG_MONT *Mont); + +/* + * @fn int SDRM_BN_CheckRelativelyPrime(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) + * @brief get gcd of two big number + * + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_ISPRIME if two elements are relatively prime + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR otherwise + */ +int SDRM_BN_CheckRelativelyPrime(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2); + +/* + * @fn int SDRM_BN_MILLER_RABIN(SDRM_BIG_NUM* n, cc_u32 t) + * @brief MILLER_RABIN Test + * + * @param n [in]value to test + * @param t [in]security parameter + * + * @return CRYPTO_ISPRIME if n is (probably) prime + * \n CRYPTO_INVALID_ARGUMENT if n is composite + */ +int SDRM_BN_MILLER_RABIN(SDRM_BIG_NUM* n, cc_u32 t); + +/* + * @fn int SDRM_HEX2BN(cc_u8* pbSrc, SDRM_BIG_NUM *BN_Dst) + * @brief Convert Hex String to Big Number + * + * @param pbSrc [in]source hex string + * @param BN_Dst [out]output big number + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if arrary is too small + */ +int SDRM_HEX2BN(cc_u8* pbSrc, SDRM_BIG_NUM *BN_Dst); + +/* + * @fn cc_u8 * SDRM_BN2STRBIN(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src); + * @brief Convert Big Number to binary String + * + * @param pbSrc [in]source big number + * @param BN_Dst [out]output numberBits of uot string + * + * @return (cc_u8 *) binary string + */ +cc_u8 * SDRM_BN2STRBIN(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src); + +/* + * @fn int SDRM_BN_SetWord(SDRM_BIG_NUM *BN_Dst, cc_u32 t); + * @brief Set word to Big Number + * + * @param pbSrc [in]source word + * @param BN_Dst [out]output Big Nubmer + * + * @return CRYPTO_SUCCESS if no error is occuredg + */ +int SDRM_BN_SetWord(SDRM_BIG_NUM *BN_Dst, cc_u32 t); + +/* + * @fn int SDRM_BN_isZero(SDRM_BIG_NUM *BN_Src); + * @brief check big number is zero + * + * @param pbSrc [in]source big number + * + * @return 0 - false, 1 - true + */ +int SDRM_BN_isZero(SDRM_BIG_NUM *BN_Src); + +/* + * @fn cc_u8 * SDRM_BN2STRFOUR(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src); + * @brief Convert Big Number to four String + * + * @param pbSrc [in]source big number + * @param BN_Dst [out]output numberBits of four string + * + * @return (cc_u8 *) four string + */ +cc_u8 * SDRM_BN2STRFOUR(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src); + +/* + * @fn SDRM_BN_MassInit + * @brief Allocate a series of big number object + * + * @param dBufSize [in]buffer size of each big number + * @param count [in]number BigNumbers + * + * @return double pointer of SDRM_BIG_NUM structure + * \n NULL if memory allocation is failed + */ +SDRM_BIG_NUM **SDRM_BN_MassInit(cc_u32 dBufSize, cc_u32 count); + +/* + * @fn SDRM_BN_IntInit + * @brief Allocate a big number object and assign an integer value + * + * @param dSize [in]buffer size of each big number + * @param data [in]integer value + * + * @return double pointer of SDRM_BIG_NUM structure + * \n NULL if memory allocation is failed + */ +SDRM_BIG_NUM *SDRM_BN_IntInit(cc_u32 dSize, cc_u32 data); + +#ifdef __cplusplus +} +#endif + +#endif // _BIGNUM_H + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/base/cc_des.h b/ssflib/dep/cryptocore/include/base/cc_des.h new file mode 100755 index 0000000..9523ed8 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_des.h @@ -0,0 +1,412 @@ +/** + * \file des.h + * @brief high-speed implementation of DES + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/06 + */ + + +#ifndef _CCDES_H +#define _CCDES_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" + +//////////////////////////////////////////////////////////////////////////// +// Define Constants +//////////////////////////////////////////////////////////////////////////// +#define SDRM_DES_NUM_OF_ROUNDS 16 + +//////////////////////////////////////////////////////////////////////////// +// Macros +//////////////////////////////////////////////////////////////////////////// +/*! @brief circular left and right shifts for cc_u32 */ +#ifdef _MSC_VER + #define SDRM_rotl32(A, B) _lrotl((A), (B)) + #define SDRM_rotr32(A, B) _lrotr((A), (B)) +#else + #define SDRM_rotl32(A, B) (((A) << (B)) + ((A) >> (32 - (B)))) + #define SDRM_rotr32(A, B) (((A) >> (B)) + ((A) << (32 - (B)))) +#endif + +/*! @brief permutation operation */ +#define SDRM_PERM_OP(a,b,t,n,m) { \ + (t) = ((((a)>>(n))^(b))&(m)); \ + (b) ^= (t); \ + (a) ^= ((t)<<(n)); \ +} + +/*! @brief initial permutation */ +#define SDRM_IP(l,r) { \ + cc_u32 tt; \ + SDRM_PERM_OP(r,l,tt, 4,0x0f0f0f0f); \ + SDRM_PERM_OP(l,r,tt,16,0x0000ffff); \ + SDRM_PERM_OP(r,l,tt, 2,0x33333333); \ + SDRM_PERM_OP(l,r,tt, 8,0x00ff00ff); \ + SDRM_PERM_OP(r,l,tt, 1,0x55555555); \ +} + +/*! @brief inverse of initial permutation */ +#define SDRM_INV_IP(l,r) { \ + cc_u32 tt; \ + SDRM_PERM_OP(l,r,tt, 1,0x55555555); \ + SDRM_PERM_OP(r,l,tt, 8,0x00ff00ff); \ + SDRM_PERM_OP(l,r,tt, 2,0x33333333); \ + SDRM_PERM_OP(r,l,tt,16,0x0000ffff); \ + SDRM_PERM_OP(l,r,tt, 4,0x0f0f0f0f); \ +} + +/*! @brief encrypt one round */ +#define SDRM_D_ENCRYPT(L,R) { \ + u = R ^ RoundKey[i][0]; \ + t = R ^ RoundKey[i][1]; \ + t = SDRM_rotr32(t, 4); \ + L^= SDRM_DES_SPtrans[0][(u >> 2U) & 0x3f]^ \ + SDRM_DES_SPtrans[2][(u >> 10U) & 0x3f]^ \ + SDRM_DES_SPtrans[4][(u >> 18U) & 0x3f]^ \ + SDRM_DES_SPtrans[6][(u >> 26U) & 0x3f]^ \ + SDRM_DES_SPtrans[1][(t >> 2U) & 0x3f]^ \ + SDRM_DES_SPtrans[3][(t >> 10U) & 0x3f]^ \ + SDRM_DES_SPtrans[5][(t >> 18U) & 0x3f]^ \ + SDRM_DES_SPtrans[7][(t >> 26U) & 0x3f]; \ +} + +//////////////////////////////////////////////////////////////////////////// +// static values - specified in FIPS 46 +//////////////////////////////////////////////////////////////////////////// +static const cc_u8 SDRM_DES_KS_SHIFT[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; + +static const cc_u32 SDRM_DES_BitMask[] = { + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +static const cc_u8 SDRM_DES_KS_PC1[] = { + 56, 48, 40, 32, 24, 16, 8, + 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, + 18, 10, 2, 59, 51, 43, 35, + + 62, 54, 46, 38, 30, 22, 14, + 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, + 20, 12, 4, 27, 19, 11, 3 +}; + +static const cc_u32 SDRM_des_skb[8][64]={ + { + /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L,0x00000010L,0x20000000L,0x20000010L, + 0x00010000L,0x00010010L,0x20010000L,0x20010010L, + 0x00000800L,0x00000810L,0x20000800L,0x20000810L, + 0x00010800L,0x00010810L,0x20010800L,0x20010810L, + 0x00000020L,0x00000030L,0x20000020L,0x20000030L, + 0x00010020L,0x00010030L,0x20010020L,0x20010030L, + 0x00000820L,0x00000830L,0x20000820L,0x20000830L, + 0x00010820L,0x00010830L,0x20010820L,0x20010830L, + 0x00080000L,0x00080010L,0x20080000L,0x20080010L, + 0x00090000L,0x00090010L,0x20090000L,0x20090010L, + 0x00080800L,0x00080810L,0x20080800L,0x20080810L, + 0x00090800L,0x00090810L,0x20090800L,0x20090810L, + 0x00080020L,0x00080030L,0x20080020L,0x20080030L, + 0x00090020L,0x00090030L,0x20090020L,0x20090030L, + 0x00080820L,0x00080830L,0x20080820L,0x20080830L, + 0x00090820L,0x00090830L,0x20090820L,0x20090830L, + }, + { + /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000L,0x02000000L,0x00002000L,0x02002000L, + 0x00200000L,0x02200000L,0x00202000L,0x02202000L, + 0x00000004L,0x02000004L,0x00002004L,0x02002004L, + 0x00200004L,0x02200004L,0x00202004L,0x02202004L, + 0x00000400L,0x02000400L,0x00002400L,0x02002400L, + 0x00200400L,0x02200400L,0x00202400L,0x02202400L, + 0x00000404L,0x02000404L,0x00002404L,0x02002404L, + 0x00200404L,0x02200404L,0x00202404L,0x02202404L, + 0x10000000L,0x12000000L,0x10002000L,0x12002000L, + 0x10200000L,0x12200000L,0x10202000L,0x12202000L, + 0x10000004L,0x12000004L,0x10002004L,0x12002004L, + 0x10200004L,0x12200004L,0x10202004L,0x12202004L, + 0x10000400L,0x12000400L,0x10002400L,0x12002400L, + 0x10200400L,0x12200400L,0x10202400L,0x12202400L, + 0x10000404L,0x12000404L,0x10002404L,0x12002404L, + 0x10200404L,0x12200404L,0x10202404L,0x12202404L, + }, + { + /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000L,0x00000001L,0x00040000L,0x00040001L, + 0x01000000L,0x01000001L,0x01040000L,0x01040001L, + 0x00000002L,0x00000003L,0x00040002L,0x00040003L, + 0x01000002L,0x01000003L,0x01040002L,0x01040003L, + 0x00000200L,0x00000201L,0x00040200L,0x00040201L, + 0x01000200L,0x01000201L,0x01040200L,0x01040201L, + 0x00000202L,0x00000203L,0x00040202L,0x00040203L, + 0x01000202L,0x01000203L,0x01040202L,0x01040203L, + 0x08000000L,0x08000001L,0x08040000L,0x08040001L, + 0x09000000L,0x09000001L,0x09040000L,0x09040001L, + 0x08000002L,0x08000003L,0x08040002L,0x08040003L, + 0x09000002L,0x09000003L,0x09040002L,0x09040003L, + 0x08000200L,0x08000201L,0x08040200L,0x08040201L, + 0x09000200L,0x09000201L,0x09040200L,0x09040201L, + 0x08000202L,0x08000203L,0x08040202L,0x08040203L, + 0x09000202L,0x09000203L,0x09040202L,0x09040203L, + }, + { + /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000L,0x00100000L,0x00000100L,0x00100100L, + 0x00000008L,0x00100008L,0x00000108L,0x00100108L, + 0x00001000L,0x00101000L,0x00001100L,0x00101100L, + 0x00001008L,0x00101008L,0x00001108L,0x00101108L, + 0x04000000L,0x04100000L,0x04000100L,0x04100100L, + 0x04000008L,0x04100008L,0x04000108L,0x04100108L, + 0x04001000L,0x04101000L,0x04001100L,0x04101100L, + 0x04001008L,0x04101008L,0x04001108L,0x04101108L, + 0x00020000L,0x00120000L,0x00020100L,0x00120100L, + 0x00020008L,0x00120008L,0x00020108L,0x00120108L, + 0x00021000L,0x00121000L,0x00021100L,0x00121100L, + 0x00021008L,0x00121008L,0x00021108L,0x00121108L, + 0x04020000L,0x04120000L,0x04020100L,0x04120100L, + 0x04020008L,0x04120008L,0x04020108L,0x04120108L, + 0x04021000L,0x04121000L,0x04021100L,0x04121100L, + 0x04021008L,0x04121008L,0x04021108L,0x04121108L, + }, + { + /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000L,0x10000000L,0x00010000L,0x10010000L, + 0x00000004L,0x10000004L,0x00010004L,0x10010004L, + 0x20000000L,0x30000000L,0x20010000L,0x30010000L, + 0x20000004L,0x30000004L,0x20010004L,0x30010004L, + 0x00100000L,0x10100000L,0x00110000L,0x10110000L, + 0x00100004L,0x10100004L,0x00110004L,0x10110004L, + 0x20100000L,0x30100000L,0x20110000L,0x30110000L, + 0x20100004L,0x30100004L,0x20110004L,0x30110004L, + 0x00001000L,0x10001000L,0x00011000L,0x10011000L, + 0x00001004L,0x10001004L,0x00011004L,0x10011004L, + 0x20001000L,0x30001000L,0x20011000L,0x30011000L, + 0x20001004L,0x30001004L,0x20011004L,0x30011004L, + 0x00101000L,0x10101000L,0x00111000L,0x10111000L, + 0x00101004L,0x10101004L,0x00111004L,0x10111004L, + 0x20101000L,0x30101000L,0x20111000L,0x30111000L, + 0x20101004L,0x30101004L,0x20111004L,0x30111004L, + }, + { + /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000L,0x08000000L,0x00000008L,0x08000008L, + 0x00000400L,0x08000400L,0x00000408L,0x08000408L, + 0x00020000L,0x08020000L,0x00020008L,0x08020008L, + 0x00020400L,0x08020400L,0x00020408L,0x08020408L, + 0x00000001L,0x08000001L,0x00000009L,0x08000009L, + 0x00000401L,0x08000401L,0x00000409L,0x08000409L, + 0x00020001L,0x08020001L,0x00020009L,0x08020009L, + 0x00020401L,0x08020401L,0x00020409L,0x08020409L, + 0x02000000L,0x0A000000L,0x02000008L,0x0A000008L, + 0x02000400L,0x0A000400L,0x02000408L,0x0A000408L, + 0x02020000L,0x0A020000L,0x02020008L,0x0A020008L, + 0x02020400L,0x0A020400L,0x02020408L,0x0A020408L, + 0x02000001L,0x0A000001L,0x02000009L,0x0A000009L, + 0x02000401L,0x0A000401L,0x02000409L,0x0A000409L, + 0x02020001L,0x0A020001L,0x02020009L,0x0A020009L, + 0x02020401L,0x0A020401L,0x02020409L,0x0A020409L, + }, + { + /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000L,0x00000100L,0x00080000L,0x00080100L, + 0x01000000L,0x01000100L,0x01080000L,0x01080100L, + 0x00000010L,0x00000110L,0x00080010L,0x00080110L, + 0x01000010L,0x01000110L,0x01080010L,0x01080110L, + 0x00200000L,0x00200100L,0x00280000L,0x00280100L, + 0x01200000L,0x01200100L,0x01280000L,0x01280100L, + 0x00200010L,0x00200110L,0x00280010L,0x00280110L, + 0x01200010L,0x01200110L,0x01280010L,0x01280110L, + 0x00000200L,0x00000300L,0x00080200L,0x00080300L, + 0x01000200L,0x01000300L,0x01080200L,0x01080300L, + 0x00000210L,0x00000310L,0x00080210L,0x00080310L, + 0x01000210L,0x01000310L,0x01080210L,0x01080310L, + 0x00200200L,0x00200300L,0x00280200L,0x00280300L, + 0x01200200L,0x01200300L,0x01280200L,0x01280300L, + 0x00200210L,0x00200310L,0x00280210L,0x00280310L, + 0x01200210L,0x01200310L,0x01280210L,0x01280310L, + }, + { + /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000L,0x04000000L,0x00040000L,0x04040000L, + 0x00000002L,0x04000002L,0x00040002L,0x04040002L, + 0x00002000L,0x04002000L,0x00042000L,0x04042000L, + 0x00002002L,0x04002002L,0x00042002L,0x04042002L, + 0x00000020L,0x04000020L,0x00040020L,0x04040020L, + 0x00000022L,0x04000022L,0x00040022L,0x04040022L, + 0x00002020L,0x04002020L,0x00042020L,0x04042020L, + 0x00002022L,0x04002022L,0x00042022L,0x04042022L, + 0x00000800L,0x04000800L,0x00040800L,0x04040800L, + 0x00000802L,0x04000802L,0x00040802L,0x04040802L, + 0x00002800L,0x04002800L,0x00042800L,0x04042800L, + 0x00002802L,0x04002802L,0x00042802L,0x04042802L, + 0x00000820L,0x04000820L,0x00040820L,0x04040820L, + 0x00000822L,0x04000822L,0x00040822L,0x04040822L, + 0x00002820L,0x04002820L,0x00042820L,0x04042820L, + 0x00002822L,0x04002822L,0x00042822L,0x04042822L, + } +}; + +static const cc_u32 SDRM_DES_SPtrans[8][64]={ + // nibble 0 + { + 0x02080800, 0x00080000, 0x02000002, 0x02080802, 0x02000000, 0x00080802, 0x00080002, 0x02000002, + 0x00080802, 0x02080800, 0x02080000, 0x00000802, 0x02000802, 0x02000000, 0x00000000, 0x00080002, + 0x00080000, 0x00000002, 0x02000800, 0x00080800, 0x02080802, 0x02080000, 0x00000802, 0x02000800, + 0x00000002, 0x00000800, 0x00080800, 0x02080002, 0x00000800, 0x02000802, 0x02080002, 0x00000000, + 0x00000000, 0x02080802, 0x02000800, 0x00080002, 0x02080800, 0x00080000, 0x00000802, 0x02000800, + 0x02080002, 0x00000800, 0x00080800, 0x02000002, 0x00080802, 0x00000002, 0x02000002, 0x02080000, + 0x02080802, 0x00080800, 0x02080000, 0x02000802, 0x02000000, 0x00000802, 0x00080002, 0x00000000, + 0x00080000, 0x02000000, 0x02000802, 0x02080800, 0x00000002, 0x02080002, 0x00000800, 0x00080802 + }, + // nibble 1 + { + 0x40108010, 0x00000000, 0x00108000, 0x40100000, 0x40000010, 0x00008010, 0x40008000, 0x00108000, + 0x00008000, 0x40100010, 0x00000010, 0x40008000, 0x00100010, 0x40108000, 0x40100000, 0x00000010, + 0x00100000, 0x40008010, 0x40100010, 0x00008000, 0x00108010, 0x40000000, 0x00000000, 0x00100010, + 0x40008010, 0x00108010, 0x40108000, 0x40000010, 0x40000000, 0x00100000, 0x00008010, 0x40108010, + 0x00100010, 0x40108000, 0x40008000, 0x00108010, 0x40108010, 0x00100010, 0x40000010, 0x00000000, + 0x40000000, 0x00008010, 0x00100000, 0x40100010, 0x00008000, 0x40000000, 0x00108010, 0x40008010, + 0x40108000, 0x00008000, 0x00000000, 0x40000010, 0x00000010, 0x40108010, 0x00108000, 0x40100000, + 0x40100010, 0x00100000, 0x00008010, 0x40008000, 0x40008010, 0x00000010, 0x40100000, 0x00108000 + }, + // nibble 2 + { + 0x04000001, 0x04040100, 0x00000100, 0x04000101, 0x00040001, 0x04000000, 0x04000101, 0x00040100, + 0x04000100, 0x00040000, 0x04040000, 0x00000001, 0x04040101, 0x00000101, 0x00000001, 0x04040001, + 0x00000000, 0x00040001, 0x04040100, 0x00000100, 0x00000101, 0x04040101, 0x00040000, 0x04000001, + 0x04040001, 0x04000100, 0x00040101, 0x04040000, 0x00040100, 0x00000000, 0x04000000, 0x00040101, + 0x04040100, 0x00000100, 0x00000001, 0x00040000, 0x00000101, 0x00040001, 0x04040000, 0x04000101, + 0x00000000, 0x04040100, 0x00040100, 0x04040001, 0x00040001, 0x04000000, 0x04040101, 0x00000001, + 0x00040101, 0x04000001, 0x04000000, 0x04040101, 0x00040000, 0x04000100, 0x04000101, 0x00040100, + 0x04000100, 0x00000000, 0x04040001, 0x00000101, 0x04000001, 0x00040101, 0x00000100, 0x04040000 + }, + // nibble 3 + { + 0x00401008, 0x10001000, 0x00000008, 0x10401008, 0x00000000, 0x10400000, 0x10001008, 0x00400008, + 0x10401000, 0x10000008, 0x10000000, 0x00001008, 0x10000008, 0x00401008, 0x00400000, 0x10000000, + 0x10400008, 0x00401000, 0x00001000, 0x00000008, 0x00401000, 0x10001008, 0x10400000, 0x00001000, + 0x00001008, 0x00000000, 0x00400008, 0x10401000, 0x10001000, 0x10400008, 0x10401008, 0x00400000, + 0x10400008, 0x00001008, 0x00400000, 0x10000008, 0x00401000, 0x10001000, 0x00000008, 0x10400000, + 0x10001008, 0x00000000, 0x00001000, 0x00400008, 0x00000000, 0x10400008, 0x10401000, 0x00001000, + 0x10000000, 0x10401008, 0x00401008, 0x00400000, 0x10401008, 0x00000008, 0x10001000, 0x00401008, + 0x00400008, 0x00401000, 0x10400000, 0x10001008, 0x00001008, 0x10000000, 0x10000008, 0x10401000 + }, + // nibble 4 + { + 0x08000000, 0x00010000, 0x00000400, 0x08010420, 0x08010020, 0x08000400, 0x00010420, 0x08010000, + 0x00010000, 0x00000020, 0x08000020, 0x00010400, 0x08000420, 0x08010020, 0x08010400, 0x00000000, + 0x00010400, 0x08000000, 0x00010020, 0x00000420, 0x08000400, 0x00010420, 0x00000000, 0x08000020, + 0x00000020, 0x08000420, 0x08010420, 0x00010020, 0x08010000, 0x00000400, 0x00000420, 0x08010400, + 0x08010400, 0x08000420, 0x00010020, 0x08010000, 0x00010000, 0x00000020, 0x08000020, 0x08000400, + 0x08000000, 0x00010400, 0x08010420, 0x00000000, 0x00010420, 0x08000000, 0x00000400, 0x00010020, + 0x08000420, 0x00000400, 0x00000000, 0x08010420, 0x08010020, 0x08010400, 0x00000420, 0x00010000, + 0x00010400, 0x08010020, 0x08000400, 0x00000420, 0x00000020, 0x00010420, 0x08010000, 0x08000020 + }, + // nibble 5 + { + 0x80000040, 0x00200040, 0x00000000, 0x80202000, 0x00200040, 0x00002000, 0x80002040, 0x00200000, + 0x00002040, 0x80202040, 0x00202000, 0x80000000, 0x80002000, 0x80000040, 0x80200000, 0x00202040, + 0x00200000, 0x80002040, 0x80200040, 0x00000000, 0x00002000, 0x00000040, 0x80202000, 0x80200040, + 0x80202040, 0x80200000, 0x80000000, 0x00002040, 0x00000040, 0x00202000, 0x00202040, 0x80002000, + 0x00002040, 0x80000000, 0x80002000, 0x00202040, 0x80202000, 0x00200040, 0x00000000, 0x80002000, + 0x80000000, 0x00002000, 0x80200040, 0x00200000, 0x00200040, 0x80202040, 0x00202000, 0x00000040, + 0x80202040, 0x00202000, 0x00200000, 0x80002040, 0x80000040, 0x80200000, 0x00202040, 0x00000000, + 0x00002000, 0x80000040, 0x80002040, 0x80202000, 0x80200000, 0x00002040, 0x00000040, 0x80200040 + }, + + // nibble 6 + { + 0x00004000, 0x00000200, 0x01000200, 0x01000004, 0x01004204, 0x00004004, 0x00004200, 0x00000000, + 0x01000000, 0x01000204, 0x00000204, 0x01004000, 0x00000004, 0x01004200, 0x01004000, 0x00000204, + 0x01000204, 0x00004000, 0x00004004, 0x01004204, 0x00000000, 0x01000200, 0x01000004, 0x00004200, + 0x01004004, 0x00004204, 0x01004200, 0x00000004, 0x00004204, 0x01004004, 0x00000200, 0x01000000, + 0x00004204, 0x01004000, 0x01004004, 0x00000204, 0x00004000, 0x00000200, 0x01000000, 0x01004004, + 0x01000204, 0x00004204, 0x00004200, 0x00000000, 0x00000200, 0x01000004, 0x00000004, 0x01000200, + 0x00000000, 0x01000204, 0x01000200, 0x00004200, 0x00000204, 0x00004000, 0x01004204, 0x01000000, + 0x01004200, 0x00000004, 0x00004004, 0x01004204, 0x01000004, 0x01004200, 0x01004000, 0x00004004 + }, + // nibble 7 + { + 0x20800080, 0x20820000, 0x00020080, 0x00000000, 0x20020000, 0x00800080, 0x20800000, 0x20820080, + 0x00000080, 0x20000000, 0x00820000, 0x00020080, 0x00820080, 0x20020080, 0x20000080, 0x20800000, + 0x00020000, 0x00820080, 0x00800080, 0x20020000, 0x20820080, 0x20000080, 0x00000000, 0x00820000, + 0x20000000, 0x00800000, 0x20020080, 0x20800080, 0x00800000, 0x00020000, 0x20820000, 0x00000080, + 0x00800000, 0x00020000, 0x20000080, 0x20820080, 0x00020080, 0x20000000, 0x00000000, 0x00820000, + 0x20800080, 0x20020080, 0x20020000, 0x00800080, 0x20820000, 0x00000080, 0x00800080, 0x20020000, + 0x20820080, 0x00800000, 0x20800000, 0x20000080, 0x00820000, 0x00020080, 0x20020080, 0x20800000, + 0x00000080, 0x20820000, 0x00820080, 0x00000000, 0x20000000, 0x20800080, 0x00020000, 0x00820080 + } +}; + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_DES_KeySched(cc_u8 *RoundKey, cc_u8 *UserKey, cc_u32 RKPos, cc_u32 RKStep) + * @brief Expand the cipher key into the encryption key schedule + * + * @param RoundKey [out]generated round key + * @param UserKey [in]user key, 8 byte + * @param RKPos [in]index of round key starts + * @param RKStep [in]step for index + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_DES_KeySched(cc_u8 *RoundKey, cc_u8 *UserKey, cc_u32 RKPos, cc_u32 RKStep); + +/* + * @fn int SDRM_DES_Encryption(cc_u32 RoundKey[][2], cc_u8 *msg, cc_u8 *out) + * @brief DES processing for one block + * + * @param RoundKey [in]expanded round key + * @param msg [in]8 byte plaintext + * @param out [out]8 byte ciphertext + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_DES_Encryption(cc_u32 RoundKey[][2], cc_u8 *msg, cc_u8 *out); + +/* + * @fn int SDRM_DES64_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) + * @brief one block DES Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_DES64_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey); + +/* + * @fn int SDRM_DES64_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) + * @brief one block DES Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_DES64_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_ecc.h b/ssflib/dep/cryptocore/include/base/cc_ecc.h new file mode 100755 index 0000000..6740661 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_ecc.h @@ -0,0 +1,249 @@ +/** + * \file ecc.h + * @brief ecc library based on big number + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jiyoung Moon + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/05/03 + * Note : optimized by Jiyoung Moon & Jisoon Park, August,2006. + */ + + +#ifndef _CCECC_H +#define _CCECC_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" +#include "cc_bignum.h" +#include "cc_sha1.h" + +//////////////////////////////////////////////////////////////////////////// +// Constants +//////////////////////////////////////////////////////////////////////////// +#define SDRM_MAX_DIMENSION_ECC 256 +#define SDRM_SIZE_OF_ECC_KEY (SDRM_SIZE_OF_DWORD * SDRM_ECC_BN_BUFSIZE) + +//////////////////////////////////////////////////////////////////////////// +// Macros for ECC +//////////////////////////////////////////////////////////////////////////// +#define SDRM_EC_FREE(X) if (X) {free(X);} + +#define SDRM_EC_SET_ZERO(A) do { \ + memset((A), 0, sizeof(SDRM_EC_POINT) + SDRM_ECC_ALLOC_SIZE * 5); \ + (A)->IsInfinity = 0; \ + A->x = SDRM_BN_Alloc((cc_u8*)A + sizeof(SDRM_EC_POINT), SDRM_ECC_BN_BUFSIZE); \ + A->y = SDRM_BN_Alloc((cc_u8*)A->x + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); \ + A->z = SDRM_BN_Alloc((cc_u8*)A->y + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); \ + A->z2 = SDRM_BN_Alloc((cc_u8*)A->z + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); \ + A->z3 = SDRM_BN_Alloc((cc_u8*)A->z2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); \ + } while(0) + +#define SDRM_EC_CLR(A) SDRM_EC_SET_ZERO(A) + +#define SDRM_ECC_Clr(A) do { \ + SDRM_BN_Clr((A)->ECC_p); \ + SDRM_BN_Clr((A)->ECC_A); \ + SDRM_BN_Clr((A)->ECC_b); \ + SDRM_BN_Clr((A)->ECC_n); \ + SDRM_BN_Clr((A)->PRIV_KEY); \ + EC_Clr((A)->ECC_G); \ + EC_Clr((A)->PUBLIC_KEY); \ + } while(0) + +#define SDRM_ECC_FREE(X) do { \ + if ((X)) { \ + SDRM_BN_FREE(X->ECC_a); \ + SDRM_EC_FREE(X->ECC_G); \ + SDRM_EC_FREE(X->PUBLIC_KEY); \ + SDRM_EC_FREE(X); \ + } \ + } while(0) + +#define SDRM_EC_COPY(A, B) do { \ + (A)->IsInfinity = (B)->IsInfinity; \ + SDRM_BN_Copy((A)->x, (B)->x); \ + SDRM_BN_Copy((A)->y, (B)->y); \ + SDRM_BN_Copy((A)->z, (B)->z); \ + SDRM_BN_Copy((A)->z2, (B)->z2); \ + SDRM_BN_Copy((A)->z3, (B)->z3); \ + } while(0) + + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +///// ECC º¸Á¶ÇÔ¼ö +/* + * @fn SDRM_ECC_Init + * @brief return SDRM_EC_POINT structure + * + * @return address of allocate structure + * \n NULL if memory allocation is failed + */ +SDRM_EC_POINT *SDRM_ECC_Init(void); + +/* + * @fn SDRM_CURVE_Init + * @brief return SDRM_ECC_CTX structure + * + * @return address of allocate structure + * \n NULL if memory allocation is failed + */ +SDRM_ECC_CTX *SDRM_CURVE_Init(void); + +///// ECC Point ¿¬»êÇÔ¼ö +/* + * @fn SDRM_CTX_EC_Chain + * @brief Chain ÇÔ¼ö + * + * signed window method : size of window = 4 + * chain for addition/subtraction of k Using sliding window method + * @param chain [out]destination + * @param L_Src [in]byte-length of chain + * @param Len_Src [in]number of doubling in chain + * @param k [in]source + * @param window_size [in]size of window + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if given value is incorrect + */ +int SDRM_CTX_EC_Chain(signed char *chain, cc_u32 *L_Src, cc_u32 *Len_Src, SDRM_BIG_NUM *k, int window_size); + +/* + * @fn SDRM_CTX_EC_kP + * @brief get EC_Dst = kP by Montgomery Method + * + * @param ctx [in]ecc context + * @param EC_Dst [out]destination + * @param EC_Src [in]first element(P) + * @param k [in]second element(k) + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if the arguemnt represents a minus value + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_INFINITY_INPUT if the argument is a infinity value + */ +int SDRM_CTX_EC_kP(SDRM_ECC_CTX *ctx, SDRM_EC_POINT* EC_Dst, SDRM_EC_POINT *EC_Src, SDRM_BIG_NUM *k); + +/* + * @fn SDRM_CTX_EC_2kP + * @brief get EC_Dst = k1*C1 + k2*C2 + * + * @param ctx [in]ecc context + * @param EC_Dst [out]destination + * @param k1 [in]first element(k1) + * @param EC_Src1 [in]second element(C1) + * @param k2 [in]third element(k2) + * @param EC_Src2 [in]fourth element(C2) + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if the arguemnt represents a minus value + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_INFINITY_INPUT if the argument is a infinity value + */ +int SDRM_CTX_EC_2kP(SDRM_ECC_CTX *ctx, SDRM_EC_POINT *EC_Dst, SDRM_BIG_NUM *k1, SDRM_EC_POINT *EC_Src1, SDRM_BIG_NUM *k2, SDRM_EC_POINT *EC_Src2); + +///// Functions of Converting Coordingate +/* + * @fn SDRM_Mont_Jm2Jc + * @brief ÁÂÇ¥º¯È¯ 1 + * Modified Jacobian => Chundnovsky Jacobian + * (A->y) <= (A->y)/2 + * (A->z2) <= (A->z)^2 + * (A->z3) <= (A->z)^3 + * + * @param EC_Dst [out]destination + * @param new_a [in]first element + * @param new_b [in]second element + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_Mont_Jm2Jc(SDRM_EC_POINT *EC_Dst, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont); + +/* + * @fn SDRM_Mont_Jc2Jm + * @brief ÁÂÇ¥º¯È¯ 2 + * Chundnovsky Jacobian => Modified Jacobian + * (A->y) <= 2*(A->y) + * (A->z2) <= new_a*(A->z)^4 + * @param A [out]destination + * @param new_a [in]first element + * @param new_b [in]second element + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_Mont_Jc2Jm(SDRM_EC_POINT *A, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont); + +/* + * @fn SDRM_CTX_EC_Add_Jc + * @brief Chundnovsky Jacobian coordinate + * using montgomery (A = B + C) + * + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param EC_Src2 [in]second element(C) + * @param new_a [in]ECC_A's montgomery value + * @param new_b [in]ECC_B's montgomery value + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Add_Jc(SDRM_EC_POINT* EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_EC_POINT *EC_Src2, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont); + +/* + * @fn SDRM_CTX_EC_Double_Jc + * @brief Chundnovsky Jacobian coordinate + * montgomery (A = 2B) + * + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param new_a [in]ECC_A's montgomery value + * @param new_b [in]ECC_B's montgomery value + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Double_Jc(SDRM_EC_POINT *EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont); + +/* + * @fn SDRM_CTX_EC_Double_Jm + * @brief Modified Jacobian coordinate + * montgomery (A = 2B) + * + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param new_a [in]ECC_A's montgomery value + * @param new_b [in]ECC_B's montgomery value + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Double_Jm(SDRM_EC_POINT *EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont); + +#ifdef __cplusplus +} +#endif + +#endif // _ECC_H + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/base/cc_fast_math.h b/ssflib/dep/cryptocore/include/base/cc_fast_math.h new file mode 100755 index 0000000..12dd955 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_fast_math.h @@ -0,0 +1,290 @@ +/** + * @file fast_math.h + * @brief Header file for fast_mathf.c + * + * [Optional] Detail description (major features, interface description, flow of control, and so on) + * @see [Optional] Related information + + * Copyright 2008 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + * \internal + * Author : Karen Ispiryan + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2008/08/28 +*/ + +#ifndef CCFAST_MATH_H +#define CCFAST_MATH_H + +#include "CC_Type.h" + +#ifndef _OP64_NOTSUPPORTED +# define ORD_32 +#else +# define ORD_16 +#endif //_OP64_NOTSUPPORTED + +/* when we have only 16 bit processor available */ +#ifdef ORD_16 + +typedef cc_u16 BasicWord; +typedef cc_u32 BasicDWord; + +#define DIV_BY_ORD_BYTES_COUNT(x) (BasicWord)((x) >> 1) +#define MUL_BY_ORD_BYTES_COUNT(x) (BasicWord)((x) << 1) + +#define BASICWORD_BITS_COUNT 16 +#define BASICWORD_BYTES_COUNT 2 +#define MAXDIGIT (BasicWord)(0xFFFF) + +#endif + +/* when we have 32 bit processor available and also have 64 bit data type */ +#ifdef ORD_32 + +typedef cc_u32 BasicWord; +typedef cc_u64 BasicDWord; + +#define DIV_BY_ORD_BYTES_COUNT(x) (BasicWord)((x) >> 2) +#define MUL_BY_ORD_BYTES_COUNT(x) (BasicWord)((x) << 2) + +#define BASICWORD_BITS_COUNT 32 +#define BASICWORD_BYTES_COUNT 4 +#define MAXDIGIT (BasicWord)(0xFFFFFFFF) + +#endif + +#define LOW_WORD(a) (BasicWord) (a) +#define HIGH_WORD(a) (BasicWord)((a) >> BASICWORD_BITS_COUNT) + +/* In our implementation we are using assumption that DWord data type available for using. */ +/* If for some reasons it isn't so, then we just need to redefine rhe following two macros in appropriate way + * and functions will work properly. + */ +#define _add_add_(aw1,aw2,aw3,rwl,rwh) { \ + BasicDWord dw = (BasicDWord)(aw1)+(aw2)+(aw3); \ + rwl = LOW_WORD(dw); \ + rwh = HIGH_WORD(dw); \ + } + +#define _mul_add_add(wm1,wm2,aw1,aw2,rwl,rwh) { \ + BasicDWord dw = (BasicDWord)(wm1)*(wm2)+(aw1)+(aw2); \ + rwl = LOW_WORD(dw); \ + rwh = HIGH_WORD(dw); \ + } + +#define IN +#define OUT + +/*===========================================================================================================*/ + +/** + * @fn SDRM_ll_Cmp + * @brief Compare two large unsigned integers + * + * @param pFirstOperand [in] the first operand + * @param pSecondOperand [in] the second operand + * + * @return 0 if they are equal + * 1 if first bigger then second + * -1 if the seond one is bigger then first + */ +int SDRM_ll_Cmp(const BasicWord *pFirstOperand, const BasicWord *pSecondOperand, unsigned uOperandLength); + +/** + * @fn SDRM_ll_Copy + * @brief Just copy two large unsigned integers from one into another + */ +void SDRM_ll_Copy(BasicWord *pFirstOperand, const BasicWord *pSecondOperand, unsigned uOperandLength); + +/** + * @fn SDRM_ll_bit_RShift + * @brief Shift large unsigned integer to the right by uBits + * + * @param pOperand [inout] pointer to the operand to be shifted + * + * @return Nothing + * @warning We have to be careful when using this function because it modifies uOperandLength+1 words + * that is by 1 word bigger then operand original size. + * WWW....Operand...WWW|W <- it modifies the word immediately after the last one of passed operand. + */ +void SDRM_ll_bit_RShift(IN OUT BasicWord *pOperand, IN BasicWord uOperandLength, OUT BasicWord uBits); + +/** + * @fn SDRM_ll_bit_LShift + * @brief Shift large unsigned integer to the left by uBits + * + * @param pOperand [inout] pointer to the operand to be shifted + * + * @return Nothing + * @warning We have to be careful when using this function because it modifies uOperandLength+1 words + * that is by 1 word bigger then operand original size. + * It modifies the word immediately prior to the first one of passed operand -> W|WWW....Operand...WWW + */ +void SDRM_ll_bit_LShift(IN OUT BasicWord *pOperand, IN BasicWord uOperandLength, OUT BasicWord uBits); + +/** + * @fn SDRM_ll_getMSW + * @brief Return index of most significant word. + * + * @param pOperand [in] pointer to the large integer. + * + * @return The index of most significant word. + * -1 if passed integer actually is equal to 0. + */ +int SDRM_ll_getMSW(IN const BasicWord *pOperand, IN BasicWord uOperandLength); + +/** + * @fn SDRM_ll_Add + * @brief Add two large unsigned integers that have the same size. + * + * @param pFirstOperand [in] pointer to first large integer + * @param pSecondOperand [in] pointer to second large integer + * @param uOperandsLength [in] length of the operands in words + * @param pResult [out] pointer to result of subtraction + * + * @return carry if so. + */ +int SDRM_ll_Add(IN const BasicWord *pFirstOperand, + IN const BasicWord *pSecondOperand, + IN BasicWord uOperandsLength, + OUT BasicWord *pResult); + +/** + * @fn SDRM_ll_AddCarry + * @brief Add carry to large unsigned integer + * + * @param oneWord [in] value of carry + * @param pOperand [inout] pointer to large integer + * @param uOperandLength [in] length of the second operand in words + * + * @return carry if so. + */ +int SDRM_ll_AddCarry(IN BasicWord oneWord, IN BasicWord *pOperand, IN BasicWord uOperandLength); + +/** + * @fn SDRM_ll_Sub + * @brief Subtract two large unsigned integers that have the same size. + * + * @param pFirstOperand [in] pointer to first large integer + * @param pSecondOperand [in] pointer to second large integer + * @param uOperandsLength [in] length of the operands in words + * @param pResult [out] pointer to result of subtraction + * + * @return borrow if so. + */ +int SDRM_ll_Sub(IN const BasicWord *pFirstOperand, + IN const BasicWord *pSecondOperand, + IN BasicWord uOperandsLength, + OUT BasicWord *pResult); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_MulAdd(IN BasicWord *pFirstOperand, IN BasicWord uFirstOperandsLength, + IN BasicWord *pSecondOperand, IN BasicWord uSecondOperandsLength, + OUT BasicWord *pResult); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_Mul(IN BasicWord *pFirstOperand, IN BasicWord uFirstOperandsLength, + IN BasicWord *pSecondOperand, IN BasicWord uSecondOperandsLength, + OUT BasicWord *pResult); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_Square(IN BasicWord *pOperand, IN BasicWord uOperandLength, OUT BasicWord *pResult); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_mont_Rem(IN OUT BasicWord *pFirstOperand, + IN BasicWord *pModule, + IN BasicWord uModuleLength, + IN BasicWord inv); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_mont_Square(IN BasicWord *pFirstOperand, + IN BasicWord *pModule, + IN BasicWord uModuleLength, + IN BasicWord Inv, + OUT BasicWord *pResult); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_mont_Mul(IN BasicWord *pFirstOperand, + IN BasicWord *pSecondOperand, + IN BasicWord *pModule, + IN BasicWord uModuleLengthInBytes, + IN BasicWord Inv, + OUT BasicWord *pResult); + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_ExpMod( IN BasicWord *pBase, IN BasicWord uBaseLengthInBytes, + IN BasicWord *pExponent, IN BasicWord uExponentLengthInBytes, + IN BasicWord *pModule, IN BasicWord uModuleLengthInBytes, + OUT BasicWord *pResult); + +#endif /*FAST_MATH_H*/ diff --git a/ssflib/dep/cryptocore/include/base/cc_hash.h b/ssflib/dep/cryptocore/include/base/cc_hash.h new file mode 100755 index 0000000..446f33d --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_hash.h @@ -0,0 +1,337 @@ +/** + * \file hash.h + * @brief hash API function + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/08 + */ + +#ifndef _CCHASH_H +#define _CCHASH_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CC_API.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_SHA1_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_init(CryptoCoreContainer *crt); + +/* + * @fn SDRM_SHA1_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + +/* + * @fn SDRM_SHA1_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_final(CryptoCoreContainer *crt, cc_u8 *output); + +/* + * @fn SDRM_SHA1_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + +/* + * @fn SDRM_SHA224_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_init(CryptoCoreContainer *crt); + + +/* + * @fn SDRM_SHA224_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + +/* + * @fn SDRM_SHA224_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_final(CryptoCoreContainer *crt, cc_u8 *output); + +/* + * @fn SDRM_SHA224_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + +/* + * @fn SDRM_SHA256_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_init(CryptoCoreContainer *crt); + + +/* + * @fn SDRM_SHA256_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + +/* + * @fn SDRM_SHA256_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_final(CryptoCoreContainer *crt, cc_u8 *output); + +/* + * @fn SDRM_SHA256_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + +/* + * @fn SDRM_SHA384_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_init(CryptoCoreContainer *crt); + +/* + * @fn SDRM_SHA384_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + +/* + * @fn SDRM_SHA384_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_final(CryptoCoreContainer *crt, cc_u8 *output); + +/* + * @fn SDRM_SHA384_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + +/* + * @fn SDRM_SHA512_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_init(CryptoCoreContainer *crt); + +/* + * @fn SDRM_SHA512_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + +/* + * @fn SDRM_SHA512_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_final(CryptoCoreContainer *crt, cc_u8 *output); + +/* + * @fn SDRM_SHA512_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + +/* + * @fn SDRM_MD5_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_init(CryptoCoreContainer *crt); + +/* + * @fn SDRM_MD5_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen); + +/* + * @fn SDRM_MD5_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_final(CryptoCoreContainer *crt, cc_u8 *output); + +/* + * @fn SDRM_MD5_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_md5.h b/ssflib/dep/cryptocore/include/base/cc_md5.h new file mode 100755 index 0000000..c8c5326 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_md5.h @@ -0,0 +1,30 @@ +/* + * Implementation of MD5 + */ + +#ifndef _CCMD5_H +#define _CCMD5_H + +#include +#include +#include "CryptoCore.h" + +//prototypes + +#ifdef __cplusplus +extern "C" { +#endif + +void SDRM_MD5_Init(SDRM_MD5Context *ctx); + +void SDRM_MD5_Update(SDRM_MD5Context *ctx, cc_u8* buffer, cc_u32 cc_u8Count); + +void SDRM_MD5_Final(SDRM_MD5Context *ctx, cc_u8* output ); + +#ifdef __cplusplus +} +#endif + +#endif // _MD5_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_moo.h b/ssflib/dep/cryptocore/include/base/cc_moo.h new file mode 100755 index 0000000..80457a9 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_moo.h @@ -0,0 +1,206 @@ +/** + * \file moo.h + * @brief implementation of mode of operations + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/04 + */ + + +#ifndef _CCMOO_H +#define _CCMOO_H + + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" +#include "cc_aes.h" +#include "cc_des.h" +#include "cc_tdes.h" + + +//////////////////////////////////////////////////////////////////////////// +// Macros for Mode of operation +//////////////////////////////////////////////////////////////////////////// +#ifndef SDRM_CheckByteUINT32 +/*! @brief get k-th byte from cc_u32 array A */ +#define SDRM_CheckByteUINT32(A, k) (cc_u8)(0xff & (A[(k) >> 2] >> (((k) & 3 ) << 3))) +#endif + + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_ECB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key) + * @brief Encrypt a block with ECB mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_ECB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key); + + +/* + * @fn int SDRM_ECB_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key) + * @brief Decrypt a block with ECB mode + * + * @param Algorithm [in]algorithm + * @param out [out]plain text block + * @param in [in]cipher text block + * @param key [in]user key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_ECB_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key); + + +/* + * @fn int SDRM_CBC_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) + * @brief Encrypt a block with CBC mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CBC_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV); + + +/* + * @fn int SDRM_CBC_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) + * @brief Decrypt a block with CBC mode + * + * @param Algorithm [in]algorithm + * @param out [out]plain text block + * @param in [in]cipher text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CBC_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV); + + +/* + * @fn int SDRM_CFB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) + * @brief Encrypt a block with CFB mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CFB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV); + + +/* + * @fn int SDRM_CFB_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) + * @brief Decrypt a block with CBC mode + * + * @param Algorithm [in]algorithm + * @param out [out]plain text block + * @param in [in]cipher text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CFB_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV); + + +/* + * @fn int SDRM_OFB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) + * @brief Encrypt a block with OFB mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_OFB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV); + + +/* + * @fn SDRM_OFB_Dec(ALG, OUT, IN, KEY, IV) + * @brief Decrypt a block with OFB mode + * + * \n ALG [in]algorithm + * \n OUT [out]plain text block + * \n IN [in]cipher text block + * \n KEY [in]user key + * \n IV [in]initial vector + */ +#define SDRM_OFB_Dec(ALG, OUT, IN, KEY, IV) SDRM_OFB_Enc(ALG, OUT, IN, KEY, IV) + +/* + * @fn int SDRM_CTR_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV, cc_u32 counter) + * @brief Encrypt a block with CTR mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * @param counter [in]counter + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CTR_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV, cc_u32 counter); + + +/* + * @fn SDRM_CTR_Dec(ALG, OUT, IN, KEY, IV, CTR) + * @brief Decrypt a block with CTR mode + * + * \n ALG [in]algorithm + * \n OUT [out]plain text block + * \n IN [in]cipher text block + * \n KEY [in]user key + * \n IV [in]initial vector + * \n CTR [in]counter + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +#define SDRM_CTR_Dec(ALG, OUT, IN, KEY, IV, CTR) SDRM_CTR_Enc(ALG, OUT, IN, KEY, IV, CTR) + + +#ifdef __cplusplus +} +#endif + +#endif // _MOO_H + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/base/cc_pkcs1_v21.h b/ssflib/dep/cryptocore/include/base/cc_pkcs1_v21.h new file mode 100755 index 0000000..c77660e --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_pkcs1_v21.h @@ -0,0 +1,195 @@ +/** + * \file pkcs1_v21.h + * @brief PKCS#1 V1.5, V2.0(RSAES-OAEP), V2.1(RSASSA-PSS) Implemetation + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/20 + */ + + +#ifndef _CCPKCS1_V21_H +#define _CCPKCS1_V21_H + +////////////////////////////////////////////////////////////////////////// +// Include Header Files +////////////////////////////////////////////////////////////////////////// +#include +#include "CryptoCore.h" +#include "cc_bignum.h" + +////////////////////////////////////////////////////////////////////////// +// Define Constants +////////////////////////////////////////////////////////////////////////// +/*! @brief padding mode - enpadding */ +#define SDRM_ENPADDING 11111 +/*! @brief padding mode - depadding */ +#define SDRM_DEPADDING 11112 + +/*! @brief DER message */ +#define SDRM_DIGESTINFO_MD5_VALUE {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x40, 0x10} +#define SDRM_DIGESTINFO_SHA1_VALUE {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14} +#define SDRM_DIGESTINFO_SHA224_VALUE {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c} +#define SDRM_DIGESTINFO_SHA256_VALUE {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20} +#define SDRM_DIGESTINFO_SHA384_VALUE {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30} +#define SDRM_DIGESTINFO_SHA512_VALUE {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40} + +/*! @brief byte-length of DER message */ +#define SDRM_DIGESTINFO_MD5_LEN 18 +#define SDRM_DIGESTINFO_SHA1_LEN 15 +#define SDRM_DIGESTINFO_SHA224_LEN 19 +#define SDRM_DIGESTINFO_SHA256_LEN 19 +#define SDRM_DIGESTINFO_SHA384_LEN 19 +#define SDRM_DIGESTINFO_SHA512_LEN 19 + +#define SDRM_EMSA_PSS_SALT_LEN 4 + +////////////////////////////////////////////////////////////////////////// +// Function Prototypes +////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* +* @fn int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +* @brief RSAES PKCS#1 v1.5 enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k); +/* +* @fn int SDRM_Depad_Rsaes_pkcs15(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k); +* @brief RSAES PKCS#1 v1.5 depadding +* +* @param m [out]Depadded msg +* @param mLen [out]byte-size of m +* @param EM [in]Enpadded msg +* @param emLen [in]byte-size of EM +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_INVALID_ARGUMENT if enpadded message is out of RSA padding scheme +*/ +int SDRM_Depad_Rsaes_pkcs15(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k); +/* +* @fn int SDRM_Enpad_Rsaes_oaep(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k, int HASH_Algorithm) +* @brief RSAES OAEP enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsaes_oaep(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k, int HASH_Algorithm); +/* +* @fn int SDRM_Depad_Rsaes_oaep(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k, int HASH_Algorithm) +* @brief RSAES PKCS#1 v1.5 depadding +* +* @param m [out]Depadded msg +* @param mLen [out]byte-size of m +* @param EM [in]Enpadded msg +* @param emLen [in]byte-size of EM +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_INVALID_ARGUMENT if enpadded message is out of RSA padding scheme +*/ +int SDRM_Depad_Rsaes_oaep(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k, int HASH_Algorithm); + +/* +* @fn int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +* @brief RSAES PKCS#1 v1.5 enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsassa_pkcs15(cc_u8 *EM, cc_u32 emLen, cc_u8 *h, cc_u32 hLen, int HASH_Algorithm); + +/* +* @fn int SDRM_Depad_Rsassa_pkcs15(cc_u8 *EM, cc_u32 emLen, cc_u8 *h, cc_u32 hLen, int HASH_Algorithm); +* @brief RSAES PKCS#1 v1.5 enpadding +* +* @param m [out]Depadded msg +* @param mLen [out]byte-size of m +* @param EM [in]Enpadded msg +* @param emLen [in]byte-size of EM +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Depad_Rsassa_pkcs15(cc_u8 *EM, cc_u32 emLen, cc_u8 *h, cc_u32 hLen, int HASH_Algorithm); + +/* + * @fn int SDRM_Enpad_Rsassa_pss(cc_u8 *EM, cc_u32 nBits, cc_u8 *h, cc_u32 hLen, cc_u32 k, int HASH_Algorithm); + * @brief RSASSA PSS + * +* @param EM [out]Enpadded msg +* @param nBits [in]bit length of enpadded msg. +* @param h [in]hash of src message +* @param hLen [in]hash message length. +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsassa_pss(cc_u8 *EM, cc_u32 nBits, cc_u8 *h, cc_u32 hLen, cc_u32 k, int HASH_Algorithm); +/* +* @fn int SDRM_Depad_Rsassa_pss(cc_u8 *EM, cc_u32 nBits, cc_u8 *h, cc_u32 hLen, cc_u32 k, int HASH_Algorithm); +* @brief RSASSA PSS +* +* @param EM [out]Enpadded msg +* @param nBits [in]bit length of enpadded msg. +* @param h [in]hash of src message +* @param hLen [in]hash message length. +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Depad_Rsassa_pss(cc_u8 *EM, cc_u32 nBits, cc_u8 *h, cc_u32 hLen, cc_u32 k, int HASH_Algorithm); +/* + * @fn int SDRM_MGF1(int HASH_Algorithm, cc_u8* mask, cc_u8* pbSeed, cc_u32 SeedLen, cc_u32 dMaskLen) + * @brief MGF1 Function (Mask Generation Function based on a hash function) + * + * @param mask [out]byte-length of generated mask + * @param pbSeed [in]seed for MGF + * @param SeedLen [in]byte-length of pbSeed + * @param dMaskLen [in]byte-length of mask + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +//int SDRM_MGF1(int HASH_Algorithm, cc_u8* mask, cc_u8* pbSeed, cc_u32 SeedLen, cc_u32 dMaskLen); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_rc4.h b/ssflib/dep/cryptocore/include/base/cc_rc4.h new file mode 100755 index 0000000..98510ae --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_rc4.h @@ -0,0 +1,61 @@ +/** + * \file rc4.h + * @brief implementation of RC4 encryption scheme + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/01 + */ + + +#ifndef _CCRC4_H +#define _CCRC4_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_RC4_Setup(SDRM_RC4Context *ctx, cc_u8 *UserKey, cc_u32 keyLen) + * @brief intialize s + * + * @param ctx [in]crypto context + * @param UserKey [in]user key + * @param keyLen [out]byte-length of UserKey + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_RC4_Setup(SDRM_RC4Context *ctx, cc_u8 *UserKey, cc_u32 keyLen); + +/* + * @fn int SDRM_RC4_PRNG(SDRM_RC4Context *ctx, cc_u8 *in, cc_u32 inLen, cc_u8 *out) + * @brief process stream data + * + * @param ctx [in]crypto context + * @param in [in]plaintext + * @param inLen [in]byte-length of in + * @param out [out]cipher text + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_RC4_PRNG(SDRM_RC4Context *ctx, cc_u8 *in, cc_u32 inLen, cc_u8 *out); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_sha1.h b/ssflib/dep/cryptocore/include/base/cc_sha1.h new file mode 100755 index 0000000..773bbce --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_sha1.h @@ -0,0 +1,30 @@ +/* + * Implementation of SHA-1 + */ + +#ifndef _CCSHA1_H +#define _CCSHA1_H + +#include +#include +#include "CryptoCore.h" + +//prototypes + +#ifdef __cplusplus +extern "C" { +#endif + +void SDRM_SHA1_Init(SDRM_SHA1Context* ctx); + +void SDRM_SHA1_Update(SDRM_SHA1Context* ctx, const cc_u8* buffer, int ByteCount); + +void SDRM_SHA1_Final(SDRM_SHA1Context* ctx, cc_u8* output); + +#ifdef __cplusplus +} +#endif + +#endif // _SHA1_H + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/base/cc_sha2.h b/ssflib/dep/cryptocore/include/base/cc_sha2.h new file mode 100755 index 0000000..69eb1c6 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_sha2.h @@ -0,0 +1,44 @@ +/* + * Implementation of SHA-2 + */ + +#ifndef _CCSHA2_H +#define _CCSHA2_H + +#include +#include +#include "CryptoCore.h" + +//prototypes + +#ifdef __cplusplus +extern "C" { +#endif + +void SDRM_SHA224_Init(SDRM_SHA224Context* ctx); +void SDRM_SHA224_Update(SDRM_SHA224Context* ctx, const cc_u8 *message, cc_u32 len); +void SDRM_SHA224_Final(SDRM_SHA224Context* ctx, cc_u8 *digest); + +void SDRM_SHA256_Init(SDRM_SHA256Context* ctx); +void SDRM_SHA256_Update(SDRM_SHA256Context* ctx, const cc_u8 *message, cc_u32 len); +void SDRM_SHA256_Final(SDRM_SHA256Context* ctx, cc_u8 *digest); + +#ifndef _OP64_NOTSUPPORTED + +void SDRM_SHA384_Init(SDRM_SHA384Context* ctx); +void SDRM_SHA384_Update(SDRM_SHA384Context* ctx, const cc_u8 *message, cc_u32 len); +void SDRM_SHA384_Final(SDRM_SHA384Context* ctx, cc_u8 *digest); + +void SDRM_SHA512_Init(SDRM_SHA512Context* ctx); +void SDRM_SHA512_Update(SDRM_SHA512Context* ctx, const cc_u8 *message, cc_u32 len); +void SDRM_SHA512_Final(SDRM_SHA512Context* ctx, cc_u8 *digest); + +#endif //_OP64_NOTSUPPORTED + +#ifdef __cplusplus +} +#endif + +#endif // _SHA2_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/base/cc_snow2.h b/ssflib/dep/cryptocore/include/base/cc_snow2.h new file mode 100755 index 0000000..639acd6 --- /dev/null +++ b/ssflib/dep/cryptocore/include/base/cc_snow2.h @@ -0,0 +1,68 @@ +/** + * \file snow2.h + * @brief implementation of SNOW 2.0 encryption scheme + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/02 + */ + + +#ifndef _CCSNOW2_H +#define _CCSNOW2_H + + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" + + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_SNOW2_Setup(SDRM_SNOW2Context *ctx, cc_u8 *UserKey, cc_u32 keyLen, cc_u8 *IV) + * @brief Setup FSM and s values + * @param ctx [out]crypto context + * @param UserKey [in]User Key, 128 or 256 bit + * @param keyLen [in]byte-size of User Key, 16 or 32 + * @param IV [in]16 byte initial vector + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_SNOW2_Setup(SDRM_SNOW2Context *ctx, cc_u8 *UserKey, cc_u32 keyLen, cc_u8 *IV); + +/* + * @fn int SDRM_SNOW2_getKeyStream64(SDRM_SNOW2Context *ctx, cc_u32 *keyStream64) + * @brief get 64 byte key stream + * @param ctx [out]crypto context + * @param keyStream64 [in]generated key stream + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_SNOW2_getKeyStream64(SDRM_SNOW2Context *ctx, cc_u32 *keyStream64); + +/* + * @fn int SDRM_SNOW2_getKeyStream(SDRM_SNOW2Context *ctx, cc_u32 *keyStream) + * @brief get 4 byte key stream + * @param ctx [out]crypto context + * @param keyStream [in]generated key stream + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_SNOW2_getKeyStream(SDRM_SNOW2Context *ctx, cc_u32 *keyStream); + + +#ifdef __cplusplus +} +#endif + +#endif // _SNOW2_H + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/drm_macro.h b/ssflib/dep/cryptocore/include/drm_macro.h new file mode 100755 index 0000000..ab20527 --- /dev/null +++ b/ssflib/dep/cryptocore/include/drm_macro.h @@ -0,0 +1,201 @@ +/** + * \file drm_macro.h + * @brief Common Macro Difinitions + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Changsup Ahn + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/02 + */ + +#ifndef _DRM_MACRO_H +#define _DRM_MACRO_H + +//////////////////////////////////////////////////////////////////////////// +// Header File Include +//////////////////////////////////////////////////////////////////////////// +#include + +//////////////////////////////////////////////////////////////////////////// +// Macros +//////////////////////////////////////////////////////////////////////////// +/*! @brief get larger of two */ +#define MAX2(A, B) ((A) > (B) ? (A) : (B)) + +/*! @brief get largest of three */ +#define MAX3(C, D, E) ((C) > MAX2((D), (E)) ? (C) : MAX2((D), (E))) + +/*! @brief print out by byte unit */ +#undef PrintBYTE +#define PrintBYTE(msg, Data, DataLen) { \ + int idx; \ + printf("%10s =", msg); \ + for( idx=0; idx<(int)DataLen; idx++) { \ + if( (idx!=0) && ((idx%16)==0) ) printf("\n"); \ + if((idx % 4) == 0) printf(" 0x"); \ + printf("%.2x", Data[idx]); \ + } \ + printf("\n"); \ +} + +/*! @brief print out in hexa representation */ +#undef PrintBYTE_HEX +#define PrintBYTE_HEX(msg, Data, DataLen) { \ + int idx; \ + printf("%10s =", msg); \ + for( idx=0; idx<(int)DataLen; idx++) { \ + if( (idx!=0) && ((idx%8)==0) ) printf("\n"); \ + printf("0x%.2x, ", Data[idx]); \ + } \ + printf("\n"); \ +} + +/*! @brief print out in hexa representation without length information */ +#undef PrintBYTE_FILE_RAW // raw data ÇüÅ·Π»ç¿ëÇÒ ¼ö ÀÖµµ·Ï Hex ÇüÅ·ΠÃâ·Â +#define PrintBYTE_FILE_RAW(pfile, Data, DataLen) { \ + int idx; \ + for( idx=0; idx<(int)DataLen; idx++) { \ + if( (idx==0) || ((idx%8)!=0) ) \ + fprintf(pfile, "0x%.2x, ", Data[idx]); \ + else \ + fprintf(pfile, " \n0x%.2x, ", Data[idx]); \ + } \ +} + +/*! @brief print out message */ +#undef PrintMSG +#define PrintMSG(msg) { \ + fprintf(stdout, "\n************************************************\n"); \ + fprintf(stdout, "* %s\n", msg); \ + fprintf(stdout, "*\n"); \ +} + +/*! @brief copy 16 byte block */ +#undef BlockCopy +#define BlockCopy(pbDst, pbSrc) { \ + memcpy(pbDst, pbSrc, 16); \ +} + +/*! @brief xor 16 byte block */ +#undef BlockXor +#define BlockXor(pbDst, phSrc1, phSrc2) { \ + int idx; \ + for(idx = 0; idx < 16; idx++) \ + (pbDst)[idx] = (phSrc1)[idx] ^ (phSrc2)[idx]; \ +} + +/*! @brief convert 32-bit unit to 4 byte */ +#undef GET_UINT32 +#define GET_UINT32(n,b,i) \ +{ \ + (n) = ((unsigned int)((b)[(i) ]) << 24 ) \ + | ((unsigned int)((b)[(i) + 1]) << 16 ) \ + | ((unsigned int)((b)[(i) + 2]) << 8 ) \ + | ((unsigned int)((b)[(i) + 3]) ); \ +} + +/*! @brief 4 byte to 32-bit unit */ +#undef PUT_UINT32 +#define PUT_UINT32(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} + +/*! @brief convert 24-bit unit to 3 byte */ +#undef GET_UINT24 +#define GET_UINT24(n,b,i) \ +{ \ + (n) = ( (b)[(i) ] << 16 ) \ + | ( (b)[(i) + 1] << 8 ) \ + | ( (b)[(i) + 2] ); \ +} + +/*! @brief convert 3 byte to 24-bit unit */ +#undef PUT_UINT24 +#define PUT_UINT24(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> ); \ +} + +/*! @brief convert 16-bit unit to 2 byte */ +#undef GET_UINT16 +#define GET_UINT16(n,b,i) \ +{ \ + (n) = ( (b)[(i) ] << 8 ) \ + | ( (b)[(i) + 1] ); \ +} + +/*! @brief convert 2 byte to 16-bit unit */ +#undef PUT_UINT16 +#define PUT_UINT16(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) ); \ +} + +/*! @brief read 1 byte of s form o & increase o */ +#undef READ_8 +#define READ_8(t,s,o) { \ + t = (unsigned char) s[o]; \ + o+=1; \ +} + +/*! @brief read 2 byte of sfrom o & increase o */ +#undef READ_16 +#define READ_16(t,s,o) { \ + GET_UINT16(t,s,o); \ + o+=2; \ +} + +/*! @brief read 3 byte of s from o & increase o */ +#undef READ_24 +#define READ_24(t,s,o) { \ + GET_UINT24(t,s,o); \ + o+=3; \ +} + +/*! @brief read 4 byte of s from o & increase o */ +#undef READ_32 +#define READ_32(t,s,o) { \ + GET_UINT32(t,s,o); \ + o+=4; \ +} + +/*! @brief write 4 byte to s from o & increase o */ +#undef WRITE_32 +#define WRITE_32(t,s,o) { \ + PUT_UINT32(s,t,o); \ + o+=4; \ +} + +/*! @brief write 3 byte to s from o & increase o */ +#undef WRITE_24 +#define WRITE_24(t,s,o) { \ + PUT_UINT24(s,t,o); \ + o+=3; \ +} + +/*! @brief write 2 byte to s from o & increase o */ +#undef WRITE_16 +#define WRITE_16(t,s,o) { \ + PUT_UINT16(s,t,o); \ + o+=2; \ +} + +/*! @brief write 1 byte to s from o & increase o */ +#undef WRITE_8 +#define WRITE_8(t,s,o) { \ + t[o] = (unsigned char)s; \ + o+=1; \ +} + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_cmac.h b/ssflib/dep/cryptocore/include/middle/cc_cmac.h new file mode 100755 index 0000000..05409c1 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_cmac.h @@ -0,0 +1,96 @@ +/** + * \file cmac.h + * @brief funciton for c-mac code generation by AES-128 + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/20 + */ + + +#ifndef _CCCMAC_H +#define _CCCMAC_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CC_API.h" +#include "cc_moo.h" +#include "cc_aes.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_CMAC_init(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen) + * @brief Parameter setting for mac code generation + * + * @param crt [out]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CMAC_init(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen); + +/* + * @fn int SDRM_CMAC_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen) + * @brief process data blocks + * + * @param crt [out]crypto parameter + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CMAC_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen); + +/* + * @fn int SDRM_CMAC_final(CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen) + * @brief process last data block + * + * @param crt [in]crypto parameter + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CMAC_final(CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn int SDRM_CMAC_getMAC(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen) + * @brief generate c-mac code + * + * @param crt [in]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_CMAC_getMAC(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen); + +#ifdef __cplusplus +} +#endif + +#endif // _CMAC_H + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/include/middle/cc_dh.h b/ssflib/dep/cryptocore/include/middle/cc_dh.h new file mode 100755 index 0000000..21631b0 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_dh.h @@ -0,0 +1,94 @@ +/** + * \file dh.h + * @brief implementation of Diffie-Hellman Key Exchange Protocol + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2012/04/12 + */ + +#ifndef _DIFFIE_HELLMAN_H +#define _DIFFIE_HELLMAN_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "CC_API.h" + +#define DH_DEFAULT_GENERATOR 5 /**< fixed generator value */ + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @fn SDRM_GenerateDHParam(SDRM_DHContext* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned int* pGenerator) + * @brief generate parameters for Diffie-Hellman protocol + * + * @param [out] crt context + * @param [out] pPrime prime number + * @param [in] nPrimeLen size of pPrime buffer + * @param [out] pGenerator generator value + * @return int + */ +int SDRM_GenerateDHParam(CryptoCoreContainer* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned char* pGenerator); + +/** + * @fn SDRM_SetDHParam(SDRM_DHContext* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned int nGenerator) + * @brief set parameters for Diffie-Hellman protocol + * + * @param [out] crt context + * @param [in] pPrime prime number + * @param [in] nPrimeLen size of pPrime buffer + * @param [in] pGenerator generator value + * @param [in] nGeneratorLen generator len + * @return int + */ +int SDRM_SetDHParam(CryptoCoreContainer* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned char* pGenerator, unsigned int nGeneratorLen); + +/** + * @fn SDRM_GenerateDHPrivate(CryptoCoreContainer* crt, unsigned char* pPub) + * @brief generate private value and calculate public value + * + * @param [in] crt context + * @param [out] pPriv private value + * @param [out] pPub public value + * @return int + */ +int SDRM_GenerateDHPrivate(CryptoCoreContainer* crt, unsigned char* pPriv, unsigned char* pPub); + +/** + * @fn SDRM_GetDHSharedSecret(CryptoCoreContainer* crt, unsigned char* pPub, unsigned char* pSharedSecret) + * @brief calculate shared secret + * + * @param [in] crt context + * @param [in] pPriv private value + * @param [in] pPub guest's public value + * @param [out] pSharedSecret public value + * @return int + */ +int SDRM_GetDHSharedSecret(CryptoCoreContainer* crt, unsigned char* pPriv, unsigned char* pPub, unsigned char* pSharedSecret); + +/** + * @fn SDRM_FreeDHContext(CryptoCoreContainer* crt) + * @brief free context buffer + * + * @param [in] crt context + */ +void SDRM_FreeDHContext(SDRM_DHContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif // _DIFFIE_HELLMAN_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_dsa.h b/ssflib/dep/cryptocore/include/middle/cc_dsa.h new file mode 100755 index 0000000..8ba4fd9 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_dsa.h @@ -0,0 +1,171 @@ +/** + * \file dsa.h + * @brief implementation of dsa signature/verifycation + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/23 + */ + +#ifndef _CCDSA_H +#define _CCDSA_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "CC_API.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_DSAContext *SDRM_DSA_InitCrt(void) + * @brief generate DSA Context + * + * @return pointer to the generated context + * \n NULL if memory allocation is failed + */ +SDRM_DSAContext *SDRM_DSA_InitCrt(void); + +/* + * @fn int SDRM_DSA_SetParam(CryptoCoreContainer *crt, cc_u8 *DSA_P_Data, cc_u32 DSA_P_Len, cc_u8 *DSA_Q_Data, cc_u32 DSA_Q_Len, cc_u8 *DSA_G_Data, cc_u32 DSA_G_Len) + * @brief set DSA parameters + * + * @param crt [out]dsa context + * @param DSA_P_Data [in]octet string of p value + * @param DSA_P_Len [in]legnth of p_val + * @param DSA_Q_Data [in]octet string of q value + * @param DSA_Q_Len [in]legnth of q_val + * @param DSA_G_Data [in]octet string of al value + * @param DSA_G_Len [in]legnth of al_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_SetParam( + CryptoCoreContainer *crt, + cc_u8 *DSA_P_Data, cc_u32 DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 DSA_G_Len); + +/* + * @fn int SDRM_DSA_SetKeyPair(CryptoCoreContainer *crt, cc_u8 *DSA_Y_Data, cc_u32 DSA_Y_Len, cc_u8 *DSA_X_Data, cc_u32 DSA_X_Len) + * @brief set DSA parameters + * + * @param crt [out]dsa context + * @param DSA_Y_Data [in]octet string of y value + * @param DSA_Y_Len [in]legnth of y_val + * @param DSA_X_Data [in]octet string of a value + * @param DSA_X_Len [in]legnth of a_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_SetKeyPair( + CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 DSA_X_Len); + +/* + * @fn int SDRM_DSA_GenParam(CryptoCoreContainer *crt, cc_u32 T_Siz, cc_u8 *DSA_P_Data, cc_u32 *DSA_P_Len, cc_u8 *DSA_Q_Data, cc_u32 *DSA_Q_Len, cc_u8 *DSA_G_Data, cc_u32 *DSA_G_Len) + * @brief generate and set DSA parameters + * + * @param crt [out]dsa context + * @param T_Siz [in]fix the length of p to 512 + 64t bit (0 <= T_Siz <= 8) + * @param DSA_P_Data [out]octet string of p value + * @param DSA_P_Len [out]legnth of p_val + * @param DSA_Q_Data [out]octet string of q value + * @param DSA_Q_Len [out]legnth of q_val + * @param DSA_G_Data [out]octet string of al value + * @param DSA_G_Len [out]legnth of al_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_GenParam( + CryptoCoreContainer *crt, + cc_u32 T_Siz, cc_u8 *DSA_P_Data, cc_u32 *DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 *DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 *DSA_G_Len); + +/* + * @fn int SDRM_DSA_GenKeypair(CryptoCoreContainer *crt, cc_u8 *DSA_Y_Data, cc_u32 *DSA_Y_Len, cc_u8 *DSA_X_Data, cc_u32 *DSA_X_Len) + * @brief generate and set DSA parameters + * + * @param crt [out]dsa context + * @param DSA_Y_Data [out]octet string of y value + * @param DSA_Y_Len [out]legnth of y_val + * @param DSA_X_Data [out]octet string of a value + * @param DSA_X_Len [out]legnth of a_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_GenKeypair( + CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 *DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 *DSA_X_Len); + +/* + * @fn int SDRM_DSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [out]generated signature + * @param signLen [out]byte-length of signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_DSA_sign( + CryptoCoreContainer *crt, + cc_u8 *hash, cc_u32 hashLen, + cc_u8 *signature, cc_u32 *signLen); + +/* + * @fn int SDRM_DSA_verify(CryptoCoreContainer *crt,cc_u8 *hash, cc_u32 hashLen,cc_u8 *signature, cc_u32 signLen,int *result) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [in]signature + * @param signLen [in]byte-length of signature + * @param result [in]result of veryfing signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if the length of signature is invalid + */ +int SDRM_DSA_verify( + CryptoCoreContainer *crt, + cc_u8 *hash, cc_u32 hashLen, + cc_u8 *signature, cc_u32 signLen, + int *result); + +#ifdef __cplusplus +} +#endif + +#endif // _DSA_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_ecdh.h b/ssflib/dep/cryptocore/include/middle/cc_ecdh.h new file mode 100755 index 0000000..8caa853 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_ecdh.h @@ -0,0 +1,61 @@ +/** + * \file ecdh.h + * @brief implementation of EC Diffie-Hellman Key Exchange Protocol + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/27 + */ + +#ifndef _CCECDH_H +#define _CCECDH_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "CC_API.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_generateDH1stPhaseKey(CryptoCoreContainer *crt, cc_u8 *pchXk, cc_u8 *pchXv) + * @brief generate Xk and its Xv + * + * @param crt [in]crypto context + * @param pchXk [out]Generated Random Number + * @param pchXv [out]DH 1st phase value + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_generateDH1stPhaseKey(CryptoCoreContainer *crt, cc_u8 *pchXk, cc_u8 *pchXv); + +/* + * @fn int SDRM_generateDHKey(CryptoCoreContainer *crt, cc_u8* pchXk, cc_u8* pchYv, cc_u8* pchKauth) + * @brief genenrate auth key with Xk and Yv + * + * @param crt [in]crypto context + * @param pchXk [in]Generated Random Number + * @param pchYv [in]DH 1st phase value + * @param pchKauth [out]authentication key + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_generateDHKey(CryptoCoreContainer *crt, cc_u8* pchXk, cc_u8* pchYv, cc_u8* pchKauth); + +#ifdef __cplusplus +} +#endif + +#endif // _ECDH_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_ecdsa.h b/ssflib/dep/cryptocore/include/middle/cc_ecdsa.h new file mode 100755 index 0000000..c9fd27f --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_ecdsa.h @@ -0,0 +1,144 @@ +/** + * \file ecdsa.h + * @brief implementation of public key signature algorithm + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/13 + */ + +#ifndef _CCECDSA_H +#define _CCECDSA_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CC_API.h" +#include "cc_ecc.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_ECDSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [out]generated signature + * @param signLen [out]byte-length of signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_ECDSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen); + +/* + * @fn int SDRM_ECDSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [in]signature + * @param signLen [in]byte-length of signature + * @param result [in]result of veryfing signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if the length of signature is invalid + */ +int SDRM_ECDSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result); + +/* + * @fn SDRM_ECC_Set_CTX + * @brief Set parameters for ECC + * + * @param crt [out]crypto env structure + * @param Dimension [in]dimension + * @param ECC_P_Data [in]represents p + * @param ECC_P_Len [in]byte-length of p + * @param ECC_A_Data [in]represents a + * @param ECC_A_Len [in]byte-length of a + * @param ECC_B_Data [in]represents b + * @param ECC_B_Len [in]byte-length of b + * @param ECC_G_X_Data [in]represents x coordinate of g + * @param ECC_G_X_Len [in]byte-length of x coordinate of g + * @param ECC_G_Y_Data [in]represents y coordinate of g + * @param ECC_G_Y_Len [in]byte-length of y coordinate of g + * @param ECC_R_Data [in]represents r + * @param ECC_R_Len [in]byte-length of r + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if argument is null + */ +int SDRM_ECC_Set_CTX( + struct _CryptoCoreContainer *crt, cc_u16 Dimension, + cc_u8* ECC_P_Data, cc_u32 ECC_P_Len, + cc_u8* ECC_A_Data, cc_u32 ECC_A_Len, + cc_u8* ECC_B_Data, cc_u32 ECC_B_Len, + cc_u8* ECC_G_X_Data, cc_u32 ECC_G_X_Len, + cc_u8* ECC_G_Y_Data, cc_u32 ECC_G_Y_Len, + cc_u8* ECC_R_Data, cc_u32 ECC_R_Len +); + +/* + * @fn SDRM_ECC_genKeypair + * @brief Generate Private Key and Generate Key Pair for ECC Signature + * + * @param crt [out]crypto env structure + * @param PrivateKey [in]represents x coordinate of public key + * @param PrivateKeyLen [in]byte-length of x coordinate of public key + * @param PublicKey_X [in]represents x coordinate of public key + * @param PublicKey_XLen [in]byte-length of x coordinate of public key + * @param PublicKey_Y [in]represents y coordinate of public key + * @param PublicKey_YLen [in]byte-length of y coordinate of public key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if argument is null + */ +int SDRM_ECC_genKeypair( + CryptoCoreContainer *crt, + cc_u8 *PrivateKey, cc_u32 *PrivateKeyLen, + cc_u8 *PublicKey_X, cc_u32 *PublicKey_XLen, + cc_u8 *PublicKey_Y, cc_u32 *PublicKey_YLen +); + +/* + * @fn SDRM_ECC_setKeypair + * @brief Set key data for ECC + * + * @param crt [out]crypto env structure + * @param PRIV_Data [in]represents private key + * @param PRIV_Len [in]byte-length of private key + * @param PUB_X_Data [in]represents x coordinate of public key + * @param PUB_X_Len [in]byte-length of x coordinate of public key + * @param PUB_Y_Data [in]represents y coordinate of public key + * @param PUB_Y_Len [in]byte-length of y coordinate of public key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if argument is null + */ +int SDRM_ECC_setKeypair( + CryptoCoreContainer *crt, + cc_u8* PRIV_Data, cc_u32 PRIV_Len, + cc_u8* PUB_X_Data, cc_u32 PUB_X_Len, + cc_u8* PUB_Y_Data, cc_u32 PUB_Y_Len +); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_hmac.h b/ssflib/dep/cryptocore/include/middle/cc_hmac.h new file mode 100755 index 0000000..73e1df5 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_hmac.h @@ -0,0 +1,94 @@ +/** + * \file hmac.h + * @brief funciton for c-mac code generation by SHA1 and MD5 + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/19 + */ + + +#ifndef _CCHMAC_H +#define _CCHMAC_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CC_API.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_HMAC_init + * @brief Parameter setting for mac code generation + * + * @param crt [out]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_HMAC_init(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen); + +/* + * @fn SDRM_HMAC_update + * @brief process data blocks + * + * @param crt [out]crypto parameter + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_HMAC_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen); + +/* + * @fn SDRM_HMAC_final + * @brief process last data block + * + * @param crt [in]crypto parameter + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_HMAC_final(CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn SDRM_HMAC_getMAC + * @brief generate h-mac code + * + * @param crt [in]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_HMAC_getMAC(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen); + +#ifdef __cplusplus +} +#endif + +#endif // _HMAC_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_rng.h b/ssflib/dep/cryptocore/include/middle/cc_rng.h new file mode 100755 index 0000000..9be75c7 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_rng.h @@ -0,0 +1,60 @@ +/** + * \file rng.h + * @brief Random Number Generator Interface + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon, Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/07 + */ + + +#ifndef _CCRNG_H +#define _CCRNG_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "CC_API.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_X931_seed + * @brief Seed RNG System + * + * @param crt [in]crypto env structure + * @param seed [in]seed for RNG System + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_X931_seed(CryptoCoreContainer *crt, cc_u8 *seed); + +/* + * @fn SDRM_X931_get + * @brief generate random number + * + * @param crt [in]crypto env structure + * @param bitLength [in]bit length for generated number + * @param data [out]generated data + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_X931_get(CryptoCoreContainer *crt, cc_u32 bitLength, cc_u8 *data); + +#ifdef __cplusplus +} +#endif + +#endif // _RNG_H + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_rsa.h b/ssflib/dep/cryptocore/include/middle/cc_rsa.h new file mode 100755 index 0000000..6c37c69 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_rsa.h @@ -0,0 +1,351 @@ +/** + * \file rsa.h + * @brief implementation of rsa encryption/decryption and signature/verifycation + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/20 + */ + + +#ifndef _CCRSA_H +#define _CCRSA_H + +////////////////////////////////////////////////////////////////////////// +// Include Header Files +////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include "CC_API.h" + +////////////////////////////////////////////////////////////////////////// +// Function Prototypes +////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_RSA_InitCrt + * @brief generate RSA Context + * + * @return pointer to the generated context + * \n NULL if memory allocation is failed + */ +SDRM_RSAContext *SDRM_RSA_InitCrt(cc_u32 RSAKeyByteLen); + +/* + * @fn SDRM_RSA_setNED + * @brief set RSA parameters + * + * @param crt [out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [in]n value + * @param RSA_N_Len [in]byte-length of n + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_D_Data [in]d value + * @param RSA_D_Len [in]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + */ +int SDRM_RSA_setNED +( + CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 RSA_D_Len +); + +/* + * @fn SDRM_RSA_setNEDPQ + * @brief set RSA parameters + * + * @param crt [out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [in]n value + * @param RSA_N_Len [in]byte-length of n + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_D_Data [in]d value + * @param RSA_D_Len [in]byte-length of d + * @param RSA_P_Data [in]p value + * @param RSA_P_Len [in]byte-length of p + * @param RSA_Q_Data [in]q value + * @param RSA_Q_Len [in]byte-length of q + * @param RSA_DmodP1_Data [in]d mod (p-1) value + * @param RSA_DmodP1_Len [in]byte-length of d mod (p-1) + * @param RSA_DmodQ1_Data [in]d mod (q-1) value + * @param RSA_DmodQ1_Len [in]byte-length of d mod (q-1) + * @param RSA_iQmodP_Data [in]q^(-1) mod p value + * @param RSA_iQmodP_Len [in]byte-length of q^(-1) mod p + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + */ +int SDRM_RSA_setNEDPQ +( + CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + cc_u8* RSA_DmodP1_Data, cc_u32 RSA_DmodP1_Len, + cc_u8* RSA_DmodQ1_Data, cc_u32 RSA_DmodQ1_Len, + cc_u8* RSA_iQmodP_Data, cc_u32 RSA_iQmodP_Len +); + +/* + * @fn SDRM_RSA_GenerateKey + * @brief generate and set RSA parameters + * + * @param crt [out]rsa context + * @param PaddingMethod [out]padding method + * @param RSA_N_Data [out]n value + * @param RSA_N_Len [out]byte-length of n + * @param RSA_E_Data [out]e value + * @param RSA_E_Len [out]byte-length of e + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateKey +( + CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len +); + +/*! \brief generate and set RSA parameters + * \param crt [in/out]rsa context + * \param PaddingMethod [in]padding method + * \param RSA_N_Data [out]n value + * \param RSA_N_Len [out]byte-length of n + * \param RSA_E_Data [in]e value + * \param RSA_E_Len [in]byte-length of e + * \param RSA_D_Data [out]d value + * \param RSA_D_Len [out]byte-length of d + * \param RSA_P_Data [out]p value + * \param RSA_P_Len [out]byte-length of p + * \param RSA_Q_Data [out]q value + * \param RSA_Q_Len [out]byte-length of q + * \param RSA_DP_Data [out]dmodp1 value + * \param RSA_DP_Len [out]byte-length of dmodp1 + * \param RSA_DQ_Data [out]dmodq1 value + * \param RSA_DQ_Len [out]byte-length of dmodq1 + * \param RSA_QP_Data [out]iqmodp value + * \param RSA_QP_Len [out]byte-length of iqmodp + * \return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateKeyforCRT(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + cc_u8* RSA_DP_Data, cc_u32 *RSA_DP_Len, + cc_u8* RSA_DQ_Data, cc_u32 *RSA_DQ_Len, + cc_u8* RSA_QP_Data, cc_u32 *RSA_QP_Len +); +/* + * @fn SDRM_RSA_GenerateND + * @brief generate and set RSA parameters with specfied e + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_N_Data [out]n value + * @param RSA_N_Len [out]byte-length of n + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateND +( + CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len +); + +/* + * @fn SDRM_RSA_GenerateDwithPQE + * @brief generate D with specfied p, q, d mod (p-1), d mod (q-1) and e + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_P_Data [in]n value + * @param RSA_P_Len [in]byte-length of n + * @param RSA_Q_Data [in]d value + * @param RSA_Q_Len [in]byte-length of d + * @param RSA_D_P_Data [in]d mod (p-1) value + * @param RSA_D_P_Len [in]byte-length of d mod (p-1) + * @param RSA_D_Q_Data [in]d mod (q-1) value + * @param RSA_D_Q_Len [in]byte-length of d mod (q-1) + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateDwithPQE +( + CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len +); + +/* + * @fn int SDRM_RSA_GenNEDPQ(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + * cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + * cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + * cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + * cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + * cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + * cc_u8* RSA_DmodP1_Data, cc_u32 *RSA_DmodP1_Len, + * cc_u8* RSA_DmodQ1_Data, cc_u32 *RSA_DmodQ1_Len, + * cc_u8* RSA_iQmodP_Data, cc_u32 *RSA_iQmodP_Len) + * @brief generate and set RSA parameters for CRT + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [out]n value + * @param RSA_N_Len [out]byte-length of n + * @param RSA_E_Data [out]e value + * @param RSA_E_Len [out]byte-length of e + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * @param RSA_P_Len [out]byte-length of p + * @param RSA_Q_Data [out]q value + * @param RSA_Q_Len [out]byte-length of q + * @param RSA_DmodP1_Data [out]d mod (p-1) value + * @param RSA_DmodP1_Len [out]byte-length of d mod (p-1) + * @param RSA_DmodQ1_Data [out]d mod (q-1) value + * @param RSA_DmodQ1_Len [out]byte-length of d mod (q-1) + * @param RSA_iQmodP_Data [out]q^(-1) mod p value + * @param RSA_iQmodP_Len [out]byte-length of q^(-1) mod p + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenNEDPQ(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + cc_u8* RSA_DmodP1_Data, cc_u32 *RSA_DmodP1_Len, + cc_u8* RSA_DmodQ1_Data, cc_u32 *RSA_DmodQ1_Len, + cc_u8* RSA_iQmodP_Data, cc_u32 *RSA_iQmodP_Len); + +/* + * @fn SDRM_RSA_encrypt + * @brief generate and set RSA parameters + * + * @param crt [in]rsa context + * @param in [in]message to encrypt + * @param inLen [in]byte-length of in + * @param out [out]encrypted message + * @param outLen [out]byte-length of out + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_encrypt(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + +/* + * @fn SDRM_RSA_decrypt + * @brief RSA Decryption + * + * @param crt [in]rsa context + * @param in [in]message to decrypt + * @param inLen [in]byte-length of in + * @param out [out]decrypted message + * @param outLen [out]byte-length of out + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_decrypt(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + +/* + * @fn SDRM_RSA_decryptByCRT + * @brief RSA Decryption using CRT + * + * @param crt [in]rsa context + * @param in [in]message to decrypt + * @param inLen [in]byte-length of in + * @param out [out]decrypted message + * @param outLen [out]byte-length of out + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_decryptByCRT(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + +/* + * @fn SDRM_RSA_sign + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [out]generated signature + * @param signLen [out]byte-length of signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_RSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen); + +/* + * @fn SDRM_RSA_verify + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [in]signature + * @param signLen [in]byte-length of signature + * @param result [in]result of veryfing signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if the length of signature is invalid + */ +int SDRM_RSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_symmetric.h b/ssflib/dep/cryptocore/include/middle/cc_symmetric.h new file mode 100755 index 0000000..f49c7a1 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_symmetric.h @@ -0,0 +1,247 @@ +/** + * \file symmetric.h + * @brief API for symmetric encryption + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon, Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/07 + */ + + +#ifndef _CCSYMMETRIC_H +#define _CCSYMMETRIC_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CC_API.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn SDRM_AES_init + * @brief intialize crypt context for aes + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_AES_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV); + +/* + * @fn SDRM_AES_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param Text [in]message block + * @param TextLen [in]byte-length of Text + * @param output [out]proecessed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_AES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn SDRM_AES_final + * @brief process final block and padding + * + * @param crt [in]crypto env structure + * @param input [in]message block + * @param inputLen [in]byte-length of Text + * @param output [out]processed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_AES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn SDRM_RC4_init + * @brief intialize crypt context for RC4 + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method, not needed + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector, not needed + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_RC4_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV); + +/* + * @fn SDRM_RC4_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param Text [in]message block + * @param TextLen [in]byte-length of Text + * @param output [out]proecessed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_RC4_process(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + +/* + * @fn SDRM_SNOW2_init + * @brief intialize crypt context for SNOW2 + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method, not needed + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_SNOW2_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV); + +/* + * @fn + * @brief process message block + * @param crt [in]crypto env structure + * @param in [in]message block + * @param inLen [in]byte-length of Text + * @param out [out]processed message + * @param outLen [out]byte-length of output + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_SNOW2_process(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen); + +/* + * @fn SDRM_DES_init + * @brief intialize crypt context for des + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_DES_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV); + +/* + * @fn SDRM_DES_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param in [in]message block + * @param inLen [in]byte-length of Text + * @param out [out]processed message + * @param outLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_DES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn SDRM_DES_final + * @brief process final block and padding + * + * @param crt [in]crypto env structure + * @param input [in]message block + * @param inputLen [in]byte-length of Text + * @param output [out]processed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_DES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn SDRM_TDES_init + * @brief intialize crypt context for triple des + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_TDES_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV); + +/* + * @fn SDRM_TDES_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param Text [in]message block + * @param TextLen [in]byte-length of Text + * @param output [out]proecessed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_TDES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen); + +/* + * @fn SDRM_TDES_final + * @brief process final block and padding + * + * @param crt [in]crypto env structure + * @param input [in]message block + * @param inputLen [in]byte-length of Text + * @param output [out]processed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_TDES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/include/middle/cc_tdes.h b/ssflib/dep/cryptocore/include/middle/cc_tdes.h new file mode 100755 index 0000000..386fae9 --- /dev/null +++ b/ssflib/dep/cryptocore/include/middle/cc_tdes.h @@ -0,0 +1,85 @@ +/** + * \file tdes.h + * @brief high-speed implementation of Triple DES-EDE + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/06 + */ + + +#ifndef _CCTDES_H +#define _CCTDES_H + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "CryptoCore.h" + +//////////////////////////////////////////////////////////////////////////// +// Function Prototypes +//////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @fn int SDRM_TDES_KeySched(cc_u8 *RoundKey, cc_u8 *UserKey, cc_u32 KeyLen, cc_u32 RKStep) + * @brief Expand the cipher key into the encryption key schedule + * + * @param RoundKey [out]generated round key + * @param UserKey [in]user key, 16 or 24 byte + * @param KeyLen [in]byte-length of UserKey + * @param RKStep [in]operation mode + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_TDES_KeySched(cc_u8 *RoundKey, cc_u8 *UserKey, cc_u32 KeyLen, cc_u32 RKStep); + +/* + * @fn int SDRM_TDES_Encryption(cc_u32 RoundKey[][2], cc_u8 *msg, cc_u8 *out) + * @brief Triple DES processing for one block + * + * @param RoundKey [in]expanded round key + * @param msg [in]8 byte plaintext + * @param out [out]8 byte ciphertext + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_TDES_Encryption(cc_u32 RoundKey[][2], cc_u8 *msg, cc_u8 *out); + +/* + * @fn int SDRM_TDES64_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) + * @brief one block Triple DES Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_TDES64_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey); + +/* + * @fn int SDRM_TDES64_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) + * @brief one block Triple DES Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_TDES64_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey); + +#ifdef __cplusplus +} +#endif + +#endif + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/CC_API.c b/ssflib/dep/cryptocore/source/CC_API.c new file mode 100755 index 0000000..9fa7d66 --- /dev/null +++ b/ssflib/dep/cryptocore/source/CC_API.c @@ -0,0 +1,448 @@ +/** + * \file CC_API.c + * @brief API of samsung Crypto Library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jae Heung Lee + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/10/24 + * Note : modified for implementation, by Jisoon, Park, 06/11/06 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "CryptoCore.h" +#include "cc_rng.h" +#include "cc_symmetric.h" +#include "cc_hash.h" +#include "cc_ecdsa.h" +#include "cc_cmac.h" +#include "cc_rsa.h" +#include "cc_dsa.h" +#include "cc_ecdh.h" +#include "cc_hmac.h" +#include "cc_dh.h" + +//////////////////////////////////////////////////////////////////////////// +// functions +//////////////////////////////////////////////////////////////////////////// +void *CCMalloc(int siz) +{ + cc_u8 *pbBuf = (cc_u8*)malloc(siz); + + if (pbBuf == NULL) + { + return NULL; + } + else + { + memset(pbBuf, 0, siz); + return (void*)pbBuf; + } +} + +void CCFree(void *ptr) +{ + if (ptr != NULL) + { + free(ptr); + } +} + +/* + * @fn CryptoCoreContainer *create_CryptoCoreContainer(cc_u32 algorithm) + * @brief memory allocation and initialize the crypt sturcture + * + * @param algorithm [in]algorithm want to use + * + * @return address of created sturcture + */ +CryptoCoreContainer *create_CryptoCoreContainer(cc_u32 algorithm) +{ + CryptoCoreContainer *crt; + srand((unsigned int)time(NULL)); + + // allocate memory for crypt data structure (by using CCMalloc) + crt = (CryptoCoreContainer *)CCMalloc(sizeof(CryptoCoreContainer)); + if (crt == NULL) + { + return NULL; + } + + crt->ctx = (CryptoCoreCTX *)CCMalloc(sizeof(CryptoCoreCTX)); + if (crt->ctx == NULL) + { + free(crt); + return NULL; + } + + crt->PRNG_seed = NULL; + crt->PRNG_get = NULL; + crt->MD_init = NULL; + crt->MD_update = NULL; + crt->MD_final = NULL; + crt->MD_getHASH = NULL; + crt->MAC_init = NULL; + crt->MAC_update = NULL; + crt->MAC_final = NULL; + crt->MAC_getMAC = NULL; + crt->SE_init = NULL; + crt->SE_process = NULL; + crt->SE_final = NULL; + crt->AE_encrypt = NULL; + crt->AE_decrypt = NULL; + crt->DS_sign = NULL; + crt->DS_verify = NULL; + crt->DSA_genParam = NULL; + crt->DSA_setParam = NULL; + crt->DSA_genKeypair = NULL; + crt->DSA_setKeyPair = NULL; + crt->RSA_genKeypair = NULL; + crt->RSA_genKeypairWithE= NULL; + crt->RSA_genKeypairForCRT = NULL; + crt->RSA_genKeyDWithPQE = NULL; + crt->RSA_genKeypairWithEforCRT= NULL; + crt->RSA_setKeypair = NULL; + crt->RSA_setKeypairForCRT = NULL; + crt->EC_setCurve = NULL; + crt->EC_genKeypair = NULL; + crt->EC_setKeypair = NULL; + crt->DH_GenerateParam = NULL; + crt->DH_SetParam = NULL; + crt->DH_Gen1stPhaseKey = NULL; + crt->DH_GenAuthKey = NULL; + crt->ECDH_Gen1stPhaseKey= NULL; + crt->ECDH_GenAuthKey = NULL; + + // allocate memory for context data structure + // and set up the member functions according to the algorithm + crt->alg = algorithm; + switch(algorithm) + { + case ID_X931: + crt->ctx->x931ctx = (SDRM_X931Context*)CCMalloc(sizeof(SDRM_X931Context)); + crt->PRNG_seed = SDRM_X931_seed; + crt->PRNG_get = SDRM_X931_get; + break; + case ID_MD5: + crt->ctx->md5ctx = (SDRM_MD5Context*)CCMalloc(sizeof(SDRM_MD5Context)); + crt->MD_init = SDRM_MD5_init; + crt->MD_update = SDRM_MD5_update; + crt->MD_final = SDRM_MD5_final; + crt->MD_getHASH = SDRM_MD5_hash; + break; + case ID_SHA1: + crt->ctx->sha1ctx = (SDRM_SHA1Context*)CCMalloc(sizeof(SDRM_SHA1Context)); + crt->MD_init = SDRM_SHA1_init; + crt->MD_update = SDRM_SHA1_update; + crt->MD_final = SDRM_SHA1_final; + crt->MD_getHASH = SDRM_SHA1_hash; + break; + case ID_SHA224: + crt->ctx->sha224ctx = (SDRM_SHA224Context*)CCMalloc(sizeof(SDRM_SHA224Context)); + crt->MD_init = SDRM_SHA224_init; + crt->MD_update = SDRM_SHA224_update; + crt->MD_final = SDRM_SHA224_final; + crt->MD_getHASH = SDRM_SHA224_hash; + break; + case ID_SHA256: + crt->ctx->sha256ctx = (SDRM_SHA256Context*)CCMalloc(sizeof(SDRM_SHA256Context)); + crt->MD_init = SDRM_SHA256_init; + crt->MD_update = SDRM_SHA256_update; + crt->MD_final = SDRM_SHA256_final; + crt->MD_getHASH = SDRM_SHA256_hash; + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + crt->ctx->sha384ctx = (SDRM_SHA384Context*)CCMalloc(sizeof(SDRM_SHA384Context)); + crt->MD_init = SDRM_SHA384_init; + crt->MD_update = SDRM_SHA384_update; + crt->MD_final = SDRM_SHA384_final; + crt->MD_getHASH = SDRM_SHA384_hash; + break; + case ID_SHA512: + crt->ctx->sha512ctx = (SDRM_SHA512Context*)CCMalloc(sizeof(SDRM_SHA512Context)); + crt->MD_init = SDRM_SHA512_init; + crt->MD_update = SDRM_SHA512_update; + crt->MD_final = SDRM_SHA512_final; + crt->MD_getHASH = SDRM_SHA512_hash; + break; +#endif + case ID_CMAC: + crt->ctx->cmacctx = (SDRM_CMACContext*)CCMalloc(sizeof(SDRM_CMACContext)); + crt->MAC_init = SDRM_CMAC_init; + crt->MAC_update = SDRM_CMAC_update; + crt->MAC_final = SDRM_CMAC_final; + crt->MAC_getMAC = SDRM_CMAC_getMAC; + break; + case ID_HMD5: + case ID_HSHA1: + case ID_HSHA224: + case ID_HSHA256: +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384: + case ID_HSHA512: +#endif //_OP64_NOTSUPPORTED + crt->ctx->hmacctx = (SDRM_HMACContext*)CCMalloc(sizeof(SDRM_HMACContext)); + crt->MAC_init = SDRM_HMAC_init; + crt->MAC_update = SDRM_HMAC_update; + crt->MAC_final = SDRM_HMAC_final; + crt->MAC_getMAC = SDRM_HMAC_getMAC; + break; + case ID_DH : + crt->ctx->dhctx = (SDRM_DHContext*)CCMalloc(sizeof(SDRM_DHContext)); + crt->DH_GenerateParam = SDRM_GenerateDHParam; + crt->DH_SetParam = SDRM_SetDHParam; + crt->DH_Gen1stPhaseKey = SDRM_GenerateDHPrivate; + crt->DH_GenAuthKey = SDRM_GetDHSharedSecret; + break; + case ID_ECDH : + crt->ctx->ecdhctx = (SDRM_ECDHContext*)SDRM_CURVE_Init(); + crt->EC_setCurve = SDRM_ECC_Set_CTX; + crt->EC_genKeypair = SDRM_ECC_genKeypair; + crt->EC_setKeypair = SDRM_ECC_setKeypair; + crt->ECDH_Gen1stPhaseKey = SDRM_generateDH1stPhaseKey; + crt->ECDH_GenAuthKey = SDRM_generateDHKey; + break; + case ID_AES128: + crt->ctx->aesctx = (SDRM_AESContext*)CCMalloc(sizeof(SDRM_AESContext)); + crt->SE_init = SDRM_AES_init; + crt->SE_process = SDRM_AES_process; + crt->SE_final = SDRM_AES_final; + crt->SE_EncryptOneBlock = SDRM_AES128_Encryption; + crt->SE_DecryptOneBlock = SDRM_AES128_Decryption; + break; + case ID_AES192: + crt->ctx->aesctx = (SDRM_AESContext*)CCMalloc(sizeof(SDRM_AESContext)); + crt->SE_init = SDRM_AES_init; + crt->SE_process = SDRM_AES_process; + crt->SE_final = SDRM_AES_final; + crt->SE_EncryptOneBlock = SDRM_AES192_Encryption; + crt->SE_DecryptOneBlock = SDRM_AES192_Decryption; + break; + case ID_AES256: + crt->ctx->aesctx = (SDRM_AESContext*)CCMalloc(sizeof(SDRM_AESContext)); + crt->SE_init = SDRM_AES_init; + crt->SE_process = SDRM_AES_process; + crt->SE_final = SDRM_AES_final; + crt->SE_EncryptOneBlock = SDRM_AES256_Encryption; + crt->SE_DecryptOneBlock = SDRM_AES256_Decryption; + break; + case ID_DES: + crt->ctx->desctx = (SDRM_DESContext*)CCMalloc(sizeof(SDRM_DESContext)); + crt->SE_init = SDRM_DES_init; + crt->SE_process = SDRM_DES_process; + crt->SE_final = SDRM_DES_final; + crt->SE_EncryptOneBlock = SDRM_DES64_Encryption; + crt->SE_DecryptOneBlock = SDRM_DES64_Decryption; + break; + case ID_TDES: + crt->ctx->tdesctx = (SDRM_TDESContext*)CCMalloc(sizeof(SDRM_TDESContext)); + crt->SE_init = SDRM_TDES_init; + crt->SE_process = SDRM_TDES_process; + crt->SE_final = SDRM_TDES_final; + crt->SE_EncryptOneBlock = SDRM_TDES64_Encryption; + crt->SE_DecryptOneBlock = SDRM_TDES64_Decryption; + break; + case ID_RC4: + crt->ctx->rc4ctx = (SDRM_RC4Context*)CCMalloc(sizeof(SDRM_RC4Context)); + crt->SE_init = SDRM_RC4_init; + crt->SE_process = SDRM_RC4_process; + break; + case ID_SNOW2: + crt->ctx->snow2ctx = (SDRM_SNOW2Context*)CCMalloc(sizeof(SDRM_SNOW2Context)); + crt->SE_init = SDRM_SNOW2_init; + crt->SE_process = SDRM_SNOW2_process; + break; + case ID_RSA512: + crt->ctx->rsactx = SDRM_RSA_InitCrt(64); + crt->RSA_genKeypair = SDRM_RSA_GenerateKey; + crt->RSA_genKeypairWithE = SDRM_RSA_GenerateND; + crt->RSA_genKeyDWithPQE = SDRM_RSA_GenerateDwithPQE; + crt->RSA_genKeypairWithEforCRT = SDRM_RSA_GenerateKeyforCRT; + crt->RSA_setKeypair = SDRM_RSA_setNED; + crt->RSA_setKeypairForCRT = SDRM_RSA_setNEDPQ; + crt->AE_encrypt = SDRM_RSA_encrypt; + crt->AE_decrypt = SDRM_RSA_decrypt; + crt->AE_decryptByCRT = SDRM_RSA_decryptByCRT; + crt->DS_sign = SDRM_RSA_sign; + crt->DS_verify = SDRM_RSA_verify; + break; + case ID_RSA: + case ID_RSA1024: + crt->ctx->rsactx = SDRM_RSA_InitCrt(128); + crt->RSA_genKeypair = SDRM_RSA_GenerateKey; + crt->RSA_genKeypairWithE = SDRM_RSA_GenerateND; + crt->RSA_genKeyDWithPQE = SDRM_RSA_GenerateDwithPQE; + crt->RSA_genKeypairWithEforCRT = SDRM_RSA_GenerateKeyforCRT; + crt->RSA_setKeypair = SDRM_RSA_setNED; + crt->RSA_setKeypairForCRT = SDRM_RSA_setNEDPQ; + crt->AE_encrypt = SDRM_RSA_encrypt; + crt->AE_decrypt = SDRM_RSA_decrypt; + crt->AE_decryptByCRT = SDRM_RSA_decryptByCRT; + crt->DS_sign = SDRM_RSA_sign; + crt->DS_verify = SDRM_RSA_verify; + break; + case ID_RSA2048: + crt->ctx->rsactx = SDRM_RSA_InitCrt(256); + crt->RSA_genKeypair = SDRM_RSA_GenerateKey; + crt->RSA_genKeypairWithE = SDRM_RSA_GenerateND; + crt->RSA_genKeyDWithPQE = SDRM_RSA_GenerateDwithPQE; + crt->RSA_genKeypairWithEforCRT = SDRM_RSA_GenerateKeyforCRT; + crt->RSA_setKeypair = SDRM_RSA_setNED; + crt->RSA_setKeypairForCRT = SDRM_RSA_setNEDPQ; + crt->AE_encrypt = SDRM_RSA_encrypt; + crt->AE_decrypt = SDRM_RSA_decrypt; + crt->AE_decryptByCRT = SDRM_RSA_decryptByCRT; + crt->DS_sign = SDRM_RSA_sign; + crt->DS_verify = SDRM_RSA_verify; + break; + case ID_RSA3072: + crt->ctx->rsactx = SDRM_RSA_InitCrt(384); + crt->RSA_genKeypair = SDRM_RSA_GenerateKey; + crt->RSA_genKeypairWithE = SDRM_RSA_GenerateND; + crt->RSA_genKeyDWithPQE = SDRM_RSA_GenerateDwithPQE; + crt->RSA_genKeypairWithEforCRT = SDRM_RSA_GenerateKeyforCRT; + crt->RSA_setKeypair = SDRM_RSA_setNED; + crt->RSA_setKeypairForCRT = SDRM_RSA_setNEDPQ; + crt->AE_encrypt = SDRM_RSA_encrypt; + crt->AE_decrypt = SDRM_RSA_decrypt; + crt->AE_decryptByCRT = SDRM_RSA_decryptByCRT; + crt->DS_sign = SDRM_RSA_sign; + crt->DS_verify = SDRM_RSA_verify; + break; + case ID_DSA: + crt->ctx->dsactx = (SDRM_DSAContext*)SDRM_DSA_InitCrt(); + crt->DSA_genParam = SDRM_DSA_GenParam; + crt->DSA_setParam = SDRM_DSA_SetParam; + crt->DSA_genKeypair = SDRM_DSA_GenKeypair; + crt->DSA_setKeyPair = SDRM_DSA_SetKeyPair; + crt->DS_sign = SDRM_DSA_sign; + crt->DS_verify = SDRM_DSA_verify; + break; + case ID_ECDSA: + crt->ctx->ecdsactx = (SDRM_ECDSAContext*)SDRM_CURVE_Init(); + crt->EC_setCurve = SDRM_ECC_Set_CTX; + crt->EC_genKeypair = SDRM_ECC_genKeypair; + crt->EC_setKeypair = SDRM_ECC_setKeypair; + crt->DS_sign = SDRM_ECDSA_sign; + crt->DS_verify = SDRM_ECDSA_verify; + break; + default: + // free CryptoCoreContainer data structure + free(crt->ctx); + free(crt); + crt = NULL; + break; + } + return crt; +} + +/* + * @fn void destroy_CryptoCoreContainer(CryptoCoreContainer* crt) + * + * @brief free allocated memory + * @param crt [in]crypt context + * + * @return void + */ +void destroy_CryptoCoreContainer(CryptoCoreContainer* crt) +{ + if (crt == NULL) + { + return; + } + + if (crt->ctx == NULL) + { + free(crt); + return; + } + + // free context data structure + switch(crt->alg) + { + case ID_X931: + CCFree(crt->ctx->x931ctx); + break; + case ID_MD5: + CCFree(crt->ctx->md5ctx); + break; + case ID_SHA1: + CCFree(crt->ctx->sha1ctx); + break; + case ID_SHA224: + CCFree(crt->ctx->sha224ctx); + break; + case ID_SHA256: + CCFree(crt->ctx->sha256ctx); + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + CCFree(crt->ctx->sha384ctx); + break; + case ID_SHA512: + CCFree(crt->ctx->sha512ctx); + break; +#endif + case ID_CMAC: + CCFree(crt->ctx->cmacctx); + break; + case ID_HMD5: + case ID_HSHA1: + case ID_HSHA224: + case ID_HSHA256: +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384: + case ID_HSHA512: +#endif //_OP64_NOTSUPPORTED + CCFree(crt->ctx->hmacctx); + break; + case ID_AES128: + case ID_AES192: + case ID_AES256: + CCFree(crt->ctx->aesctx); + break; + case ID_DES: + CCFree(crt->ctx->desctx); + break; + case ID_TDES: + CCFree(crt->ctx->tdesctx); + break; + case ID_RC4: + CCFree(crt->ctx->rc4ctx); + break; + case ID_SNOW2: + CCFree(crt->ctx->snow2ctx); + break; + case ID_RSA512: + case ID_RSA: + case ID_RSA1024: + case ID_RSA2048: + CCFree(crt->ctx->rsactx); + break; + case ID_DSA: + CCFree(crt->ctx->dsactx); + break; + case ID_ECDSA: + CCFree(crt->ctx->ecdsactx); + break; + case ID_ECDH: + CCFree(crt->ctx->ecdhctx); + break; + case ID_DH : + SDRM_FreeDHContext(crt->ctx->dhctx); + CCFree(crt->ctx->dhctx); + break; + } + + // free CryptoCoreContainer data structure + CCFree(crt->ctx); + CCFree(crt); +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/base/cc_ANSI_x931.c b/ssflib/dep/cryptocore/source/base/cc_ANSI_x931.c new file mode 100755 index 0000000..98c55d7 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_ANSI_x931.c @@ -0,0 +1,110 @@ +/** + * \file ANSI_x931.c + * @brief Pseudorandom number generator based on a design described in ANSI X9.31 + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Junbum Shin + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/23 + * Edited : Use date data, and update seed, by Jisoon Park, 06/11/08 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include +#include "cc_aes.h" +#include "cc_ANSI_x931.h" + +//////////////////////////////////////////////////////////////////////////// +// Constants +//////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_RNG_X931 + * @brief generate random number with seed + * + * @param Seed [in]seed for RNG System + * @param bitLength [in]bit length of data to generate + * @param data [out]generated data + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_RNG_X931(cc_u8 *Si_ANSI_X9_31, cc_u32 bitLength, cc_u8 *data) +{ + static cc_u8 K_ANSI_X9_31[SDRM_X931_SEED_SIZ] = {0xfd, 0x74, 0x3d, 0xe1, 0xdc, 0x08, 0xdc, 0x3d, 0x0f, 0xea, 0xf5, 0xa3, 0x6e, 0xb1, 0xc0, 0x7f}; + int res = CRYPTO_SUCCESS; + int i, offset; + int byteLength, residue; + int numBlock, residueBlock; + cc_u8 *DT; + cc_u8 I[SDRM_X931_SEED_SIZ] = {0}; + cc_u8 Ri_ANSI_X9_31[SDRM_X931_SEED_SIZ]; + cc_u32 Date[SDRM_X931_SEED_SIZ / 4]; + cc_u32 RoundKey[4*(10 + 1)]; //AES Round Key + + time_t nowTime; + + time(&nowTime); + Date[0] = (cc_u32)nowTime; + Date[1] = rand(); + Date[2] = rand(); + Date[3] = rand(); + + DT = (cc_u8*)Date; //DT : Time | Clock | RND | RND + + SDRM_rijndaelKeySetupDec(RoundKey, K_ANSI_X9_31, 128); + + byteLength = bitLength / 8 ; + residue = bitLength - byteLength * 8; + + if (residue == 0) + { + memset(data, 0x0, byteLength); + } + else + { + byteLength += 1; + memset(data, 0x0, byteLength); + } + + numBlock = byteLength / SDRM_X931_SEED_SIZ; + residueBlock = byteLength - numBlock * SDRM_X931_SEED_SIZ; + offset = 0; + + for(i = 0; i < numBlock; i++) + { + SDRM_rijndaelDecrypt(RoundKey, 10, DT, I); + BlockXor(I, I, Si_ANSI_X9_31); + + SDRM_rijndaelDecrypt(RoundKey, 10, I, Ri_ANSI_X9_31); + BlockXor(I, I, Ri_ANSI_X9_31); + + SDRM_rijndaelDecrypt(RoundKey, 10, I, Si_ANSI_X9_31); + memcpy(data + offset, Ri_ANSI_X9_31, SDRM_X931_SEED_SIZ); + offset += SDRM_X931_SEED_SIZ; + } + + if (residueBlock != 0) + { + SDRM_rijndaelDecrypt(RoundKey, 10, DT, I); + BlockXor(I, I, Si_ANSI_X9_31); + + SDRM_rijndaelDecrypt(RoundKey, 10, I, Ri_ANSI_X9_31); + BlockXor(I, I, Ri_ANSI_X9_31); + + SDRM_rijndaelDecrypt(RoundKey, 10, I, Si_ANSI_X9_31); + memcpy(data + offset, Ri_ANSI_X9_31, residueBlock); + } + + BlockXor(Si_ANSI_X9_31, I, Si_ANSI_X9_31); + + return res; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/base/cc_aes.c b/ssflib/dep/cryptocore/source/base/cc_aes.c new file mode 100755 index 0000000..cbce0d7 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_aes.c @@ -0,0 +1,1389 @@ +/** + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS 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 Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_aes.h" + +#define FULL_UNROLL + +//////////////////////////////////////////////////////////////////////////// +// AES conversion matrix +//////////////////////////////////////////////////////////////////////////// +static const cc_u32 SDRM_Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +static const cc_u32 SDRM_Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +static const cc_u32 SDRM_Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +static const cc_u32 SDRM_Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +static const cc_u32 SDRM_Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +static const cc_u32 SDRM_Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +static const cc_u32 SDRM_Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +static const cc_u32 SDRM_Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +static const cc_u32 SDRM_Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +static const cc_u32 SDRM_Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +static const cc_u32 SDRM_rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, + /* for 128-bit blocks, Rijndael never uses more than 10 _rcon values */ +}; + +//////////////////////////////////////////////////////////////////////////// +// Macros for AES +//////////////////////////////////////////////////////////////////////////// +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) + +#ifdef _MSC_VER + #define GETUINT32(p) SWAP(*((cc_u32 *)(p))) + #define PUTUINT32(ct, st) { *((cc_u32 *)(ct)) = SWAP((st)); } +#else + #define GETUINT32(pt) (((cc_u32)(pt)[0] << 24) ^ ((cc_u32)(pt)[1] << 16) ^ ((cc_u32)(pt)[2] << 8) ^ ((cc_u32)(pt)[3])) + #define PUTUINT32(ct, st) { (ct)[0] = (cc_u8)((st) >> 24); (ct)[1] = (cc_u8)((st) >> 16); (ct)[2] = (cc_u8)((st) >> 8); (ct)[3] = (cc_u8)(st); } +#endif + +/* + * @fn SDRM_rijndaelKeySetupEnc + * @brief Expand the cipher key into the encryption key schedule + * + * @param rk [out]expanded round key + * @param cipherKey [in]user key + * @param keyBits [in]bit-length of cipherKey + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_rijndaelKeySetupEnc(cc_u32 rk[/*4*(Nr + 1)*/], const cc_u8 cipherKey[], int keyBits) +{ + int i = 0; + cc_u32 temp; + + rk[0] = GETUINT32(cipherKey ); + rk[1] = GETUINT32(cipherKey + 4); + rk[2] = GETUINT32(cipherKey + 8); + rk[3] = GETUINT32(cipherKey + 12); + if (keyBits == 128) + { + for (;;) + { + temp = rk[3]; + rk[4] = rk[0] ^ + (SDRM_Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (SDRM_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(temp >> 24) ] & 0x000000ff) ^ + SDRM_rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) + { + return 10; + } + rk += 4; + } + } + + rk[4] = GETUINT32(cipherKey + 16); + rk[5] = GETUINT32(cipherKey + 20); + if (keyBits == 192) + { + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (SDRM_Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (SDRM_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(temp >> 24) ] & 0x000000ff) ^ + SDRM_rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) + { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETUINT32(cipherKey + 24); + rk[7] = GETUINT32(cipherKey + 28); + if (keyBits == 256) + { + for (;;) + { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (SDRM_Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (SDRM_Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(temp >> 24) ] & 0x000000ff) ^ + SDRM_rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (SDRM_Te4[(temp >> 24) ] & 0xff000000) ^ + (SDRM_Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_rijndaelKeySetupDec + * @brief Expand the cipher key into the decryption key schedule + * + * @param rk [out]expanded round key + * @param cipherKey [in]user key + * @param keyBits [in]bit-length of cipherKey + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_rijndaelKeySetupDec(cc_u32 rk[/*4*(Nr + 1)*/], const cc_u8 cipherKey[], int keyBits) +{ + int Nr, i, j; + cc_u32 temp; + + /* expand the cipher key: */ + Nr = SDRM_rijndaelKeySetupEnc(rk, cipherKey, keyBits); + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) + { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < Nr; i++) + { + rk += 4; + rk[0] = + SDRM_Td0[SDRM_Te4[(rk[0] >> 24) ] & 0xff] ^ + SDRM_Td1[SDRM_Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + SDRM_Td2[SDRM_Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + SDRM_Td3[SDRM_Te4[(rk[0] ) & 0xff] & 0xff]; + rk[1] = + SDRM_Td0[SDRM_Te4[(rk[1] >> 24) ] & 0xff] ^ + SDRM_Td1[SDRM_Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + SDRM_Td2[SDRM_Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + SDRM_Td3[SDRM_Te4[(rk[1] ) & 0xff] & 0xff]; + rk[2] = + SDRM_Td0[SDRM_Te4[(rk[2] >> 24) ] & 0xff] ^ + SDRM_Td1[SDRM_Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + SDRM_Td2[SDRM_Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + SDRM_Td3[SDRM_Te4[(rk[2] ) & 0xff] & 0xff]; + rk[3] = + SDRM_Td0[SDRM_Te4[(rk[3] >> 24) ] & 0xff] ^ + SDRM_Td1[SDRM_Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + SDRM_Td2[SDRM_Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + SDRM_Td3[SDRM_Te4[(rk[3] ) & 0xff] & 0xff]; + } + return Nr; +} + +/* + * @fn SDRM_rijndaelEncrypt + * @brief 16 byte AES Encryption with round key + * + * @param rk [in]expanded round key + * @param Nr [in]numer of rounds + * @param pt [in]plain text + * @param ct [out]cipher text + * + * @return void + */ +void SDRM_rijndaelEncrypt(const cc_u32 rk[/*4*(Nr + 1)*/], int Nr, const cc_u8 pt[16], cc_u8 ct[16]) +{ + cc_u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETUINT32(pt ) ^ rk[0]; + s1 = GETUINT32(pt + 4) ^ rk[1]; + s2 = GETUINT32(pt + 8) ^ rk[2]; + s3 = GETUINT32(pt + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[ 4]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[ 5]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[ 6]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = SDRM_Te0[t0 >> 24] ^ SDRM_Te1[(t1 >> 16) & 0xff] ^ SDRM_Te2[(t2 >> 8) & 0xff] ^ SDRM_Te3[t3 & 0xff] ^ rk[ 8]; + s1 = SDRM_Te0[t1 >> 24] ^ SDRM_Te1[(t2 >> 16) & 0xff] ^ SDRM_Te2[(t3 >> 8) & 0xff] ^ SDRM_Te3[t0 & 0xff] ^ rk[ 9]; + s2 = SDRM_Te0[t2 >> 24] ^ SDRM_Te1[(t3 >> 16) & 0xff] ^ SDRM_Te2[(t0 >> 8) & 0xff] ^ SDRM_Te3[t1 & 0xff] ^ rk[10]; + s3 = SDRM_Te0[t3 >> 24] ^ SDRM_Te1[(t0 >> 16) & 0xff] ^ SDRM_Te2[(t1 >> 8) & 0xff] ^ SDRM_Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[12]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[13]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[14]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = SDRM_Te0[t0 >> 24] ^ SDRM_Te1[(t1 >> 16) & 0xff] ^ SDRM_Te2[(t2 >> 8) & 0xff] ^ SDRM_Te3[t3 & 0xff] ^ rk[16]; + s1 = SDRM_Te0[t1 >> 24] ^ SDRM_Te1[(t2 >> 16) & 0xff] ^ SDRM_Te2[(t3 >> 8) & 0xff] ^ SDRM_Te3[t0 & 0xff] ^ rk[17]; + s2 = SDRM_Te0[t2 >> 24] ^ SDRM_Te1[(t3 >> 16) & 0xff] ^ SDRM_Te2[(t0 >> 8) & 0xff] ^ SDRM_Te3[t1 & 0xff] ^ rk[18]; + s3 = SDRM_Te0[t3 >> 24] ^ SDRM_Te1[(t0 >> 16) & 0xff] ^ SDRM_Te2[(t1 >> 8) & 0xff] ^ SDRM_Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[20]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[21]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[22]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = SDRM_Te0[t0 >> 24] ^ SDRM_Te1[(t1 >> 16) & 0xff] ^ SDRM_Te2[(t2 >> 8) & 0xff] ^ SDRM_Te3[t3 & 0xff] ^ rk[24]; + s1 = SDRM_Te0[t1 >> 24] ^ SDRM_Te1[(t2 >> 16) & 0xff] ^ SDRM_Te2[(t3 >> 8) & 0xff] ^ SDRM_Te3[t0 & 0xff] ^ rk[25]; + s2 = SDRM_Te0[t2 >> 24] ^ SDRM_Te1[(t3 >> 16) & 0xff] ^ SDRM_Te2[(t0 >> 8) & 0xff] ^ SDRM_Te3[t1 & 0xff] ^ rk[26]; + s3 = SDRM_Te0[t3 >> 24] ^ SDRM_Te1[(t0 >> 16) & 0xff] ^ SDRM_Te2[(t1 >> 8) & 0xff] ^ SDRM_Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[28]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[29]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[30]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = SDRM_Te0[t0 >> 24] ^ SDRM_Te1[(t1 >> 16) & 0xff] ^ SDRM_Te2[(t2 >> 8) & 0xff] ^ SDRM_Te3[t3 & 0xff] ^ rk[32]; + s1 = SDRM_Te0[t1 >> 24] ^ SDRM_Te1[(t2 >> 16) & 0xff] ^ SDRM_Te2[(t3 >> 8) & 0xff] ^ SDRM_Te3[t0 & 0xff] ^ rk[33]; + s2 = SDRM_Te0[t2 >> 24] ^ SDRM_Te1[(t3 >> 16) & 0xff] ^ SDRM_Te2[(t0 >> 8) & 0xff] ^ SDRM_Te3[t1 & 0xff] ^ rk[34]; + s3 = SDRM_Te0[t3 >> 24] ^ SDRM_Te1[(t0 >> 16) & 0xff] ^ SDRM_Te2[(t1 >> 8) & 0xff] ^ SDRM_Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[36]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[37]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[38]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[39]; + if (Nr > 10) + { + /* round 10: */ + s0 = SDRM_Te0[t0 >> 24] ^ SDRM_Te1[(t1 >> 16) & 0xff] ^ SDRM_Te2[(t2 >> 8) & 0xff] ^ SDRM_Te3[t3 & 0xff] ^ rk[40]; + s1 = SDRM_Te0[t1 >> 24] ^ SDRM_Te1[(t2 >> 16) & 0xff] ^ SDRM_Te2[(t3 >> 8) & 0xff] ^ SDRM_Te3[t0 & 0xff] ^ rk[41]; + s2 = SDRM_Te0[t2 >> 24] ^ SDRM_Te1[(t3 >> 16) & 0xff] ^ SDRM_Te2[(t0 >> 8) & 0xff] ^ SDRM_Te3[t1 & 0xff] ^ rk[42]; + s3 = SDRM_Te0[t3 >> 24] ^ SDRM_Te1[(t0 >> 16) & 0xff] ^ SDRM_Te2[(t1 >> 8) & 0xff] ^ SDRM_Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[44]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[45]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[46]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = SDRM_Te0[t0 >> 24] ^ SDRM_Te1[(t1 >> 16) & 0xff] ^ SDRM_Te2[(t2 >> 8) & 0xff] ^ SDRM_Te3[t3 & 0xff] ^ rk[48]; + s1 = SDRM_Te0[t1 >> 24] ^ SDRM_Te1[(t2 >> 16) & 0xff] ^ SDRM_Te2[(t3 >> 8) & 0xff] ^ SDRM_Te3[t0 & 0xff] ^ rk[49]; + s2 = SDRM_Te0[t2 >> 24] ^ SDRM_Te1[(t3 >> 16) & 0xff] ^ SDRM_Te2[(t0 >> 8) & 0xff] ^ SDRM_Te3[t1 & 0xff] ^ rk[50]; + s3 = SDRM_Te0[t3 >> 24] ^ SDRM_Te1[(t0 >> 16) & 0xff] ^ SDRM_Te2[(t1 >> 8) & 0xff] ^ SDRM_Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = SDRM_Te0[s0 >> 24] ^ SDRM_Te1[(s1 >> 16) & 0xff] ^ SDRM_Te2[(s2 >> 8) & 0xff] ^ SDRM_Te3[s3 & 0xff] ^ rk[52]; + t1 = SDRM_Te0[s1 >> 24] ^ SDRM_Te1[(s2 >> 16) & 0xff] ^ SDRM_Te2[(s3 >> 8) & 0xff] ^ SDRM_Te3[s0 & 0xff] ^ rk[53]; + t2 = SDRM_Te0[s2 >> 24] ^ SDRM_Te1[(s3 >> 16) & 0xff] ^ SDRM_Te2[(s0 >> 8) & 0xff] ^ SDRM_Te3[s1 & 0xff] ^ rk[54]; + t3 = SDRM_Te0[s3 >> 24] ^ SDRM_Te1[(s0 >> 16) & 0xff] ^ SDRM_Te2[(s1 >> 8) & 0xff] ^ SDRM_Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) + { + t0 = + SDRM_Te0[(s0 >> 24) ] ^ + SDRM_Te1[(s1 >> 16) & 0xff] ^ + SDRM_Te2[(s2 >> 8) & 0xff] ^ + SDRM_Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + SDRM_Te0[(s1 >> 24) ] ^ + SDRM_Te1[(s2 >> 16) & 0xff] ^ + SDRM_Te2[(s3 >> 8) & 0xff] ^ + SDRM_Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + SDRM_Te0[(s2 >> 24) ] ^ + SDRM_Te1[(s3 >> 16) & 0xff] ^ + SDRM_Te2[(s0 >> 8) & 0xff] ^ + SDRM_Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + SDRM_Te0[(s3 >> 24) ] ^ + SDRM_Te1[(s0 >> 16) & 0xff] ^ + SDRM_Te2[(s1 >> 8) & 0xff] ^ + SDRM_Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) + { + break; + } + + s0 = + SDRM_Te0[(t0 >> 24) ] ^ + SDRM_Te1[(t1 >> 16) & 0xff] ^ + SDRM_Te2[(t2 >> 8) & 0xff] ^ + SDRM_Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + SDRM_Te0[(t1 >> 24) ] ^ + SDRM_Te1[(t2 >> 16) & 0xff] ^ + SDRM_Te2[(t3 >> 8) & 0xff] ^ + SDRM_Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + SDRM_Te0[(t2 >> 24) ] ^ + SDRM_Te1[(t3 >> 16) & 0xff] ^ + SDRM_Te2[(t0 >> 8) & 0xff] ^ + SDRM_Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + SDRM_Te0[(t3 >> 24) ] ^ + SDRM_Te1[(t0 >> 16) & 0xff] ^ + SDRM_Te2[(t1 >> 8) & 0xff] ^ + SDRM_Te3[(t2 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (SDRM_Te4[(t0 >> 24) ] & 0xff000000) ^ + (SDRM_Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTUINT32(ct , s0); + s1 = + (SDRM_Te4[(t1 >> 24) ] & 0xff000000) ^ + (SDRM_Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTUINT32(ct + 4, s1); + s2 = + (SDRM_Te4[(t2 >> 24) ] & 0xff000000) ^ + (SDRM_Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTUINT32(ct + 8, s2); + s3 = + (SDRM_Te4[(t3 >> 24) ] & 0xff000000) ^ + (SDRM_Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTUINT32(ct + 12, s3); +} + +/* + * @fn SDRM_rijndaelDecrypt + * @brief 16 byte AES Decryption with round key + * + * @param rk [in]expanded round key + * @param Nr [in]numer of rounds + * @param ct [in]cipher text + * @param pt [out]plain text + * + * @return void + */ +void SDRM_rijndaelDecrypt(const cc_u32 rk[/*4*(Nr + 1)*/], int Nr, const cc_u8 ct[16], cc_u8 pt[16]) +{ + cc_u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETUINT32(ct ) ^ rk[0]; + s1 = GETUINT32(ct + 4) ^ rk[1]; + s2 = GETUINT32(ct + 8) ^ rk[2]; + s3 = GETUINT32(ct + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[ 4]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[ 5]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[ 6]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[ 7]; + /* round 2: */ + s0 = SDRM_Td0[t0 >> 24] ^ SDRM_Td1[(t3 >> 16) & 0xff] ^ SDRM_Td2[(t2 >> 8) & 0xff] ^ SDRM_Td3[t1 & 0xff] ^ rk[ 8]; + s1 = SDRM_Td0[t1 >> 24] ^ SDRM_Td1[(t0 >> 16) & 0xff] ^ SDRM_Td2[(t3 >> 8) & 0xff] ^ SDRM_Td3[t2 & 0xff] ^ rk[ 9]; + s2 = SDRM_Td0[t2 >> 24] ^ SDRM_Td1[(t1 >> 16) & 0xff] ^ SDRM_Td2[(t0 >> 8) & 0xff] ^ SDRM_Td3[t3 & 0xff] ^ rk[10]; + s3 = SDRM_Td0[t3 >> 24] ^ SDRM_Td1[(t2 >> 16) & 0xff] ^ SDRM_Td2[(t1 >> 8) & 0xff] ^ SDRM_Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[12]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[13]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[14]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = SDRM_Td0[t0 >> 24] ^ SDRM_Td1[(t3 >> 16) & 0xff] ^ SDRM_Td2[(t2 >> 8) & 0xff] ^ SDRM_Td3[t1 & 0xff] ^ rk[16]; + s1 = SDRM_Td0[t1 >> 24] ^ SDRM_Td1[(t0 >> 16) & 0xff] ^ SDRM_Td2[(t3 >> 8) & 0xff] ^ SDRM_Td3[t2 & 0xff] ^ rk[17]; + s2 = SDRM_Td0[t2 >> 24] ^ SDRM_Td1[(t1 >> 16) & 0xff] ^ SDRM_Td2[(t0 >> 8) & 0xff] ^ SDRM_Td3[t3 & 0xff] ^ rk[18]; + s3 = SDRM_Td0[t3 >> 24] ^ SDRM_Td1[(t2 >> 16) & 0xff] ^ SDRM_Td2[(t1 >> 8) & 0xff] ^ SDRM_Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[20]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[21]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[22]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = SDRM_Td0[t0 >> 24] ^ SDRM_Td1[(t3 >> 16) & 0xff] ^ SDRM_Td2[(t2 >> 8) & 0xff] ^ SDRM_Td3[t1 & 0xff] ^ rk[24]; + s1 = SDRM_Td0[t1 >> 24] ^ SDRM_Td1[(t0 >> 16) & 0xff] ^ SDRM_Td2[(t3 >> 8) & 0xff] ^ SDRM_Td3[t2 & 0xff] ^ rk[25]; + s2 = SDRM_Td0[t2 >> 24] ^ SDRM_Td1[(t1 >> 16) & 0xff] ^ SDRM_Td2[(t0 >> 8) & 0xff] ^ SDRM_Td3[t3 & 0xff] ^ rk[26]; + s3 = SDRM_Td0[t3 >> 24] ^ SDRM_Td1[(t2 >> 16) & 0xff] ^ SDRM_Td2[(t1 >> 8) & 0xff] ^ SDRM_Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[28]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[29]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[30]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = SDRM_Td0[t0 >> 24] ^ SDRM_Td1[(t3 >> 16) & 0xff] ^ SDRM_Td2[(t2 >> 8) & 0xff] ^ SDRM_Td3[t1 & 0xff] ^ rk[32]; + s1 = SDRM_Td0[t1 >> 24] ^ SDRM_Td1[(t0 >> 16) & 0xff] ^ SDRM_Td2[(t3 >> 8) & 0xff] ^ SDRM_Td3[t2 & 0xff] ^ rk[33]; + s2 = SDRM_Td0[t2 >> 24] ^ SDRM_Td1[(t1 >> 16) & 0xff] ^ SDRM_Td2[(t0 >> 8) & 0xff] ^ SDRM_Td3[t3 & 0xff] ^ rk[34]; + s3 = SDRM_Td0[t3 >> 24] ^ SDRM_Td1[(t2 >> 16) & 0xff] ^ SDRM_Td2[(t1 >> 8) & 0xff] ^ SDRM_Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[36]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[37]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[38]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[39]; + if (Nr > 10) + { + /* round 10: */ + s0 = SDRM_Td0[t0 >> 24] ^ SDRM_Td1[(t3 >> 16) & 0xff] ^ SDRM_Td2[(t2 >> 8) & 0xff] ^ SDRM_Td3[t1 & 0xff] ^ rk[40]; + s1 = SDRM_Td0[t1 >> 24] ^ SDRM_Td1[(t0 >> 16) & 0xff] ^ SDRM_Td2[(t3 >> 8) & 0xff] ^ SDRM_Td3[t2 & 0xff] ^ rk[41]; + s2 = SDRM_Td0[t2 >> 24] ^ SDRM_Td1[(t1 >> 16) & 0xff] ^ SDRM_Td2[(t0 >> 8) & 0xff] ^ SDRM_Td3[t3 & 0xff] ^ rk[42]; + s3 = SDRM_Td0[t3 >> 24] ^ SDRM_Td1[(t2 >> 16) & 0xff] ^ SDRM_Td2[(t1 >> 8) & 0xff] ^ SDRM_Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[44]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[45]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[46]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[47]; + if (Nr > 12) { + /* round 12: */ + s0 = SDRM_Td0[t0 >> 24] ^ SDRM_Td1[(t3 >> 16) & 0xff] ^ SDRM_Td2[(t2 >> 8) & 0xff] ^ SDRM_Td3[t1 & 0xff] ^ rk[48]; + s1 = SDRM_Td0[t1 >> 24] ^ SDRM_Td1[(t0 >> 16) & 0xff] ^ SDRM_Td2[(t3 >> 8) & 0xff] ^ SDRM_Td3[t2 & 0xff] ^ rk[49]; + s2 = SDRM_Td0[t2 >> 24] ^ SDRM_Td1[(t1 >> 16) & 0xff] ^ SDRM_Td2[(t0 >> 8) & 0xff] ^ SDRM_Td3[t3 & 0xff] ^ rk[50]; + s3 = SDRM_Td0[t3 >> 24] ^ SDRM_Td1[(t2 >> 16) & 0xff] ^ SDRM_Td2[(t1 >> 8) & 0xff] ^ SDRM_Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = SDRM_Td0[s0 >> 24] ^ SDRM_Td1[(s3 >> 16) & 0xff] ^ SDRM_Td2[(s2 >> 8) & 0xff] ^ SDRM_Td3[s1 & 0xff] ^ rk[52]; + t1 = SDRM_Td0[s1 >> 24] ^ SDRM_Td1[(s0 >> 16) & 0xff] ^ SDRM_Td2[(s3 >> 8) & 0xff] ^ SDRM_Td3[s2 & 0xff] ^ rk[53]; + t2 = SDRM_Td0[s2 >> 24] ^ SDRM_Td1[(s1 >> 16) & 0xff] ^ SDRM_Td2[(s0 >> 8) & 0xff] ^ SDRM_Td3[s3 & 0xff] ^ rk[54]; + t3 = SDRM_Td0[s3 >> 24] ^ SDRM_Td1[(s2 >> 16) & 0xff] ^ SDRM_Td2[(s1 >> 8) & 0xff] ^ SDRM_Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += Nr << 2; +#else /* !FULL_UNROLL */ + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) + { + t0 = + SDRM_Td0[(s0 >> 24) ] ^ + SDRM_Td1[(s3 >> 16) & 0xff] ^ + SDRM_Td2[(s2 >> 8) & 0xff] ^ + SDRM_Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + SDRM_Td0[(s1 >> 24) ] ^ + SDRM_Td1[(s0 >> 16) & 0xff] ^ + SDRM_Td2[(s3 >> 8) & 0xff] ^ + SDRM_Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + SDRM_Td0[(s2 >> 24) ] ^ + SDRM_Td1[(s1 >> 16) & 0xff] ^ + SDRM_Td2[(s0 >> 8) & 0xff] ^ + SDRM_Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + SDRM_Td0[(s3 >> 24) ] ^ + SDRM_Td1[(s2 >> 16) & 0xff] ^ + SDRM_Td2[(s1 >> 8) & 0xff] ^ + SDRM_Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) + { + break; + } + + s0 = + SDRM_Td0[(t0 >> 24) ] ^ + SDRM_Td1[(t3 >> 16) & 0xff] ^ + SDRM_Td2[(t2 >> 8) & 0xff] ^ + SDRM_Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + SDRM_Td0[(t1 >> 24) ] ^ + SDRM_Td1[(t0 >> 16) & 0xff] ^ + SDRM_Td2[(t3 >> 8) & 0xff] ^ + SDRM_Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + SDRM_Td0[(t2 >> 24) ] ^ + SDRM_Td1[(t1 >> 16) & 0xff] ^ + SDRM_Td2[(t0 >> 8) & 0xff] ^ + SDRM_Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + SDRM_Td0[(t3 >> 24) ] ^ + SDRM_Td1[(t2 >> 16) & 0xff] ^ + SDRM_Td2[(t1 >> 8) & 0xff] ^ + SDRM_Td3[(t0 ) & 0xff] ^ + rk[3]; + } +#endif /* ?FULL_UNROLL */ + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (SDRM_Td4[(t0 >> 24) ] & 0xff000000) ^ + (SDRM_Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTUINT32(pt , s0); + s1 = + (SDRM_Td4[(t1 >> 24) ] & 0xff000000) ^ + (SDRM_Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTUINT32(pt + 4, s1); + s2 = + (SDRM_Td4[(t2 >> 24) ] & 0xff000000) ^ + (SDRM_Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTUINT32(pt + 8, s2); + s3 = + (SDRM_Td4[(t3 >> 24) ] & 0xff000000) ^ + (SDRM_Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (SDRM_Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (SDRM_Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTUINT32(pt + 12, s3); +} + +/* + * @fn SDRM_AES128_Encryption + * @brief AES-128 Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES128_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[4*(10 + 1)]; + + SDRM_rijndaelKeySetupEnc(RoundKey, UserKey, 128); + + SDRM_rijndaelEncrypt(RoundKey, 10, plainText, cipherText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_AES128_Decryption + * @brief AES-128 Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES128_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[4*(10 + 1)]; + + SDRM_rijndaelKeySetupDec(RoundKey, UserKey, 128); + + SDRM_rijndaelDecrypt(RoundKey, 10, cipherText, plainText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_AES192_Encryption + * @brief AES-192 Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES192_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[4*(12 + 1)]; + + SDRM_rijndaelKeySetupEnc(RoundKey, UserKey, 192); + + SDRM_rijndaelEncrypt(RoundKey, 12, plainText, cipherText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_AES192_Decryption + * @brief AES-192 Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES192_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[4*(12 + 1)]; + + SDRM_rijndaelKeySetupDec(RoundKey, UserKey, 192); + + SDRM_rijndaelDecrypt(RoundKey, 12, cipherText, plainText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_AES256_Encryption + * @brief AES-256 Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES256_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[4*(14 + 1)]; + + SDRM_rijndaelKeySetupEnc(RoundKey, UserKey, 256); + + SDRM_rijndaelEncrypt(RoundKey, 14, plainText, cipherText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_AES256_Decryption + * @brief AES-256 Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_AES256_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[4*(14 + 1)]; + + SDRM_rijndaelKeySetupDec(RoundKey, UserKey, 256); + + SDRM_rijndaelDecrypt(RoundKey, 14, cipherText, plainText); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/base/cc_bignum.c b/ssflib/dep/cryptocore/source/base/cc_bignum.c new file mode 100755 index 0000000..07016ab --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_bignum.c @@ -0,0 +1,3202 @@ +/** + * \file bignum.c + * @brief big number library + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/03 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_bignum.h" +#include "cc_fast_math.h" +//////////////////////////////////////////////////////////////////////////// +// Global Variables +//////////////////////////////////////////////////////////////////////////// +cc_u32 DWD_Zero[2] = {0, 0}; +cc_u32 DWD_One[2] = {1, 0}; + +SDRM_BIG_NUM _BN_Zero = {0, 0, 2, DWD_Zero}; +SDRM_BIG_NUM _BN_One = {0, 1, 2, DWD_One}; + +SDRM_BIG_NUM *BN_Zero = &_BN_Zero; +SDRM_BIG_NUM *BN_One = &_BN_One; + +//////////////////////////////////////////////////////////////////////////// +// Local Functon Protypes +//////////////////////////////////////////////////////////////////////////// +int SDRM_DWD_Classical_REDC(cc_u32 *pdDest, cc_u32 DstLen, cc_u32 *pdModulus, cc_u32 ModLen); + +#ifdef _OP64_NOTSUPPORTED + +#define SDRM_HL(A) (cc_u32)(((A) >> 16) & 0xffffu) +#define SDRM_LL(A) (cc_u32)((A) & 0xffffu) +#define SDRM_LH(A) (cc_u32)(((A) & 0xffffu) << 16) +#define NOT(A) (~(A)) + +/* + * @fn SDRM_DIGIT_Mul + * @brief Double-width UINT32 Multiplication + * + * \n Dest [out]destination, 2-cc_u32-size array + * \n Src1 [in]first element + * \n Src2 [in]second element + * + * @return void + */ +void SDRM_DIGIT_Mul(cc_u32 *Dest, cc_u32 Src1, cc_u32 Src2) +{ + cc_u32 Da, Db, R1, R0; + + R1 = SDRM_HL(Src1) * SDRM_HL(Src2); + R0 = SDRM_LL(Src1) * SDRM_LL(Src2); + + Da = SDRM_HL(Src1) * SDRM_LL(Src2); + Db = SDRM_LL(Src1) * SDRM_HL(Src2); + + if ((Db += Da) < Da) { + R1 += ((cc_u32)1) << 16; + } + if ((R0 += SDRM_LH(Db)) < SDRM_LH(Db)) { + R1++; + } + + Dest[0] = R0; + Dest[1] = R1 + SDRM_HL(Db); + + return; +} + +/* + * @fn SDRM_DIGIT_Div + * @brief Doublue-width DWROD Division + * + * \n Src1 [in]upper-digit of dividend + * \n Src2 [in]lower-digit of dividend + * \n Div [in]divisor + */ +cc_u32 SDRM_DIGIT_Div(cc_u32 Src1, cc_u32 Src2, cc_u32 Div) +{ + cc_u32 Dq, Dr, Dx, Dy, Dt; + + // Estimate high half of quotient + Dq = Src1 / (SDRM_HL(Div) + 1); + + // Subtract the product of estimate and divisor from the dividend + Dr = Src1 - (SDRM_HL(Div) * Dq); + Dx = SDRM_HL(Dr); + Dy = SDRM_LH(Dr) + SDRM_HL(Src2); + if ((Dr = Dy - (SDRM_LL(Div) * Dq)) > Dy) + { + Dx--; + } + + // Correct estimate + while ((Dx > 0) || ((Dx == 0) && (Dr >= Div))) + { + if((Dr -= Div) > NOT(Div)) + { + Dx--; + } + Dq++; + } + Dt = SDRM_LH(Dq); + + // Estimate low half of quotient + Dq = Dr / (SDRM_HL(Div) + 1); + + // Subtract the product of estimate and divisor from the dividend + Dr -= SDRM_HL(Div) * Dq; + Dx = SDRM_HL(Dr); + Dy = SDRM_LH(Dr) + SDRM_LL(Src2); + if ((Dr = Dy - (SDRM_LL(Div) * Dq)) > Dy) { + Dx--; + } + + // Correct estimate + while ((Dx > 0) || ((Dx == 0) && (Dr >= Div))) + { + if ((Dr -= Div) > NOT(Div)) + { + Dx--; + } + Dq++; + } + + return (Dt + Dq); +} + +/* + * @fn SDRM_DIGIT_Mod + * @brief Doublue-width DWROD Modular + * + * \n Src1 [in]upper-digit of dividend + * \n Src2 [in]lower-digit of dividend + * \n Div [in]divisor + */ +cc_u32 SDRM_DIGIT_Mod(cc_u32 Src1, cc_u32 Src2, cc_u32 Div) +{ + cc_u32 Dq, Dr, Dx, Dy; + + // Estimate high half of quotient + Dq = Src1 / (SDRM_HL(Div) + 1); + + // Subtract the from dividend the product of estimate and divisor + Dr = Src1 - (SDRM_HL(Div) * Dq); + Dx = SDRM_HL(Dr); + Dy = SDRM_LH(Dr) + SDRM_HL(Src2); + if ((Dr = Dy - (SDRM_LL(Div) * Dq)) > Dy) + { + Dx--; + } + + // Correct estimate + while ((Dx > 0) || ((Dx == 0) && (Dr >= Div))) + { + if ((Dr -= Div) > NOT(Div)) + { + Dx--; + } + } + + // Estimate low half of quotient + Dq = Dr / (SDRM_HL(Div) + 1); + + // Subtract the from dividend the product of estimate and divisor + Dr -= SDRM_HL(Div) * Dq; + Dx = SDRM_HL(Dr); + Dy = SDRM_LH(Dr) + SDRM_LL(Src2); + if ((Dr = Dy - (SDRM_LL(Div) * Dq)) > Dy) + { + Dx--; + } + + // Correct estimate + while ((Dx > 0) || ((Dx == 0) && (Dr >= Div))) + { + if ((Dr -= Div) > NOT(Div) ) + { + Dx--; + } + } + + return Dr; +} + +#endif //_OP64_NOTSUPPORTED + +/* + * @fn SDRM_DWD_Cmp + * @brief cc_u32 Array Comparison + * + * @param pdSrc1 [in]first element + * @param dSrcLen1 [in]legnth of pdSrc1 + * @param pdSrc2 [in]second element + * @param dSrcLen2 [in]legnth of pdSrc2 + * + * @return 1 if pdSrc1 is larger than pdSrc2 + * \n 0 if same + * \n -1 if pdSrc2 is larger than pdSrc1 + */ +static int SDRM_DWD_Cmp(cc_u32 *pdSrc1, cc_u32 dSrcLen1, cc_u32 *pdSrc2, cc_u32 dSrcLen2) +{ + cc_u32 i; + + //When the length is different + if (dSrcLen1 >= dSrcLen2) + { + for (i = dSrcLen1 - 1; i != dSrcLen2 - 1; i--) + { + if (pdSrc1[i]) + { + return +1; + } + } + } + else + { + for (i = dSrcLen2 - 1; i != dSrcLen1 - 1; i--) + { + if (pdSrc2[i]) + { + return -1; + } + } + } + + //Compare common digits + for (; i != (cc_u32)-1; i--) + { + if (pdSrc1[i] == pdSrc2[i]) + { + continue; + } + else + { + if (pdSrc1[i] > pdSrc2[i]) + { + return +1; + } + else + { + return -1; + } + } + } + + return 0; +} + +/* + * @fn SDRM_DWD_SHL + * @brief Shift left the digit array + * + * @param pdDest [out]destination + * @param pdSrc [in]source + * @param dSrcLen [in]legnth of pdSrc + * @param dNumOfShift [in]shift amount + * + * @return carry + */ +static cc_u32 SDRM_DWD_SHL(cc_u32 *pdDest, cc_u32 *pdSrc, cc_u32 dSrcLen, cc_u32 dNumOfShift) +{ + cc_u32 i = dSrcLen - 1; + cc_u32 dRet; + + if (dSrcLen == 0) + { + *pdDest = 0; + return 0; + } + + dRet = pdSrc[i] >> (SDRM_BitsInDWORD - dNumOfShift); + + for (; i != 0; i--) + { + pdDest[i] = (pdSrc[i] << dNumOfShift) ^ (pdSrc[i - 1] >> (SDRM_BitsInDWORD - dNumOfShift)); + } + + pdDest[i] = pdSrc[i] << dNumOfShift; + + return dRet; +} + +/* + * @fn SDRM_DWD_SHR + * @brief Shift right the digit array + * + * @param pdDest [out]destination + * @param pdSrc [in]source + * @param dSrcLen [in]legnth of pdSrc + * @param dNumOfShift [in]shift amount + * + * @return carry + */ +static cc_u32 SDRM_DWD_SHR(cc_u32 *pdDest, cc_u32 *pdSrc, cc_u32 dSrcLen, cc_u32 dNumOfShift) +{ + cc_u32 i = 0; + cc_u32 dRet; + + dRet = pdSrc[i] << (SDRM_BitsInDWORD - dNumOfShift); + + for (; i < dSrcLen - 1; i++) + { + pdDest[i] = (pdSrc[i] >> dNumOfShift) ^ (pdSrc[i + 1] << (SDRM_BitsInDWORD - dNumOfShift)); + } + + pdDest[i] = pdSrc[i] >> dNumOfShift; + + return dRet; +} + +/* + * @fn SDRM_DWD_Add + * @brief Add two digit array + * + * @param pdDest [out]destination + * @param pdSrc1 [in]first element + * @param dSrcLen1 [in]legnth of pdSrc1 + * @param pdSrc2 [in]second element + * @param dSrcLen2 [in]legnth of pdSrc2 + * + * @return carry + */ +static cc_u32 SDRM_DWD_Add(cc_u32 *pdDest, cc_u32 *pdSrc1, cc_u32 dSrcLen1, cc_u32 *pdSrc2, cc_u32 dSrcLen2) +{ + cc_u32 i; + cc_u32 dCarry = 0, dTemp; + + //add low digits + for (i = 0; i < dSrcLen2; i++) + { + if ((pdSrc2[i] == ((cc_u32)-1)) && (dCarry)) + { + pdDest[i] = pdSrc1[i]; + } + else + { + dTemp = pdSrc2[i] + dCarry; + pdDest[i] = pdSrc1[i] + dTemp; + dCarry = (pdDest[i] < dTemp ) ? 1 : 0; + } + } + + //copy high digits + if (dSrcLen1 > i) + { + memcpy(pdDest + i, pdSrc1 + i, (dSrcLen1 - i) * SDRM_SIZE_OF_DWORD); + } + + //process carry + if (!dCarry) + { + return 0; + } + else + { + for (i = dSrcLen2; i < dSrcLen1; i++) + { + if (++pdDest[i]) + { + return 0; + } + } + } + + return 1; +} + +/* + * @fn SDRM_DWD_Sub + * @brief subtract digit array + * + * @param pdDest [out]destination + * @param pdSrc1 [in]first element + * @param dSrcLen1 [in]legnth of pdSrc1 + * @param pdSrc2 [in]second element + * @param dSrcLen2 [in]legnth of pdSrc2 + * + * @return carry + */ +static cc_u32 SDRM_DWD_Sub(cc_u32 *pdDest, cc_u32 *pdSrc1, cc_u32 dSrcLen1, cc_u32 *pdSrc2, cc_u32 dSrcLen2) +{ + cc_u32 i; + cc_u32 dCarry = 0, dTemp; + + //subtract low digits + for (i = 0; i < dSrcLen2; i++) + { + if (pdSrc2[i] + dCarry == 0) + { + pdDest[i] = pdSrc1[i]; + } + else + { + dTemp = pdSrc2[i] + dCarry; + pdDest[i] = pdSrc1[i] - dTemp; + dCarry = ((pdDest[i]) > ~(dTemp)) ? 1 : 0; + } + } + + //copy high digits + if (dSrcLen1 > i) + { + memcpy(pdDest + i, pdSrc1 + i, (dSrcLen1 - i) * SDRM_SIZE_OF_DWORD); + } + + //process carry + if (!dCarry) + { + return 0; + } + else + { + for (i = dSrcLen2 ; i < dSrcLen1; i++) + { + if (pdDest[i]--) + { + return 0; + } + } + } + + return (~0); +} + +/* + * @fn SDRM_DWD_MulAdd + * @brief Add multiple + * + * @param pdDest [out]destination + * @param dDstLen [in]legnth of pbDest + * @param pdSrc [in]source + * @param dSrcLen [in]legnth of pdSrc + * @param dMultiplier [in]multiplier + * + * @return carry + */ +static cc_u32 SDRM_DWD_MulAdd(cc_u32 *pdDest, cc_u32 dDstLen, cc_u32 *pdSrc, cc_u32 dSrcLen, cc_u32 dMultiplier) +{ + cc_u32 i; + cc_u32 dTemp = 0; + cc_u64 pdDigit2; + + //Multiplication part + for (i = 0; i < dSrcLen; i++) + { + /* + * Time code optimization. To be continue! + */ + pdDigit2 =((cc_u64)pdSrc[i] * dMultiplier) + pdDest[i] + dTemp; + pdDest[i] = (cc_u32)pdDigit2; + dTemp = pdDigit2 >> 32; + + /*SDRM_DIGIT_Mul(pdDigit, dMultiplier, pdSrc[i]); + if ((dTemp += pdDigit[0]) < pdDigit[0]) + { + pdDigit[1]++; + } + + if ((pdDest[i] += dTemp) < dTemp) + { + pdDigit[1]++; + } + + dTemp = pdDigit[1];*/ + } + + if (i == dDstLen) + { + return dTemp; + } + + //process top digit + if ((pdDest[i] += dTemp) >= dTemp) + { + return 0; + } + + for (i++; i < dDstLen; i++) + { + if ((++pdDest[i]) != 0) + { + return 0; + } + } + + return 1; +} + +/* + * @fn SDRM_DWD_MulSub + * @brief Multiply and Subtract Digit Array + * + * @param pdDest [out]destination + * @param dDstLen [in]legnth of pbDest + * @param pdSrc [in]source + * @param dSrcLen [in]legnth of pdSrc + * @param dMultiplier [in]multiplier + * + * @return carry + */ +static cc_u32 SDRM_DWD_MulSub(cc_u32 *pdDest, cc_u32 dDstLen, cc_u32 *pdSrc, cc_u32 dSrcLen, cc_u32 dMultiplier) +{ + cc_u32 i; + cc_u32 pdDigit[2], dTemp = 0; + + //Multiplication part + for (i = 0; i < dSrcLen; i++) + { + SDRM_DIGIT_Mul(pdDigit, dMultiplier, pdSrc[i]); + dTemp += pdDigit[0]; + + if (dTemp < pdDigit[0]) + { + pdDigit[1]++; + } + + if (pdDest[i] < dTemp) + { + pdDigit[1]++; + } + + pdDest[i] -= dTemp; + dTemp = pdDigit[1]; + } + + if (i == dDstLen) + { + return dTemp; + } + + //process top digit + if (pdDest[i] >= dTemp) + { + pdDest[i] -= dTemp; + + return 0; + } + else + { + pdDest[i] -= dTemp; + } + + for (i++; i < dDstLen; i++) + { + if ((pdDest[i]--) != 0) + { + return 0; + } + } + + return 1; +} + +/* + * @fn SDRM_DWD_Mul + * @brief Multiply tow Digit array + * + * @param pdDest [out]destination + * @param pdSrc1 [in]first element + * @param dSrcLen1 [in]legnth of pdSrc1 + * @param pdSrc2 [in]second element + * @param dSrcLen2 [in]legnth of pdSrc2 + * + * @return void + */ +static void SDRM_DWD_Mul(cc_u32 *pdDest, cc_u32 *pdSrc1, cc_u32 dSrcLen1, cc_u32 *pdSrc2, cc_u32 dSrcLen2) +{ + cc_u32 i, j; + cc_u32 dTemp; + cc_u64 pdDigit2; + + memset(pdDest, 0, (dSrcLen1 + dSrcLen2) * SDRM_SIZE_OF_DWORD); + + for (j = 0; j < dSrcLen2; j++) + { + dTemp = 0; + for (i = 0; i < dSrcLen1; i++) + { + + pdDigit2 =((cc_u64)pdSrc1[i] * pdSrc2[j]) + pdDest[i + j] + dTemp; + pdDest[i + j] = (cc_u32)pdDigit2; + dTemp = pdDigit2 >> 32; + + + /*SDRM_DIGIT_Mul(pdDigit, pdSrc1[i], pdSrc2[j]); + if ((dTemp += pdDigit[0]) < pdDigit[0]) + { + pdDigit[1]++; + } + + if ((pdDest[i + j] += dTemp) < dTemp) + { + pdDigit[1]++; + } + + dTemp = pdDigit[1];*/ + } + pdDest[i + j] = dTemp; + } +} + +/* + * @fn SDRM_DWD_Div + * @brief Multiply tow Digit array + * + * @param pdDest [out]quotient + * @param pdRem [out]remainder + * @param pdSrc1 [in]divisor + * @param dSrcLen1 [in]legnth of pdSrc1 + * @param pdSrc2 [in]dividend + * @param dSrcLen2 [in]legnth of pdSrc2 + * + * @return 0 if reaminder is zero + * \n 1 otherwise + */ +static cc_u32 SDRM_DWD_Div(cc_u32 *pdDest, cc_u32 *pdRem, + cc_u32 *pdSrc1, cc_u32 dSrcLen1, + cc_u32 *pdSrc2, cc_u32 dSrcLen2) +{ + cc_u32 i, q, c, dNum_of_Shift = 0; + cc_u32 *C = (cc_u32*)malloc(SDRM_SIZE_OF_DWORD * 2 * (MAX2(dSrcLen1, dSrcLen2) + 2)); + + if (!C) + { + return (cc_u32)CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_DWD_Copy(C, pdSrc1, dSrcLen1); + C[dSrcLen1] = 0; + c = dSrcLen1 + 1; + + //Remove lowest '0's + for (i = dSrcLen2 * SDRM_BitsInDWORD-1; !SDRM_CheckBitUINT32(pdSrc2, i); i--, dNum_of_Shift++); + + if (dNum_of_Shift) + { + SDRM_DWD_SHL(C, C, c, dNum_of_Shift); + SDRM_DWD_SHL(pdSrc2, pdSrc2, dSrcLen2, dNum_of_Shift); + } + + for (i = c-dSrcLen2 - 1; i != (cc_u32)-1; i--) + { + if (C[dSrcLen2 + i]==pdSrc2[dSrcLen2 - 1] ) + { + q = (cc_u32)-1; + } + else + { + q = SDRM_DIGIT_Div(C[dSrcLen2 + i], C[dSrcLen2 + i - 1], pdSrc2[dSrcLen2 - 1]); + } + + if (SDRM_DWD_MulSub(C + i, dSrcLen2 + 1, pdSrc2, dSrcLen2, q) ) + { + q--; + if (!SDRM_DWD_Add(C + i, C + i, dSrcLen2 + 1, pdSrc2, dSrcLen2)) + { + q--; + SDRM_DWD_Add(C + i, C + i, dSrcLen2 + 1, pdSrc2, dSrcLen2); + } + } + pdDest[i] = q; + } + + //Recover lowest '0's + if (dNum_of_Shift) + { + SDRM_DWD_SHR(pdSrc2, pdSrc2, dSrcLen2, dNum_of_Shift); + SDRM_DWD_SHR(C, C, dSrcLen2, dNum_of_Shift); + } + + if (pdRem) + { + SDRM_DWD_Copy(pdRem, C, dSrcLen2); + } + + for (i = 0; i < c; i++) + { + if (C[i]) + { + free(C); + + return 1; + } + } + free(C); + + return 0; +} + +/* + * @fn SDRM_DWD_Classical_REDC + * @brief Classical Modular Reduction Algorithm + * + * @param pdDest [out]destination + * @param DstLen [in]length of pdDest + * @param pdModulus [in]modulus + * @param ModLen [in]legnth of pdModulus + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_DWD_Classical_REDC(cc_u32 *pdDest, cc_u32 DstLen, cc_u32 *pdModulus, cc_u32 ModLen) +{ + cc_u32 i; + cc_u32 MSB=0, TTTT=0, FLAG=0, D_Quotient, MSD_Modulus; + + if (DstLen < ModLen) + { + return CRYPTO_SUCCESS; + } + + if (pdDest[DstLen - 1] >= pdModulus[ModLen - 1]) + { + FLAG++; + TTTT = pdDest[DstLen]; + pdDest[DstLen++] = 0; + } + + for (i = SDRM_BitsInDWORD - 1; i != (cc_u32)-1; i--) + { + if (pdModulus[ModLen - 1] & ((cc_u32)1 << i)) + { + break; + } + + MSB++; + } + + if (MSB) + { + SDRM_DWD_SHL(pdModulus, pdModulus, ModLen, MSB); + SDRM_DWD_SHL(pdDest, pdDest, DstLen, MSB); + } + + // Step 2 : main part + MSD_Modulus = pdModulus[ModLen - 1]; + for (i = DstLen - ModLen - 1; i != (cc_u32)-1; i--) + { + // Step 2-1 : Estimate D_Quotient + if (pdDest[ModLen + i] == MSD_Modulus) + { + D_Quotient = (cc_u32)-1; + } + else + { + D_Quotient = SDRM_DIGIT_Div(pdDest[ModLen + i], pdDest[ModLen + i - 1], MSD_Modulus); + } + + // Step 2-2 : Make pdDest <- pdDest-D_Quotient*pdModulus + if (SDRM_DWD_MulSub(pdDest + i, ModLen + 1, pdModulus, ModLen, D_Quotient) ) + { + if (SDRM_DWD_Add(pdDest + i, pdDest + i, ModLen + 1, pdModulus, ModLen) == 0) + { + SDRM_DWD_Add(pdDest + i, pdDest + i, ModLen + 1, pdModulus, ModLen); + } + } + } + + // Step 4 : inverse part of Step 2 + if (MSB) + { + SDRM_DWD_SHR(pdModulus, pdModulus, ModLen, MSB); + SDRM_DWD_SHR(pdDest, pdDest, ModLen, MSB); + } + + // Step 4.5 : inverse part of Step 1.5 + if (FLAG) + { + DstLen--; + pdDest[DstLen] = TTTT; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DIGIT_Gcd + * @brief get gcd of two digits + * + * @param s1 [in]first element + * @param s2 [in]second element + * + * @return gcd + */ +cc_u32 SDRM_DIGIT_Gcd(cc_u32 s1, cc_u32 s2) + { + cc_u32 dTemp; + + if (s1 < s2) + { + dTemp = s1; + s1 = s2; + s2 = dTemp; + } + + while(s2) + { + dTemp = s1 % s2; + s1 = s2; + s2 = dTemp; + } + + return s1; +} + +/* + * @fn SDRM_PrintBN + * @brief Show out a Big Number + * + * @param level [in]log level + * @param s [in]title + * @param bn [in]big number to show out + * + * @return void + */ +void SDRM_PrintBN(const char* s, SDRM_BIG_NUM* bn) +{ + cc_u32 i; + if(bn->sign == 0) { + printf("%15s %d :", s, (int)(bn->Length)); + } + else { + printf("%15s-%d :", s, (int)(bn->Length)); + } + for (i = 0; i < bn->Length ; i++) + { + printf("%08x ", (int)(bn->pData[bn->Length - i -1])); + } + + printf("\n"); + + return; +} + +/* + * @fn SDRM_BN2OS + * @brief Convert Big Number to Octet String + * + * @param BN_Src [in]source integer + * @param dDstLen [in]Byte-length of pbDst + * @param pbDst [out]output octet string + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if arrary is too small + */ +int SDRM_BN2OS(SDRM_BIG_NUM *BN_Src, cc_u32 dDstLen, cc_u8 *pbDst) +{ + cc_u32 i; + + if ((BN_Src == NULL) || (pbDst == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_BN_OPTIMIZE_LENGTH(BN_Src); + + if (BN_Src->sign) + { + pbDst[0] = '-'; + dDstLen += 1; + } + + if ((SDRM_SIZE_OF_DWORD * BN_Src->Length) <= dDstLen) + { + memset(pbDst, 0, dDstLen); + + for (i = 0; (dDstLen != 0) && (i < BN_Src->Length); i++) + { + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i] ) & 0xff); + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i]>> 8) & 0xff); + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i]>>16) & 0xff); + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i]>>24) & 0xff); + } + } + else + { + i = (SDRM_SIZE_OF_DWORD * BN_Src->Length) - dDstLen; + if (i >= SDRM_SIZE_OF_DWORD) + { + return CRYPTO_BUFFER_TOO_SMALL; + } + else if ( BN_Src->pData[BN_Src->Length - 1] >> (8 * (SDRM_SIZE_OF_DWORD - i))) + { + return CRYPTO_BUFFER_TOO_SMALL; + } + + for (i = 0;; i++) + { + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i] ) & 0xff); + if (dDstLen == 0) + { + break; + } + + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i]>> 8) & 0xFF); + if (dDstLen == 0) + { + break; + } + + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i]>>16) & 0xFF); + if (dDstLen == 0) + { + break; + } + + pbDst[--dDstLen] = (cc_u8)((BN_Src->pData[i]>>24) & 0xFF); + if (dDstLen == 0) + { + break; + } + } + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_OS2BN + * @brief Convert Octet String to Big Number + * + * @param pbSrc [in]source octet string + * @param dSrcLen [in]Byte-length of pbSrc + * @param BN_Dst [out]output big number + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if arrary is too small + */ +int SDRM_OS2BN(cc_u8 *pbSrc, cc_u32 dSrcLen, SDRM_BIG_NUM *BN_Dst) +{ + cc_u32 i; + int ret; + + if ((pbSrc == NULL) || (BN_Dst == NULL)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + SDRM_BN_Clr(BN_Dst); + + for (i = 0; i < dSrcLen; i++) + { + ret = SDRM_BN_SHL(BN_Dst, BN_Dst, 8); + + if (ret != CRYPTO_SUCCESS) + { + return ret; + } + + BN_Dst->pData[0] ^= pbSrc[i]; + if (BN_Dst->Length == 0) { + BN_Dst->Length = 1; + } + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_I2OSP + * @brief Converts a nonnonegative integer to an octet string of a specified length + * + * @param BN_Src [in]nonnegative integer to be converted + * @param dDstLen [in]intended length of the resulting octet string + * @param pbDst [out]corresponding octet string of length dDstLen + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_I2OSP(SDRM_BIG_NUM *BN_Src, cc_u32 dDstLen, cc_u8 *pbDst) +{ + int count; + + SDRM_BN_OPTIMIZE_LENGTH(BN_Src); + + count = 0; + for (dDstLen--; (int)dDstLen >= 0; dDstLen--) + { + pbDst[count++] = SDRM_CheckByteUINT32(BN_Src->pData, dDstLen); + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Clr + * @brief Clear the SDRM_BIG_NUM structure + * + * @param BN_Src [in]source + * + * @return CRYPTO_SUCCESS + */ +int SDRM_BN_Clr(SDRM_BIG_NUM* BN_Src) +{ + BN_Src->sign = 0; + BN_Src->Length = 0; + + memset(BN_Src->pData, 0, BN_Src->Size * SDRM_SIZE_OF_DWORD); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Copy + * @brief copy SDRM_BIG_NUM + * + * @param BN_Dest [out]destination + * @param BN_Src [in]source + * + * @return CRYPTO_SUCCESS + */ +int SDRM_BN_Copy(SDRM_BIG_NUM* BN_Dest, SDRM_BIG_NUM* BN_Src) +{ + if (BN_Src->Length > BN_Dest->Size) + { + return CRYPTO_BUFFER_TOO_SMALL; + } + + BN_Dest->sign = BN_Src->sign; + BN_Dest->Length = BN_Src->Length; + + memcpy(BN_Dest->pData, BN_Src->pData, BN_Src->Length * SDRM_SIZE_OF_DWORD); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Alloc + * @brief allocate big number from buffer + * + * @param pbSrc [in]start pointer of buffer + * @param dSize [in]buffer size of big number + * + * @return pointer of SDRM_BIG_NUM structure + */ +SDRM_BIG_NUM *SDRM_BN_Alloc(cc_u8* pbSrc, cc_u32 dSize) +{ + SDRM_BIG_NUM *BN_Dest = (SDRM_BIG_NUM*)(void*)pbSrc; + + if (pbSrc == NULL) + { + return NULL; + } + + memset(BN_Dest, 0, sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD); + BN_Dest->pData = (cc_u32*)(void*)(pbSrc + sizeof(SDRM_BIG_NUM)); + BN_Dest->Size = dSize; + BN_Dest->Length = 0; + + return BN_Dest; +} + +/* + * @fn SDRM_BN_Init + * @brief Allocate a new big number object + * + * @param dSize [in]buffer size of big number + * + * @return pointer of SDRM_BIG_NUM structure + * \n NULL if memory allocation is failed + */ +SDRM_BIG_NUM *SDRM_BN_Init(cc_u32 dSize) +{ + cc_u32 AllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + cc_u8 *pbBuf = (cc_u8*)malloc(AllocSize); + SDRM_BIG_NUM *BN_Src = (SDRM_BIG_NUM*)(void*)pbBuf; + if (BN_Src == NULL) + { + return NULL; + } + + memset(BN_Src, 0, AllocSize); + BN_Src->pData = (cc_u32*)(void*)(pbBuf + sizeof(SDRM_BIG_NUM)); + BN_Src->Size = dSize; + + return BN_Src; +} + +/* + * @fn SDRM_BN_Cmp + * @brief Compare two Big Number + * + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return 1 if BN_Src1 is larger than pdSrc2 + * \n 0 if same + * \n -1 if BN_Src2 is larger than pdSrc1 + */ +int SDRM_BN_Cmp(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) +{ + if (BN_Src1->Length >= BN_Src2->Length) + { + return SDRM_DWD_Cmp(BN_Src1->pData, BN_Src1->Length, BN_Src2->pData, BN_Src2->Length); + } + else + { + return -SDRM_DWD_Cmp(BN_Src2->pData, BN_Src2->Length, BN_Src1->pData, BN_Src1->Length); + } +} + +/* + * @fn SDRM_BN_Cmp_sign + * @brief Compare two Big Number considering sign + * + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return 1 if BN_Src1 is larger than pdSrc2 + * \n 0 if same + * \n -1 if BN_Src2 is larger than pdSrc1 + */ +int SDRM_BN_Cmp_sign(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) +{ + if (BN_Src1->sign > BN_Src2->sign) + { + return -1; + } + else if (BN_Src1->sign < BN_Src2->sign) + { + return 1; + } + + if ( BN_Src1->Length >= BN_Src2->Length ) + { + return SDRM_DWD_Cmp(BN_Src1->pData, BN_Src1->Length, BN_Src2->pData, BN_Src2->Length); + } + else + { + return -SDRM_DWD_Cmp(BN_Src2->pData, BN_Src2->Length, BN_Src1->pData, BN_Src1->Length); + } +} + +/* + * @fn SDRM_BN_Rand + * @brief Generate simple random number + * + * @param BN_Dst [out]destination + * @param BitLen [in]bit-length of generated random number + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_BN_Rand(SDRM_BIG_NUM *BN_Dst, cc_u32 BitLen) +{ + cc_u32 i, j; + + SDRM_BN_Clr(BN_Dst); + + for (i = 0; i < (BitLen / SDRM_BitsInDWORD); i++) + { + BN_Dst->pData[i] = rand() ^ (rand() << 11); + } + + j = BitLen % SDRM_BitsInDWORD; + if (j) + { + BN_Dst->pData[i] = rand() ^ (rand() << 11); + BN_Dst->pData[i] &= (((cc_u32)1) << j) - 1; + i++; + } + + BN_Dst->Length = ((BitLen - 1) / SDRM_BitsInDWORD) + 1; + + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_SHL + * @brief Big Number Shift Left + * + * @param BN_Dst [out]destination + * @param BN_Src [in]source + * @param NumOfShift [in]shift amount + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_BN_SHL(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, cc_u32 NumOfShift) +{ + cc_u32 t; + + if (!BN_Src->Length) + { + SDRM_BN_Copy(BN_Dst, BN_Zero); + return CRYPTO_SUCCESS; + } + + BN_Dst->sign = BN_Src->sign; + + t = NumOfShift % SDRM_BitsInDWORD; + if (t) + { + BN_Dst->Length = BN_Src->Length; + t = SDRM_DWD_SHL(BN_Dst->pData, BN_Src->pData, BN_Src->Length, t); + if (t) + { + BN_Dst->pData[BN_Dst->Length++] = t; + } + } + else + { + SDRM_BN_Copy(BN_Dst, BN_Src); + } + + t = NumOfShift / SDRM_BitsInDWORD; + if (t) + { + BN_Dst->Length += t; + + memmove((BN_Dst->pData) + t, BN_Dst->pData, (BN_Dst->Length - t) * SDRM_SIZE_OF_DWORD); + + memset(BN_Dst->pData, 0, t * SDRM_SIZE_OF_DWORD); + } + + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_SHR + * @brief Big Number Shift Right + * + * @param BN_Dst [out]destination + * @param BN_Src [in]source + * @param NumOfShift [in]shift amount + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_BN_SHR(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, cc_u32 NumOfShift) +{ + cc_u32 t; + + if (!BN_Src->Length) + { + SDRM_BN_Copy(BN_Dst, BN_Src); + return CRYPTO_SUCCESS; + } + + t = NumOfShift / SDRM_BitsInDWORD; + if (t) + { + if (t >= BN_Src->Length) + { + SDRM_BN_Copy(BN_Dst, BN_Zero); + return CRYPTO_SUCCESS; + } + + memcpy(BN_Dst->pData, (BN_Src->pData) + t, (BN_Src->Length - t) * SDRM_SIZE_OF_DWORD); + + BN_Dst->Length = BN_Src->Length - t; + BN_Dst->sign = BN_Src->sign; + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + } + else + { + SDRM_BN_Copy(BN_Dst, BN_Src); + } + + t = NumOfShift % SDRM_BitsInDWORD; + if (t) + { + SDRM_DWD_SHR(BN_Dst->pData, BN_Dst->pData, BN_Dst->Length, t); + } + + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Add + * @brief Big Number Addition + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Add(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) +{ + cc_u32 carry, dSize, dAllocSize; + SDRM_BIG_NUM *temp, *temp_Src1, *temp_Src2; + cc_u8 *pbBuf; + + dSize = MAX2(BN_Src1->Size, BN_Src2->Size); + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + pbBuf = (cc_u8*)malloc(dAllocSize * 2); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + temp_Src1 = SDRM_BN_Alloc(pbBuf, dSize); + temp_Src2 = SDRM_BN_Alloc(pbBuf + dAllocSize, dSize); + + if (!BN_Src1->Length) + { + SDRM_BN_Copy(BN_Dst, BN_Src2); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + if (!BN_Src2->Length) { + SDRM_BN_Copy(BN_Dst, BN_Src1); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + SDRM_BN_Copy(temp_Src1, BN_Src1); + SDRM_BN_Copy(temp_Src2, BN_Src2); + + if (temp_Src1->sign ^ temp_Src2->sign) + { + if (temp_Src1->sign) + { + temp = temp_Src1; + temp_Src1 = temp_Src2; + temp_Src2 = temp; + } + + if (SDRM_BN_Cmp(temp_Src1, temp_Src2) < 0) + { + SDRM_DWD_Sub(BN_Dst->pData, temp_Src2->pData, temp_Src2->Length, temp_Src1->pData, temp_Src1->Length); + BN_Dst->sign = 1; + BN_Dst->Length = temp_Src2->Length; + } + else + { + SDRM_DWD_Sub(BN_Dst->pData, temp_Src1->pData, temp_Src1->Length, temp_Src2->pData, temp_Src2->Length); + BN_Dst->sign = 0; + BN_Dst->Length = temp_Src1->Length; + } + + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + if (temp_Src1->sign) + { + BN_Dst->sign = 1; + } + else + { + BN_Dst->sign = 0; + } + + if (temp_Src1->Length > temp_Src2->Length) + { + BN_Dst->Length = temp_Src1->Length; + carry = SDRM_DWD_Add(BN_Dst->pData, temp_Src1->pData, temp_Src1->Length, temp_Src2->pData, temp_Src2->Length); + if (carry) + { + BN_Dst->pData[BN_Dst->Length++] = carry; + } + } + else + { + BN_Dst->Length = temp_Src2->Length; + carry = SDRM_DWD_Add(BN_Dst->pData, temp_Src2->pData, temp_Src2->Length, temp_Src1->pData, temp_Src1->Length); + if ( carry ) + { + BN_Dst->pData[BN_Dst->Length++] = carry; + } + } + + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Sub + * @brief Big Number Subtraction + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Sub(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) +{ + int i, add = 0, dSize, dAllocSize; + SDRM_BIG_NUM *temp, *temp_Src1, *temp_Src2; + cc_u8 *pbBuf; + + dSize = MAX2(BN_Src1->Size, BN_Src2->Size); + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + pbBuf = (cc_u8*)malloc(dAllocSize * 2); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + temp_Src1 = SDRM_BN_Alloc(pbBuf, dSize); + temp_Src2 = SDRM_BN_Alloc(pbBuf + dAllocSize, dSize); + + SDRM_BN_Copy(temp_Src1, BN_Src1); + SDRM_BN_Copy(temp_Src2, BN_Src2); + + if (BN_Src1 == BN_Src2) + { + SDRM_BN_Clr(BN_Dst); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + //to process sign + if (temp_Src1->sign) + { + if (temp_Src2->sign) + { + temp = temp_Src1; + temp_Src1 = temp_Src2; + temp_Src2 = temp; + } + else + { + add = 1; + temp_Src2->sign = 1; + } + } + else + { + if (temp_Src2->sign) + { + add = 1; + temp_Src2->sign = 0; + } + } + + if (add) + { + i = (temp_Src1->Length | temp_Src2->Length) +1; + if (i) + { + SDRM_BN_Add(BN_Dst, temp_Src1, temp_Src2); + } + else + { + SDRM_BN_Add(BN_Dst, temp_Src2, temp_Src1); + } + + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + if (SDRM_BN_Cmp(temp_Src1, temp_Src2) < 0) + { + SDRM_DWD_Sub(BN_Dst->pData, temp_Src2->pData, temp_Src2->Length, temp_Src1->pData, temp_Src1->Length); + BN_Dst->sign = 1; + BN_Dst->Length = temp_Src2->Length; + } + else + { + SDRM_DWD_Sub(BN_Dst->pData, temp_Src1->pData, temp_Src1->Length, temp_Src2->pData, temp_Src2->Length); + BN_Dst->sign = 0; + BN_Dst->Length = temp_Src1->Length; + } + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Mul + * @brief Big Number Multiplication + * + * @param BN_Dst [out]destination + * @param BN_Multiplicand [in]first element + * @param BN_Multiplier [in]second element + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Mul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Multiplicand, SDRM_BIG_NUM *BN_Multiplier) +{ + SDRM_BIG_NUM *Dst; + + if ((BN_Multiplicand->Length == 0) || (BN_Multiplier->Length == 0)) + { + SDRM_BN_Clr(BN_Dst); + return CRYPTO_SUCCESS; + } + + Dst = SDRM_BN_Init(BN_Dst->Size * 2); + if (Dst == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + Dst->Length = BN_Multiplicand->Length + BN_Multiplier->Length; + + if (BN_Multiplicand->sign != BN_Multiplier->sign) + { + Dst->sign = 1; + } + else + { + Dst->sign = 0; + } + + if (BN_Multiplicand->Length > BN_Multiplier->Length) + { + SDRM_DWD_Mul(Dst->pData, BN_Multiplicand->pData, BN_Multiplicand->Length, BN_Multiplier->pData, BN_Multiplier->Length); + } + else + { + SDRM_DWD_Mul(Dst->pData, BN_Multiplier->pData, BN_Multiplier->Length, BN_Multiplicand->pData, BN_Multiplicand->Length); + } + + SDRM_BN_OPTIMIZE_LENGTH(Dst); + + SDRM_BN_Copy(BN_Dst, Dst); + SDRM_BN_FREE(Dst); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_Div + * @brief Big Number Division + * + * @param BN_Quotient [out]quotient + * @param BN_Remainder [out]remainder + * @param BN_Dividend [in]dividend + * @param BN_Divisor [in]divisor + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_Div(SDRM_BIG_NUM *BN_Quotient, SDRM_BIG_NUM *BN_Remainder, SDRM_BIG_NUM *BN_Dividend, SDRM_BIG_NUM *BN_Divisor) +{ + cc_u32 tmp, dSize, dAllocSize; + SDRM_BIG_NUM *temp_Dividend, *temp_Divisor; + cc_u32 *bnTmp; + cc_u8 *pbBuf; + + if (BN_Quotient != NULL) + { + dSize = MAX2(BN_Quotient->Size, BN_Dividend->Size); + } + else + { + dSize = BN_Dividend->Size; + } + + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + pbBuf = (cc_u8*)malloc(dAllocSize * 3 + 2 * SDRM_SIZE_OF_DWORD); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + temp_Dividend = SDRM_BN_Alloc(pbBuf, dSize); + temp_Divisor = SDRM_BN_Alloc(pbBuf + dAllocSize, dSize); + bnTmp = (cc_u32*)(void*)(pbBuf + dSize + dAllocSize); + + SDRM_BN_Copy(temp_Dividend, BN_Dividend); + SDRM_BN_Copy(temp_Divisor, BN_Divisor); + + if (SDRM_BN_Cmp(temp_Dividend, temp_Divisor) < 0) + { + if (BN_Remainder != NULL) + { + SDRM_BN_Copy(BN_Remainder, temp_Dividend); + //free(pbBuf); + //return CRYPTO_SUCCESS; modify by Chalyi Aleksandr: it is not correct + } + + if (BN_Quotient != NULL) + { + SDRM_BN_Clr(BN_Quotient); + } + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + if (BN_Quotient == NULL) + { + BN_Remainder->Length = temp_Divisor->Length; + tmp = SDRM_DWD_Div(bnTmp, BN_Remainder->pData, temp_Dividend->pData, temp_Dividend->Length, temp_Divisor->pData, temp_Divisor->Length); + SDRM_BN_OPTIMIZE_LENGTH(BN_Remainder); + BN_Remainder->sign = BN_Dividend->sign; + } + else if (BN_Remainder == NULL) + { + BN_Quotient->Length = temp_Dividend->Length - temp_Divisor->Length + 1; + tmp = SDRM_DWD_Div(BN_Quotient->pData, bnTmp, temp_Dividend->pData, temp_Dividend->Length, temp_Divisor->pData, temp_Divisor->Length); + SDRM_BN_OPTIMIZE_LENGTH(BN_Quotient); + BN_Quotient->sign= (BN_Dividend->sign^BN_Divisor->sign); + } + else + { + BN_Quotient->Length = temp_Dividend->Length - temp_Divisor->Length + 1; + BN_Remainder->Length = temp_Divisor->Length; + BN_Quotient->sign= (BN_Dividend->sign^BN_Divisor->sign); + BN_Remainder->sign = BN_Dividend->sign; + + tmp = SDRM_DWD_Div(BN_Quotient->pData, BN_Remainder->pData, BN_Dividend->pData, BN_Dividend->Length, BN_Divisor->pData, BN_Divisor->Length); + + SDRM_BN_OPTIMIZE_LENGTH(BN_Quotient); + SDRM_BN_OPTIMIZE_LENGTH(BN_Remainder); + } + + free(pbBuf); + + if (!(tmp == 0 || tmp == 1)) + { + return CRYPTO_ERROR; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_ModAdd + * @brief Big Number Modular Addition + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element of addition + * @param BN_Src2 [in]second element of addition + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModAdd(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus) +{ + SDRM_BIG_NUM *BN_Src1_temp, *BN_Src2_temp; + cc_u8 *pbBuf; + cc_u32 tmp = 0, dSize, AllocSize; + + dSize = MAX3(BN_Src1->Size, BN_Src2->Size, BN_Modulus->Size); + AllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + pbBuf = (cc_u8*)malloc(AllocSize * 2); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_Src1_temp = SDRM_BN_Alloc(pbBuf, dSize); + BN_Src2_temp = SDRM_BN_Alloc(pbBuf + AllocSize, dSize); + + SDRM_BN_Copy(BN_Src1_temp, BN_Src1); + SDRM_BN_Copy(BN_Src2_temp, BN_Src2); + + if ((SDRM_BN_Cmp(BN_Src1, BN_Modulus)>=0)) + { + SDRM_BN_ModRed(BN_Src1_temp, BN_Src1, BN_Modulus); + } + + if ((SDRM_BN_Cmp(BN_Src2, BN_Modulus)>=0)) + { + SDRM_BN_ModRed(BN_Src2_temp, BN_Src2, BN_Modulus); + } + + if (BN_Src1_temp->Length >= BN_Src2_temp->Length) + { + BN_Dst->Length = BN_Src1_temp->Length; + BN_Dst->sign = BN_Src1_temp->sign; + tmp = SDRM_DWD_Add(BN_Dst->pData, BN_Src1_temp->pData, BN_Src1_temp->Length, BN_Src2_temp->pData, BN_Src2_temp->Length); + } + else + { + BN_Dst->Length = BN_Src2_temp->Length; + BN_Dst->sign = BN_Src2_temp->sign; + tmp = SDRM_DWD_Add(BN_Dst->pData, BN_Src2_temp->pData, BN_Src2_temp->Length, + BN_Src1_temp->pData, BN_Src1_temp->Length); + } + + if (tmp) + { + BN_Dst->pData[BN_Dst->Length++] = tmp; + } + + SDRM_BN_ModRed(BN_Dst, BN_Dst, BN_Modulus); + + if (SDRM_DWD_Cmp(BN_Dst->pData, BN_Dst->Length, BN_Modulus->pData, BN_Modulus->Length) >= 0) + { + SDRM_DWD_Sub(BN_Dst->pData, BN_Dst->pData, BN_Dst->Length, BN_Modulus->pData, BN_Modulus->Length); + } + + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_ModSub + * @brief Big Number Modular Subtraction + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element of subtraction + * @param BN_Src2 [in]second element of subtraction + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModSub(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus) +{ + cc_u32 tmp = 0, dSize, AllocSize; + SDRM_BIG_NUM *BN_Src1_temp, *BN_Src2_temp; + cc_u8 *pbBuf; + + dSize = MAX3(BN_Src1->Size, BN_Src2->Size, BN_Modulus->Size); + AllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + pbBuf = (cc_u8*)malloc(AllocSize * 2); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_Src1_temp = SDRM_BN_Alloc(pbBuf, dSize); + BN_Src2_temp = SDRM_BN_Alloc(pbBuf + AllocSize, dSize); + + SDRM_BN_Copy(BN_Src1_temp, BN_Src1); + SDRM_BN_Copy(BN_Src2_temp, BN_Src2); + + if ((SDRM_BN_Cmp(BN_Src1, BN_Modulus) >= 0)) + { + SDRM_BN_ModRed(BN_Src1_temp, BN_Src1, BN_Modulus); + } + + if ((SDRM_BN_Cmp(BN_Src2, BN_Modulus) >= 0)) + { + SDRM_BN_ModRed(BN_Src2_temp, BN_Src2, BN_Modulus); + } + + if (SDRM_DWD_Cmp(BN_Src1_temp->pData, BN_Src1_temp->Length, BN_Src2_temp->pData, BN_Src2_temp->Length) >= 0) + { + BN_Dst->Length = BN_Src1_temp->Length; + BN_Dst->sign = BN_Src1_temp->sign; + + tmp = SDRM_DWD_Sub(BN_Dst->pData, BN_Src1_temp->pData, BN_Src1_temp->Length, BN_Src2_temp->pData, BN_Src2_temp->Length); + } + else + { + BN_Dst->Length = BN_Modulus->Length; + BN_Dst->sign = BN_Modulus->sign; + SDRM_DWD_Add(BN_Dst->pData, BN_Modulus->pData, BN_Modulus->Length, BN_Src1_temp->pData, BN_Src1_temp->Length); + SDRM_DWD_Sub(BN_Dst->pData, BN_Dst->pData, BN_Dst->Length, BN_Src2_temp->pData, BN_Src2_temp->Length); + } + + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + free(pbBuf); + + if (tmp != 0) + { + return CRYPTO_ERROR; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_ModRed + * @brief Big Number Modular Reduction + * + * @param BN_Dst [out]destination + * @param BN_Src [in]source + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModRed(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src, SDRM_BIG_NUM *BN_Modulus) +{ + int ret; + cc_u32 *Value = (cc_u32*)malloc(SDRM_SIZE_OF_DWORD * 2 * (sizeof(SDRM_BIG_NUM) + MAX2(BN_Src->Size, BN_Modulus->Size) + 2)); + + if (!Value) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if (SDRM_BN_Cmp(BN_Src, BN_Modulus) < 0) + { + SDRM_BN_Copy(BN_Dst, BN_Src); + free(Value); + return CRYPTO_SUCCESS; + } + + memcpy(Value, BN_Src->pData, BN_Src->Length * SDRM_SIZE_OF_DWORD); + + ret = SDRM_DWD_Classical_REDC(Value, BN_Src->Length, BN_Modulus->pData, BN_Modulus->Length); + + if (ret != CRYPTO_SUCCESS) + { + free(Value); + return ret; + } + + memcpy(BN_Dst->pData, Value, BN_Modulus->Length * SDRM_SIZE_OF_DWORD); + + BN_Dst->Length = BN_Modulus->Length; + BN_Dst->sign = BN_Modulus->sign; + SDRM_BN_OPTIMIZE_LENGTH(BN_Dst); + + free(Value); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_ModMul + * @brief Big Number Modular Multiplication + * + * @param BN_Dst [out]destination + * @param BN_Src1 [in]first element of multiplication + * @param BN_Src2 [in]second element of multipliation + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +int SDRM_BN_ModMul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_NUM *BN_Modulus) +{ + int ret; + SDRM_BIG_NUM Dest; + cc_u32 *Value = (cc_u32*)malloc(SDRM_SIZE_OF_DWORD * (MAX3(BN_Src1->Size, BN_Src2->Size, BN_Modulus->Size) + 2)); + + if (!Value) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + memset(Value, 0x00, SDRM_SIZE_OF_DWORD * (MAX3(BN_Src1->Size, BN_Src2->Size, BN_Modulus->Size) + 2)); + + SDRM_DWD_Mul(Value, BN_Src1->pData, BN_Src1->Length, BN_Src2->pData, BN_Src2->Length); + + ret = SDRM_DWD_Classical_REDC(Value, BN_Src1->Length + BN_Src2->Length, BN_Modulus->pData, BN_Modulus->Length); + if (ret != CRYPTO_SUCCESS) + { + free(Value); + + return ret; + } + + Dest.sign = (BN_Src1->sign == BN_Src2->sign)? 0 : 1; + Dest.Length = BN_Modulus->Length; + Dest.pData = Value; + + SDRM_BN_OPTIMIZE_LENGTH(&Dest); + + SDRM_BN_Copy(BN_Dst, &Dest); + + free(Value); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_ModInv + * @brief Big Number Modular Inverse + * + * @param BN_Dest [out]destination + * @param BN_Src [in]soure + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + * \n CRYPTO_NEGATIVE_INPUT if source is negative value + * \n CRYPTO_INVERSE_NOT_EXIST if inverse is not exists + */ +int SDRM_BN_ModInv(SDRM_BIG_NUM *BN_Dest, SDRM_BIG_NUM *BN_Src, SDRM_BIG_NUM *BN_Modulus) +{ + SDRM_BIG_NUM *BN_G0, *BN_G1, *BN_V0, *BN_V1, *BN_Y, *BN_Temp1, *BN_Temp2; + cc_u8 *pbBuf = NULL; + cc_u32 dSize, dAllocSize; + + dSize = MAX2(BN_Src->Size, BN_Modulus->Size); + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + pbBuf = (cc_u8*)malloc(dAllocSize * 7); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_G0 = SDRM_BN_Alloc(pbBuf, dSize); + BN_G1 = SDRM_BN_Alloc((cc_u8*)BN_G0 + dAllocSize, dSize); + BN_V0 = SDRM_BN_Alloc((cc_u8*)BN_G1 + dAllocSize, dSize); + BN_V1 = SDRM_BN_Alloc((cc_u8*)BN_V0 + dAllocSize, dSize); + BN_Y = SDRM_BN_Alloc((cc_u8*)BN_V1 + dAllocSize, dSize); + BN_Temp1 = SDRM_BN_Alloc((cc_u8*)BN_Y + dAllocSize, dSize); + BN_Temp2 = SDRM_BN_Alloc((cc_u8*)BN_Temp1 + dAllocSize, dSize); + + if (BN_Src->sign) + { + free(pbBuf); + return CRYPTO_NEGATIVE_INPUT; + } + + //Extended Euclid Algorithm + SDRM_BN_Copy(BN_G0, BN_Modulus); + SDRM_BN_ModRed(BN_G1, BN_Src, BN_Modulus); + + SDRM_BN_Copy(BN_V0, BN_Zero); + SDRM_BN_Copy(BN_V1, BN_One); + + SDRM_BN_Clr(BN_Y); + SDRM_BN_Clr(BN_Dest); + + while(SDRM_BN_Cmp(BN_G1, BN_Zero)) + { + if (!SDRM_BN_Cmp(BN_G1, BN_One)) + { + SDRM_BN_Copy(BN_Dest, BN_V1); + SDRM_BN_OPTIMIZE_LENGTH(BN_Dest); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + SDRM_BN_Clr(BN_Y); + SDRM_BN_Clr(BN_Temp1); + SDRM_DWD_Div(BN_Y->pData, BN_Temp1->pData, BN_G0->pData, BN_G0->Length, BN_G1->pData, BN_G1->Length); + + BN_Y->Length = BN_G0->Length; + SDRM_BN_OPTIMIZE_LENGTH(BN_Y); + + BN_Temp1->Length = BN_G1->Length; + SDRM_BN_Copy(BN_G0, BN_Temp1); + SDRM_BN_OPTIMIZE_LENGTH(BN_G0); + + SDRM_BN_Clr(BN_Temp1); + SDRM_DWD_Mul(BN_Temp1->pData, BN_Y->pData, BN_Y->Length, BN_V1->pData, BN_V1->Length); + BN_Temp1->Length = BN_Y->Length + BN_V1->Length; + SDRM_BN_OPTIMIZE_LENGTH(BN_Temp1); + + SDRM_BN_Clr(BN_Temp2); + if (SDRM_BN_Cmp(BN_V0, BN_Temp1) >= 0) + { + SDRM_BN_Add(BN_Temp2, BN_V0, BN_Temp1); + } + else + { + SDRM_BN_Add(BN_Temp2, BN_Temp1, BN_V0); + } + + SDRM_BN_Copy(BN_V0, BN_Temp2); + + if (!SDRM_BN_Cmp(BN_G0, BN_Zero)) + { + break; + } + + if (!SDRM_BN_Cmp(BN_G0, BN_One)) + { + SDRM_BN_Sub(BN_Dest, BN_Modulus, BN_V0); + SDRM_BN_OPTIMIZE_LENGTH(BN_Dest); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + SDRM_BN_Clr(BN_Y); + SDRM_BN_Clr(BN_Temp1); + SDRM_DWD_Div(BN_Y->pData, BN_Temp1->pData, BN_G1->pData, BN_G1->Length, BN_G0->pData, BN_G0->Length); + + BN_Y->Length = BN_G1->Length; + SDRM_BN_OPTIMIZE_LENGTH(BN_Y); + + BN_Temp1->Length = BN_G0->Length; + SDRM_BN_Copy(BN_G1, BN_Temp1); + SDRM_BN_OPTIMIZE_LENGTH(BN_G1); + + SDRM_BN_Clr(BN_Temp1); + SDRM_DWD_Mul(BN_Temp1->pData, BN_Y->pData, BN_Y->Length, BN_V0->pData, BN_V0->Length); + BN_Temp1->Length = BN_Y->Length + BN_V0->Length; + SDRM_BN_OPTIMIZE_LENGTH(BN_Temp1); + + SDRM_BN_Clr(BN_Temp2); + if (SDRM_BN_Cmp(BN_V1, BN_Temp1) >= 0) + { + SDRM_BN_Add(BN_Temp2, BN_V1, BN_Temp1); + } + else + { + SDRM_BN_Add(BN_Temp2, BN_Temp1, BN_V1); + } + + SDRM_BN_Copy(BN_V1, BN_Temp2); + } + + SDRM_BN_Copy(BN_Dest, BN_Zero); + free(pbBuf); + + return CRYPTO_INVERSE_NOT_EXIST; +} + +/* + * @fn SDRM_MONT_Rzn2zn + * @brief Convert Montgomery number to noraml number + * + * @param BN_Dst [out]destination, normal number + * @param BN_Src1 [in]source, montgomery number + * @param Mont [in]montgomery parameters + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_MONT_Rzn2zn(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_MONT *Mont) +{ + cc_u32 Src1_Len, Mod_Len, ri, i; + cc_u32 carry; + SDRM_BIG_NUM *Src1 = NULL; + + if (!BN_Src1->Length) + { + BN_Dst->Length = 0; + + return CRYPTO_SUCCESS; + } + + Src1_Len = ri = Mont->ri / SDRM_BitsInDWORD; + Mod_Len = Mont->Mod->Length + 1; + + Src1 = SDRM_BN_Init(BN_Src1->Size + Mod_Len); + if(Src1 == NULL)//fixed prevent cid=89093 by guoxing.xu + { + return CRYPTO_ERROR; + } + SDRM_BN_Copy(Src1, BN_Src1); + + if (!Src1_Len || !Mod_Len) + { + BN_Dst->Length = 0; + BN_Dst->pData[0] = 0; + SDRM_BN_FREE(Src1); + + return CRYPTO_SUCCESS; + } + + Src1->sign = BN_Src1->sign ^ Mont->Mod->sign; + + memset(Src1->pData + Src1->Length, 0, (Mod_Len + BN_Src1->Length - Src1->Length) * SDRM_SIZE_OF_DWORD); + + Src1->Length = Mod_Len + BN_Src1->Length; + + for (i = 0; i < Mod_Len; i++) + { + if ((carry = SDRM_DWD_MulAdd(Src1->pData + i, Src1->Length - i, Mont->Mod->pData, Mod_Len, (cc_u32)Src1->pData[i] * Mont->N0))) + { + Src1->pData[Src1->Length++] = carry; //Added by Park Ji soon, 05-03-2006 + } // (cc_u32)A.pData[i]*modulus_p <== u=a[i]*m' mod b + // A=A+ (A.pData[i]*modulus_p* modulus[i])*b^i; + } + SDRM_BN_OPTIMIZE_LENGTH(Src1); + + SDRM_BN_SHR(BN_Dst, Src1, (Mod_Len) * 32); + //BN_Dst->Length = Src1->Length - ri; + BN_Dst->Length = Src1->Length - ri- 1;//Added by yhhwang + + //if (SDRM_BN_Cmp(BN_Dst, Mont->Mod) >= 0) + while (SDRM_BN_Cmp(BN_Dst, Mont->Mod) >= 0) + { + SDRM_BN_Sub(BN_Dst, BN_Dst, Mont->Mod); + } + + SDRM_BN_FREE(Src1); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_MONT_Mul + * @brief Montgomery Multiplication + * + * @param BN_Dst [out]destination, montgomery number + * @param BN_Src1 [in]first element, montgomery number + * @param BN_Src2 [in]second element, montgomery number + * @param Mont [in]montgomery parameters + * + * @return CRYPTO_SUCCESS if no error occured + */ +int SDRM_MONT_Mul(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2, SDRM_BIG_MONT *Mont) +{ + int ret; + + /* Begin - Add to test input range by Yong Ho Hwang (20120809) */ + /* + if (SDRM_BN_Cmp(BN_Src1, Mont->Mod) >= 0) + { + ret = SDRM_BN_ModRed(BN_Src1, BN_Src1, Mont->Mod); + if (ret != CRYPTO_SUCCESS) + { + return ret; + } + } else if ( BN_Src1->sign == 1) + { + printf("Minus Value\n"); + ret = SDRM_BN_Add(BN_Src1, BN_Src1, Mont->Mod); + if (BN_Src1->sign == 1) + { + printf("Value Fail.\n"); + return CRYPTO_ERROR; + } + } + + if (SDRM_BN_Cmp(BN_Src2, Mont->Mod) >= 0) + { + ret = SDRM_BN_ModRed(BN_Src2, BN_Src2, Mont->Mod); + if (ret != CRYPTO_SUCCESS) + { + return ret; + } + } else if ( BN_Src2->sign == 1) + { + printf("Minus Value\n"); + ret = SDRM_BN_Add(BN_Src2, BN_Src2, Mont->Mod); + if (BN_Src2->sign == 1) + { + printf("Value Fail.\n"); + return CRYPTO_ERROR; + } + } + */ + /* End - Add to test input range by Yong Ho Hwang (20120809) */ + + ret = SDRM_BN_Mul(BN_Dst, BN_Src1, BN_Src2); + if (ret != CRYPTO_SUCCESS) + { + return ret; + } + + ret = SDRM_MONT_Rzn2zn(BN_Dst, BN_Dst, Mont); + + /* Begin - Add to test input range by Yong Ho Hwang (20120809) */ + /* + if (SDRM_BN_Cmp(BN_Dst, Mont->Mod) >= 0) + { + printf("Output is bigger than Mod\n"); + } else if ( BN_Dst->sign == 1) + { + printf("Minus Value\n"); + } + */ + /* End - Add to test input range by Yong Ho Hwang (20120809) */ + + return ret; +} + +/* + * @fn SDRM_MONT_Set + * @brief Set Montgomery parameters + * + * @param Mont [out]montgomery parameter + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n BN_NOT_ENOUGHT_BUFFER if malloc is failed + * \n CRYPTO_INVERSE_NOT_EXIST if inverse is not exists + */ +int SDRM_MONT_Set(SDRM_BIG_MONT *Mont, SDRM_BIG_NUM *BN_Modulus) +{ + SDRM_BIG_NUM *Ri, *R; + SDRM_BIG_NUM *temp, *Rsquare; + cc_u8 *pbBuf; + cc_u32 buf[2], dSize, dAllocSize, r2Size; + + if ((Mont == NULL) || (BN_Modulus == NULL)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (Mont->R == NULL) + { + Mont->R = SDRM_BN_Init(BN_Modulus->Size); + } + if (Mont->R == NULL)//fix prevent 89095 by guoxing.xu + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + if (Mont->Mod == NULL) + { + Mont->Mod = SDRM_BN_Init(BN_Modulus->Size); + } + if (Mont->Mod == NULL)//fix prevent 89-95 by guoxing.xu + { + SDRM_BN_FREE(Mont->R); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + if (SDRM_BN_Cmp(Mont->Mod, BN_Modulus) == 0) + { + return CRYPTO_SUCCESS; + } + + dSize = BN_Modulus->Size + 1; + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + if (!(pbBuf = (cc_u8*)malloc(dAllocSize * 3))) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + Ri = SDRM_BN_Alloc( pbBuf, dSize); + R = SDRM_BN_Alloc((cc_u8*)Ri + dAllocSize, dSize); + temp = SDRM_BN_Alloc((cc_u8*)R + dAllocSize, dSize); + +//++ 2012.08.20 - modified by yhhwang to apply R=2^(160+32) +/* == DELETED == + SDRM_BN_Copy(Mont->Mod, BN_Modulus); + + Mont->ri = (SDRM_BN_num_bits(BN_Modulus) + (SDRM_BitsInDWORD - 1)) / SDRM_BitsInDWORD * SDRM_BitsInDWORD; + + SDRM_BN_SHL(R, BN_One, SDRM_BitsInDWORD); + + buf[0] = BN_Modulus->pData[0]; + buf[1] = 0; + temp->pData[0] = buf[0]; + temp->Length = 1; + temp->sign = BN_Modulus->sign; + + SDRM_BN_ModInv(Ri, R, temp); + if (Ri == NULL) + { + free(pbBuf); + + return CRYPTO_INVERSE_NOT_EXIST; + } + + SDRM_BN_SHL(Ri, Ri, SDRM_BitsInDWORD); + SDRM_BN_Sub(Ri, Ri, BN_One); + SDRM_BN_Div(Ri, NULL, Ri, temp); + SDRM_BN_Copy(Mont->Inv_Mod, Ri); + Mont->N0 = Ri->pData[0]; + + SDRM_BN_SHL(Mont->R, BN_One, 2 * (32 + Mont->ri)); + SDRM_BN_ModRed(Mont->R, Mont->R, Mont->Mod); +*/ + +// == NEW CODE == + SDRM_BN_Copy(Mont->Mod, BN_Modulus); + Mont->Mod->pData[Mont->Mod->Length] = 0; + + Mont->ri = (SDRM_BN_num_bits(BN_Modulus) + (SDRM_BitsInDWORD - 1)) / SDRM_BitsInDWORD * SDRM_BitsInDWORD; + + SDRM_BN_SHL(R, BN_One, SDRM_BitsInDWORD); + + // Compute -m^-1 mod b + buf[0] = BN_Modulus->pData[0]; + buf[1] = 0; + temp->pData[0] = buf[0]; + temp->Length = 1; + temp->sign = BN_Modulus->sign; + + SDRM_BN_ModInv(Ri, temp, R); + Ri->sign = 1; + SDRM_BN_Add(Ri, Ri, R); + Mont->N0 = Ri->pData[0]; + + r2Size = 2 * (SDRM_BitsInDWORD + Mont->ri); + Rsquare = SDRM_BN_Init(r2Size / SDRM_BitsInDWORD + 1); + if (Rsquare == NULL) + { + free(pbBuf); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + // Compute R and R^2 mod M + SDRM_BN_SHL(Rsquare, BN_One, r2Size); + SDRM_BN_ModRed(Mont->R, Rsquare, BN_Modulus); +//-- 2012.08.20 - modified by yhhwang + + free(pbBuf); + free(Rsquare); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_MONT_Init + * @brief Allocate new momory for Montgomery parameter + * + * @param dSize [in]size of buffer of big number + * + * @return Pointer to created structure + * \n NULL if malloc failed + */ +SDRM_BIG_MONT *SDRM_MONT_Init(cc_u32 dSize) +{ + SDRM_BIG_MONT *Mont; + cc_u32 AllocSiz = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + Mont = (SDRM_BIG_MONT *)malloc(sizeof(SDRM_BIG_MONT) + AllocSiz * 3); + if (Mont == NULL) + { + return NULL; + } + + Mont->ri = 0; + Mont->R = SDRM_BN_Alloc((cc_u8*)Mont + sizeof(SDRM_BIG_MONT), dSize); + Mont->Mod = SDRM_BN_Alloc((cc_u8*)Mont->R + AllocSiz, dSize); + Mont->Inv_Mod = SDRM_BN_Alloc((cc_u8*)Mont->Mod + AllocSiz, dSize); + + return Mont; +} + +/* + * @fn SDRM_MONT_Free + * @brief Free allocated memory for montgomery paramter + * + * @param Mont [in]montgomery parameters + * + * @return void + */ +void SDRM_MONT_Free(SDRM_BIG_MONT *Mont) +{ + if (Mont != NULL) { + free(Mont); + } +} + +int SDRM_BN_num_bits_index(SDRM_BIG_NUM *BN_Src, cc_u32 bitIndex) +{ + cc_u32 l; + int j; + + if (BN_Src->Length == 0) + { + return 0; + } + + int div = bitIndex / (sizeof(cc_u32) * 8); + int rem = bitIndex % (sizeof(cc_u32) * 8); + + l = BN_Src->pData[div]; + j = SDRM_UINT32_num_bits_index(&l, rem); + return j; +} + +int SDRM_UINT32_num_bits_index(cc_u32 *pdSrc, cc_u32 bitIndex) +{ + cc_u32 i = 0; + cc_u32 temp; + + temp = *pdSrc; + + if (!temp) + { + return 0; + } + + while(temp) + { + if(bitIndex == i) { + break; + } + temp >>= 1; + i++; + } + return temp & 0x00000001; +} + + + +/* + * @fn SDRM_BN_num_bits + * @brief Calc bit-length of Big Number + * + * @param BN_Src [in]source + * + * @return bit-length + */ +int SDRM_BN_num_bits(SDRM_BIG_NUM *BN_Src) +{ + cc_u32 l; + int i, j; + + if (BN_Src->Length == 0) + { + return 0; + } + + l = BN_Src->pData[BN_Src->Length - 1]; + i = (BN_Src->Length-1) * SDRM_BitsInDWORD; + + j = SDRM_UINT32_num_bits(&l); + + return(i + j); +} + +/* + * @fn SDRM_UINT32_num_bits + * @brief Calc bit-length of cc_u32 + * + * @param pdSrc [in]source + * + * @return bit-length + */ +int SDRM_UINT32_num_bits(cc_u32 *pdSrc) +{ + int i = 0; + cc_u32 temp; + + temp = *pdSrc; + + if (!temp) + { + return 0; + } + + while(temp) + { + temp >>= 1; + i++; + } + + return i; +} + +/* + * @fn SDRM_INT_num_bits + * @brief Calc bit-length of integer + * + * @param Src [in]source + * + * @return bit-length + */ +int SDRM_INT_num_bits(int Src) +{ + int i = 0; + + if (!Src) + { + return 0; + } + + while(Src) + { + Src >>= 1; + i++; + } + + return i; +} + +/* + * @fn SDRM_BN_ModExp + * @brief Big Number Modular Exponentiation + * + * @param BN_Dst [out]destination + * @param BN_Base [in]base + * @param BN_Exponent [in]exponent + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_BN_ModExp(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Base, SDRM_BIG_NUM *BN_Exponent, SDRM_BIG_NUM *BN_Modulus) +{ + SDRM_BIG_NUM *c_, *a_, *BN_Temp; + SDRM_BIG_MONT *Mont; + int i, m; + cc_u8 *pbBuf; + cc_u32 dSize, dAllocSize; + + dSize = MAX3(BN_Base->Size, BN_Exponent->Size, BN_Modulus->Size); + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + pbBuf = (cc_u8*)malloc(dAllocSize * 3); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + c_ = SDRM_BN_Alloc(pbBuf, dSize); + a_ = SDRM_BN_Alloc((cc_u8*)c_ + dAllocSize, dSize); + BN_Temp = SDRM_BN_Alloc((cc_u8*)a_ + dAllocSize, dSize); + + if (SDRM_BN_Cmp(BN_Base, BN_Modulus) >= 0) + { + SDRM_BN_ModRed(BN_Temp, BN_Base, BN_Modulus); + } + else + { + BN_Temp = BN_Base; + } + + if (SDRM_BN_Cmp(BN_Temp, BN_Zero) == 0) + { + SDRM_BN_Copy(BN_Dst, BN_Zero); + + free(pbBuf); + return CRYPTO_SUCCESS; + } + + Mont = SDRM_MONT_Init(dSize); + SDRM_MONT_Set(Mont, BN_Modulus); + + SDRM_MONT_Zn2rzn(a_, BN_Temp, Mont); + SDRM_MONT_Zn2rzn(c_, BN_One, Mont); + + m = SDRM_BN_num_bits(BN_Exponent); + + for (i = m - 1; i >= 0; i--) + { + SDRM_MONT_Mul(c_, c_, c_, Mont); + + if (SDRM_CheckBitUINT32(BN_Exponent->pData, i) == 1) + { + SDRM_MONT_Mul(c_, c_, a_, Mont); + } + } + + SDRM_MONT_Rzn2zn(BN_Dst, c_, Mont); + + SDRM_MONT_Free(Mont); + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_ModExp2 + * @brief Big Number Modular Exponentiation2 - Karen's method + * + * @param BN_Dst [out]destination + * @param BN_Base [in]base + * @param BN_Exponent [in]exponent + * @param BN_Modulus [in]modular m + * + * @return CRYPTO_SUCCESS if no error occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_BN_ModExp2(SDRM_BIG_NUM *BN_Dst, SDRM_BIG_NUM *BN_Base, SDRM_BIG_NUM *BN_Exponent, SDRM_BIG_NUM *BN_Modulus) +{ + int retVal; + SDRM_BIG_NUM *BN_Temp; + + if ((BN_Dst != BN_Base) && (BN_Dst != BN_Exponent) && (BN_Dst != BN_Modulus)) + { + SDRM_BN_Clr(BN_Dst); + } + + if (SDRM_BN_Cmp(BN_Base, BN_Modulus) >= 0) + { + BN_Temp = SDRM_BN_Init(MAX3(BN_Base->Size, BN_Exponent->Size, BN_Modulus->Size)); + if (BN_Temp == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if (BN_Temp == BN_Base) + { + free(BN_Temp); + return CRYPTO_ERROR; + } + + SDRM_BN_ModRed(BN_Temp, BN_Base, BN_Modulus); + } + else + { + BN_Temp = BN_Base; + } + + if (SDRM_BN_Cmp(BN_Temp, BN_Zero) == 0) + { + SDRM_BN_Clr(BN_Dst); + + if (BN_Temp != BN_Base) + { + free(BN_Temp); + } + + return CRYPTO_SUCCESS; + } + + retVal = SDRM_ll_ExpMod(BN_Temp->pData, BN_Temp->Length * 4, BN_Exponent->pData, BN_Exponent->Length * 4, BN_Modulus->pData, BN_Modulus->Length * 4, BN_Dst->pData); + if (retVal != CRYPTO_SUCCESS) + { + if (BN_Temp != BN_Base) + { + free(BN_Temp); + } + + return retVal; + } + + BN_Dst->Length = BN_Dst->Size; + + while(BN_Dst->pData[BN_Dst->Length - 1] == 0) + { + BN_Dst->Length--; + } + + if (BN_Temp != BN_Base) + { + free(BN_Temp); + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_BN_CheckRelativelyPrime + * @brief get gcd of two big number + * + * @param BN_Src1 [in]first element + * @param BN_Src2 [in]second element + * + * @return CRYPTO_ISPRIME if two elements are relatively prime + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR otherwise + */ +int SDRM_BN_CheckRelativelyPrime(SDRM_BIG_NUM *BN_Src1, SDRM_BIG_NUM *BN_Src2) +{ + SDRM_BIG_NUM *Temp, *S1, *S2; + cc_u8 *pbBuf; + cc_u32 dSize, dAllocSize; + + dSize = MAX2(BN_Src1->Size, BN_Src2->Size); + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + if (!(pbBuf = (cc_u8*)malloc(dAllocSize * 3))) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + S1 = SDRM_BN_Alloc(pbBuf, dSize); + S2 = SDRM_BN_Alloc((cc_u8*)S1 + dAllocSize, dSize); + Temp = SDRM_BN_Alloc((cc_u8*)S2 + dAllocSize, dSize); + + if (SDRM_BN_Cmp(BN_Src1, BN_Src2) >= 0) + { + SDRM_BN_Copy(S1, BN_Src1); + SDRM_BN_Copy(S2, BN_Src2); + } + else + { + SDRM_BN_Copy(S1, BN_Src2); + SDRM_BN_Copy(S2, BN_Src1); + } + + SDRM_BN_OPTIMIZE_LENGTH(S1); + SDRM_BN_OPTIMIZE_LENGTH(S2); + + while(S2->Length) + { + SDRM_BN_ModRed(Temp, S1, S2); + SDRM_BN_Copy(S1, S2); + SDRM_BN_Copy(S2, Temp); + } + + if (SDRM_BN_Cmp(S1, BN_One) == 0) + { + free(pbBuf); + + return CRYPTO_ISPRIME; + } + + free(pbBuf); + + return CRYPTO_ERROR; +} + +//small primes for pre-testing +static cc_u32 miniPrimes[] = { + 0xC8E15F2A, 0x16FA4227, 0x87B81DA9, 0xDA38C071, 0xFDB17C23, 0xFE5E796B, + 0xC7E4CBF5, 0x7EB0F0B1, 0xB72EFC93, 0xF46CEE57, 0x80B2C2BB, 0x34A77199, + 0x447D1BD5, 0xEA4C7C31, 0xF046D45B, 0xFF55A7BF, 0x9B287041, 0x85663BEF, + 0x7856625B, 0 +}; + +/* + * @fn SDRM_BN_MILLER_RABIN + * @brief MILLER_RABIN Test + * + * @param n [in]value to test + * @param t [in]security parameter + * + * @return CRYPTO_ISPRIME if n is (probably) prime + * \n CRYPTO_INVALID_ARGUMENT if n is composite + */ +int SDRM_BN_MILLER_RABIN(SDRM_BIG_NUM* n, cc_u32 t) +{ + SDRM_BIG_NUM *r, *a, *y, *n1; + cc_u32 i, j, tmp, srcLen, s = 1; + cc_u8 *pbBuf; + cc_u32 dSize, dAllocSize; + + dSize = n->Size; + dAllocSize = sizeof(SDRM_BIG_NUM) + dSize * SDRM_SIZE_OF_DWORD; + + if (n->Length == 0) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if ((n->pData[0] & 0x01) == 0) + { + return CRYPTO_INVALID_ARGUMENT; + } + + for (i = 0; miniPrimes[i] != 0; i++) + { + tmp = 0; + for (j = n->Length - 1; j != (cc_u32)-1; j--) + { + tmp = SDRM_DIGIT_Mod(tmp, n->pData[j], miniPrimes[i]); + } + + if(SDRM_DIGIT_Gcd(miniPrimes[i], tmp) != 1) + { + return CRYPTO_INVALID_ARGUMENT; + } + } + + while(SDRM_CheckBitUINT32(n->pData, s) == 0) { + s++; + } + + pbBuf = (cc_u8*)malloc(dAllocSize * 4); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + r = SDRM_BN_Alloc( pbBuf, dSize); + a = SDRM_BN_Alloc((cc_u8*)r + dAllocSize, dSize); + y = SDRM_BN_Alloc((cc_u8*)a + dAllocSize, dSize); + n1 = SDRM_BN_Alloc((cc_u8*)y + dAllocSize, dSize); + + SDRM_BN_Sub(n1, n, BN_One); + SDRM_BN_SHR(r, n1, s); + + srcLen = SDRM_BN_num_bits(n); + + for (i = 1; i <= t; i++) + { + SDRM_BN_Rand(a, srcLen); + a->pData[n->Length - 1] %= n->pData[n->Length - 1]; + + SDRM_BN_ModExp(y, a, r, n); + if ((SDRM_BN_Cmp(y, BN_One) == 0) || (SDRM_BN_Cmp(y, n1) == 0)) + { + continue; + } + + for (j = 1; (j < s) && SDRM_BN_Cmp(y, n1) != 0; j++) + { + SDRM_BN_ModMul(y, y, y, n); + + if (SDRM_BN_Cmp(y, BN_One) == 0) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + } + + if (SDRM_BN_Cmp(y, n1) != 0) + { + free(pbBuf); + + return CRYPTO_INVALID_ARGUMENT; + } + + } + free(pbBuf); + + return CRYPTO_ISPRIME; +} + +/* + * @fn int SDRM_HEX2BN(cc_u8* pbSrc, SDRM_BIG_NUM *BN_Dst) + * @brief Convert Hex String to Big Number + * + * @param pbSrc [in]source hex string + * @param BN_Dst [out]output big number + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if arrary is too small + */ +int SDRM_HEX2BN(cc_u8* pbSrc, SDRM_BIG_NUM *BN_Dst) +{ + cc_u32 i, n, k, j; + cc_u8 * bufferHex = NULL; + + if (!BN_Dst) + { + BN_Dst = SDRM_BN_Init(BN_Dst->Length * SDRM_SIZE_OF_DWORD * 8); + if(BN_Dst == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + } + if(pbSrc[0] == '-') + { + BN_Dst->sign = 1; + pbSrc[0] = '0'; + } + + BN_Dst->Length = 0; + n = strlen((const char*)pbSrc); + + BN_Dst->Length = n / SDRM_SIZE_BLOCK; + //normalize length + if( n % SDRM_SIZE_BLOCK != 0 ) { + BN_Dst->Length+=1; + } +#if 0 //fix prevent problem by guoxing.xu 20140826. move to before + if (!BN_Dst) + { + BN_Dst = SDRM_BN_Init(BN_Dst->Length * SDRM_SIZE_OF_DWORD * 8); + } +#endif + for(i = 0; i < BN_Dst->Length ; i++) + { + BN_Dst->pData[i] = 0; + } + + //full string: bufferHex mod Length = 0 + bufferHex = (cc_u8 *)malloc( sizeof(cc_u8) * (BN_Dst->Length * SDRM_SIZE_BLOCK)); + + //init byffer by 0 + for(i = 0; i < BN_Dst->Length * SDRM_SIZE_BLOCK; i++) + { + bufferHex[i] = '0'; + } + + + k = n - 1; + for(i = (BN_Dst->Length * SDRM_SIZE_BLOCK) - 1; (int)k >= 0; i--, k--) + { + bufferHex[i] = pbSrc[k]; + } + + for(i = 0; i < BN_Dst->Length; i++) + { + for(j = (BN_Dst->Length * SDRM_SIZE_BLOCK) - (i * SDRM_SIZE_BLOCK) - SDRM_SIZE_BLOCK; j < (BN_Dst->Length * SDRM_SIZE_BLOCK) - (i * SDRM_SIZE_BLOCK) ; j++) + { + switch(bufferHex[j]) + { + case '0': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x0; + break; + case '1': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x1; + break; + case '2': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x2; + break; + case '3': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x3; + break; + case '4': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x4; + break; + case '5': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x5; + break; + case '6': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x6; + break; + case '7': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x7; + break; + case '8': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x8; + break; + case '9': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0x9; + break; + case 'a': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xa; + break; + case 'A': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xa; + break; + case 'b': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xb; + break; + case 'B': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xb; + break; + case 'c': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xc; + break; + case 'C': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xc; + break; + case 'd': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xd; + break; + case 'D': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xd; + break; + case 'e': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xe; + break; + case 'E': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xe; + break; + case 'f': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xf; + break; + case 'F': + BN_Dst->pData[i] = BN_Dst->pData[i] << 4; + BN_Dst->pData[i] |= 0xf; + break; + default: + return CRYPTO_INVALID_ARGUMENT; + } + } + } + + //clear time buffer + free(bufferHex); + + return CRYPTO_SUCCESS; +} + +/* + * @fn cc_u8 * SDRM_BN2STRBIN(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src); + * @brief Convert Big Number to binary String + * + * @param pbSrc [in]source big number + * @param BN_Dst [out]output numberBits of uot string + * + * @return (cc_u8 *) binary string + */ +cc_u8 * SDRM_BN2STRBIN(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src) +{ + cc_u32 i,j,k; + cc_u32 mask = 0x80000000; + cc_u32 temp, check; + cc_u8 *tempC, *tempR; + (*numberBits) = sizeof(cc_u8) * BN_Src->Length * SDRM_SIZE_OF_DWORD * 8 + 1; + tempC = (cc_u8*)malloc(*numberBits); + tempR = (cc_u8*)malloc(*numberBits); + tempC[(*numberBits) - 1] = '\0'; + for(i = BN_Src->Length - 1; (int)i >= 0 ; i--) + { + temp = BN_Src->pData[i]; + for(j = 0; j < (SDRM_SIZE_OF_DWORD * 8); j++) + { + if((temp & mask) > 0) { + tempC[(((BN_Src->Length - 1) - i) * (SDRM_SIZE_OF_DWORD * 8)) + j] = '1'; + } + else { + tempC[(((BN_Src->Length - 1) - i) * (SDRM_SIZE_OF_DWORD * 8)) + j] = '0'; + } + + temp = temp << 1; + } + } + + //next block for normalize length string (eg 0111 = 111) + check = 0; k = 0; + for(i = 0; i < (*numberBits); i++) + { + if(tempC[i] == '0' && check == 0) { + continue; + } + else { + check = 1; + } + + tempR[k] = tempC[i]; + k++; + + } + tempR[k] = '\0'; + (*numberBits) = k - 1; + + free(tempC); + + return tempR; +} + +/* + * @fn int SDRM_BN_SetWord(SDRM_BIG_NUM *BN_Dst, cc_u32 t); + * @brief Set word to Big Number + * + * @param pbSrc [in]source word + * @param BN_Dst [out]output Big Nubmer + * + * @return CRYPTO_SUCCESS if no error is occuredg + */ +int SDRM_BN_SetWord(SDRM_BIG_NUM *BN_Dst, cc_u32 t) +{ + if((int)t >= 0) + { + BN_Dst->Length = 1; + BN_Dst->sign = 0; + BN_Dst->pData[0] = t; + } + else + { + BN_Dst->Length = 1; + BN_Dst->sign = 1; + BN_Dst->pData[0] = t * (-1); + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_BN_isZero(SDRM_BIG_NUM *BN_Src); + * @brief check big number is zero + * + * @param pbSrc [in]source big number + * + * @return 0 - false, 1 - true + */ +int SDRM_BN_isZero(SDRM_BIG_NUM *BN_Src) +{ + return ((BN_Src)->Length == 0)?1:0; +} + +/* + * @fn cc_u8 * SDRM_BN2STRFOUR(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src); + * @brief Convert Big Number to four String + * + * @param pbSrc [in]source big number + * @param BN_Dst [out]output numberBits of four string + * + * @return (cc_u8 *) four string + */ +cc_u8 * SDRM_BN2STRFOUR(cc_u32 *numberBits, SDRM_BIG_NUM *BN_Src) +{ + SDRM_BIG_NUM *d, *tempREM, *num; + cc_u32 i; + cc_u32 sLength = (2 * SDRM_SIZE_OF_DWORD) * BN_Src->Length; + cc_u8 * strDestTemp = (cc_u8*)malloc(sLength * 10); + cc_u8 * strDest; + cc_u8 tempChar[10]; + (*numberBits) = 0; + + d = SDRM_BN_Init(BN_Src->Size); + if( d == NULL)// fix prevent cid =89093 by guoxing.xu + { + return NULL; + } + tempREM = SDRM_BN_Init(BN_Src->Size); + num = SDRM_BN_Init(BN_Src->Size); + if( num == NULL)//fix prevent cid = 89093 by guoxing.xu + { + SDRM_BN_FREE(d); + return NULL; + } + SDRM_BN_Copy(num, BN_Src); + SDRM_BN_SetWord(d, 4); + + + + while (!SDRM_BN_isZero(num)) + { + SDRM_BN_Div(num, tempREM, num, d); + //itoa(tempREM->pData[0], (char *)tempChar, 10); + //sprintf((char*)tempChar, "%d", tempREM->pData[0]); + snprintf((char*)tempChar, sizeof(tempChar), "%d", tempREM->pData[0]);// fix prevnet 60199 by guoxing.xu + strDestTemp[(*numberBits)] = tempChar[0]; + (*numberBits)++; + + } + + if((*numberBits) != 0) + { + strDest = (cc_u8*)malloc((*numberBits) + 1); + for(i = 0; i < (*numberBits); i++) { + strDest[i] = strDestTemp[((*numberBits) - 1) - i]; + } + strDest[(*numberBits)] = '\0'; + } + else + { + (*numberBits) = 1; + strDest = (cc_u8*)malloc((*numberBits) + 1); + strDest[0] = '0'; + strDest[(*numberBits)] = '\0'; + } + + free(strDestTemp); + SDRM_BN_FREE(d); + SDRM_BN_FREE(tempREM); + SDRM_BN_FREE(num); + + return strDest; +} + +/* + * @fn SDRM_BN_MassInit + * @brief Allocate a series of big number object + * + * @param dBufSize [in]buffer size of each big number + * @param count [in]number BigNumbers + * + * @return double pointer of SDRM_BIG_NUM structure + * \n NULL if memory allocation is failed + */ +SDRM_BIG_NUM **SDRM_BN_MassInit(cc_u32 dBufSize, cc_u32 count) +{ + cc_u32 i; + cc_u32 bnsiz = sizeof(SDRM_BIG_NUM) + dBufSize * SDRM_SIZE_OF_DWORD; + cc_u8* ptr; + void * tmp; + + SDRM_BIG_NUM** BN_Buf = (SDRM_BIG_NUM**)malloc((sizeof(SDRM_BIG_NUM*) + bnsiz) * count); + + if (BN_Buf == NULL) + { + return NULL; + } + + memset(BN_Buf, 0x00, (sizeof(SDRM_BIG_NUM*) + bnsiz) * count); + + ptr = (cc_u8*)BN_Buf + sizeof(SDRM_BIG_NUM*) * count; + for(i = 0; i < count; i++) + { + //add by guoxing.xu to avoid warning. 2/15/2014 + tmp = ptr; + BN_Buf[i] = (SDRM_BIG_NUM*)tmp; + //BN_Buf[i] = (SDRM_BIG_NUM*)ptr; + BN_Buf[i]->Size = dBufSize; + tmp = (ptr + sizeof(SDRM_BIG_NUM)); + BN_Buf[i]->pData = (cc_u32*)tmp; + //BN_Buf[i]->pData = (cc_u32*)(ptr + sizeof(SDRM_BIG_NUM)); + ptr += bnsiz; + } + + return BN_Buf; +} + +/* + * @fn SDRM_BN_IntInit + * @brief Allocate a big number object and assign an integer value + * + * @param dSize [in]buffer size of each big number + * @param data [in]integer value + * + * @return double pointer of SDRM_BIG_NUM structure + * \n NULL if memory allocation is failed + */ +SDRM_BIG_NUM *SDRM_BN_IntInit(cc_u32 dSize, cc_u32 data) +{ + SDRM_BIG_NUM* BN_Buf = SDRM_BN_Init(dSize); + if (BN_Buf == NULL) + { + return NULL; + } + + BN_Buf->pData[0] = data; + BN_Buf->Length = 1; + + return BN_Buf; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/base/cc_des.c b/ssflib/dep/cryptocore/source/base/cc_des.c new file mode 100755 index 0000000..b7834b2 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_des.c @@ -0,0 +1,168 @@ +/** + * \file des.c + * @brief high-speed implementation of DES + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/06 + */ + +////////////////////////////////////////////////////////////////////////// +// Include Header Files +////////////////////////////////////////////////////////////////////////// +#include "cc_des.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_DES_KeySched + * @brief Expand the cipher key into the encryption key schedule + * + * @param RoundKey [out]generated round key + * @param UserKey [in]user key, 8 byte + * @param RKPos [in]index of round key starts + * @param RKStep [in]step for index + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_DES_KeySched(cc_u8 *RoundKey, cc_u8 *UserKey, cc_u32 RKPos, cc_u32 RKStep) +{ + cc_u32 round, i, s, t, t2; + cc_u32 roundkey[16][2]; + cc_u32 c = 0, d = 0; + + //process Permuted Choice 1 + for (i = 0; i < 28; i++) + { + t = SDRM_DES_KS_PC1[i]; + c |= (UserKey[t >> 3] & SDRM_DES_BitMask[t & 0x07]) ? (1 << i) : 0; + } + + for (i = 28; i < 56; i++) + { + t = SDRM_DES_KS_PC1[i]; + d |= (UserKey[t >> 3] & SDRM_DES_BitMask[t & 0x07]) ? (1 << (i - 28)) : 0; + } + + //get round key + for (round = 0; round < SDRM_DES_NUM_OF_ROUNDS; round++) + { + //shift left operation + c = (c >> SDRM_DES_KS_SHIFT[round]) | (c << (28 - SDRM_DES_KS_SHIFT[round])); + d = (d >> SDRM_DES_KS_SHIFT[round]) | (d << (28 - SDRM_DES_KS_SHIFT[round])); + + s = SDRM_des_skb[0][((c) ) & 0x3f] | + SDRM_des_skb[1][((c >> 6L) & 0x03) | ((c >> 7L) & 0x3c)] | + SDRM_des_skb[2][((c >> 13L) & 0x0f) | ((c >> 14L) & 0x30)] | + SDRM_des_skb[3][((c >> 20L) & 0x01) | ((c >> 21L) & 0x06) | ((c>>22L)&0x38)]; + t = SDRM_des_skb[4][((d) ) & 0x3f] | + SDRM_des_skb[5][((d >> 7L) & 0x03) | ((d >> 8L) & 0x3c)] | + SDRM_des_skb[6][ (d >> 15L) & 0x3f] | + SDRM_des_skb[7][((d >> 21L) & 0x0f) | ((d >> 22L) & 0x30)]; + + t2 = (t << 16L) | (s & 0x0000ffffL); + roundkey[RKPos][0] = SDRM_rotr32(t2, 30); + + t2 = ((s >> 16L) | (t & 0xffff0000L)); + roundkey[RKPos][1] = SDRM_rotr32(t2, 26); + + RKPos += RKStep; + } + + memcpy(RoundKey, roundkey, 128); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DES_Encryption + * @brief DES processing for one block + * + * @param RoundKey [in]expanded round key + * @param msg [in]8 byte plaintext + * @param out [out]8 byte ciphertext + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_DES_Encryption(cc_u32 RoundKey[][2], cc_u8 *msg, cc_u8 *out) +{ + cc_u32 l, r, i, t, u; + + r = *(cc_u32*)(void*)(msg); + l = *(cc_u32*)(void*)(msg + 4); + + SDRM_IP(r,l); + + r = SDRM_rotr32(r, 29); + l = SDRM_rotr32(l, 29); + + for (i = 0; i < SDRM_DES_NUM_OF_ROUNDS; i++) + { + if (i & 0x01) + { + SDRM_D_ENCRYPT(r, l); + } + else + { + SDRM_D_ENCRYPT(l, r); + } + } + + r = SDRM_rotr32(r, 3); + l = SDRM_rotr32(l, 3); + + SDRM_INV_IP(r, l); + + memcpy(out , &l, 4); + memcpy(out + 4, &r, 4); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DES64_Encryption + * @brief one block DES Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_DES64_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[16][2]; + + SDRM_DES_KeySched((cc_u8*)RoundKey, UserKey, 0, 1); + + SDRM_DES_Encryption(RoundKey, plainText, cipherText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DES64_Decryption + * @brief one block DES Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_DES64_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[16][2]; + + SDRM_DES_KeySched((cc_u8*)RoundKey, UserKey, 15, (cc_u32)-1); + + SDRM_DES_Encryption(RoundKey, cipherText, plainText); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/base/cc_ecc.c b/ssflib/dep/cryptocore/source/base/cc_ecc.c new file mode 100755 index 0000000..d8251be --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_ecc.c @@ -0,0 +1,1280 @@ +/** + * \file ecc.c + * @brief ecc library based on big number + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jiyoung Moon + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/05/03 + * Note : optimized by Jiyoung Moon & Jisoon Park, August,2006. + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_ecc.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_ECC_Init + * @brief return SDRM_EC_POINT structure + * + * @return address of allocate structure + * \n NULL if memory allocation is failed + */ +SDRM_EC_POINT *SDRM_ECC_Init() +{ + SDRM_EC_POINT *temp; + + temp = (SDRM_EC_POINT *)malloc(sizeof(SDRM_EC_POINT) + SDRM_ECC_ALLOC_SIZE * 5); + if (!temp) + { + return NULL; + } + + temp->IsInfinity = 0; + temp->x = SDRM_BN_Alloc((cc_u8*)temp + sizeof(SDRM_EC_POINT), SDRM_ECC_BN_BUFSIZE); + temp->y = SDRM_BN_Alloc((cc_u8*)temp->x + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + temp->z = SDRM_BN_Alloc((cc_u8*)temp->y + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + temp->z2 = SDRM_BN_Alloc((cc_u8*)temp->z + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + temp->z3 = SDRM_BN_Alloc((cc_u8*)temp->z2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + return temp; +} + +/* + * @fn SDRM_CURVE_Init + * @brief return SDRM_ECC_CTX structure + * + * @return address of allocate structure + * \n NULL if memory allocation is failed + */ +SDRM_ECC_CTX *SDRM_CURVE_Init() +{ + SDRM_ECC_CTX *temp; + SDRM_EC_POINT *ptr; + cc_u8 *pbBlk; + + temp = (SDRM_ECC_CTX *)malloc(sizeof(SDRM_ECC_CTX) + SDRM_ECC_ALLOC_SIZE * 15 + 2 * sizeof(SDRM_EC_POINT)); + if (!temp) { + return NULL; + } + + pbBlk = (cc_u8*)temp + sizeof(SDRM_ECC_CTX); + + temp->ECC_a = SDRM_BN_Alloc(pbBlk, SDRM_ECC_BN_BUFSIZE); + temp->ECC_b = SDRM_BN_Alloc((cc_u8*)temp->ECC_a + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + temp->ECC_p = SDRM_BN_Alloc((cc_u8*)temp->ECC_b + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + temp->ECC_n = SDRM_BN_Alloc((cc_u8*)temp->ECC_p + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + temp->PRIV_KEY = SDRM_BN_Alloc((cc_u8*)temp->ECC_n + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + temp->uDimension = 0; + + ptr = (SDRM_EC_POINT*)(void*)((cc_u8*)temp + sizeof(SDRM_ECC_CTX) + SDRM_ECC_ALLOC_SIZE * 5); + ptr->IsInfinity = 0; + ptr->x = SDRM_BN_Alloc((cc_u8*)ptr + sizeof(SDRM_EC_POINT), SDRM_ECC_BN_BUFSIZE); + ptr->y = SDRM_BN_Alloc((cc_u8*)ptr->x + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + ptr->z = SDRM_BN_Alloc((cc_u8*)ptr->y + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + ptr->z2 = SDRM_BN_Alloc((cc_u8*)ptr->z + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + ptr->z3 = SDRM_BN_Alloc((cc_u8*)ptr->z2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + temp->ECC_G = ptr; + + ptr = (SDRM_EC_POINT*)(void*)((cc_u8*)ptr + sizeof(SDRM_EC_POINT) + SDRM_ECC_ALLOC_SIZE * 5); + ptr->IsInfinity = 0; + ptr->x = SDRM_BN_Alloc((cc_u8*)ptr + sizeof(SDRM_EC_POINT), SDRM_ECC_BN_BUFSIZE); + ptr->y = SDRM_BN_Alloc((cc_u8*)ptr->x + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + ptr->z = SDRM_BN_Alloc((cc_u8*)ptr->y + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + ptr->z2 = SDRM_BN_Alloc((cc_u8*)ptr->z + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + ptr->z3 = SDRM_BN_Alloc((cc_u8*)ptr->z2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + temp->PUBLIC_KEY = ptr; + + return temp; +} + +//////////////////////////////////////////////////////////////////////////// +// ECC Ô¼ +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_CHECK_EC_POINT_ZERO + * @brief check if the point points zero + * + * @param r [in]point + * + * @return 1 if the point is pointing zero + * \n 0 otherwise + */ +int SDRM_CHECK_EC_POINT_ZERO(SDRM_EC_POINT* r) +{ + if ((r->x->Length == 0) | (r->y->Length == 0)) + { + // return = 1 if input is zero + return 1; + } + else + { + return 0; + } +} + +/* + * @fn SDRM_Mont_Jm2Jc + * @brief ǥȯ 1 : Modified Jacobian => Chundnovsky Jacobian + * (A->y) <= (A->y)/2 + * (A->z2) <= (A->z)^2 + * (A->z3) <= (A->z)^3 + * + * @param EC_Dst [out]destination + * @param new_a [in]first element + * @param new_b [in]second element + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_Mont_Jm2Jc(SDRM_EC_POINT *EC_Dst, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont) +{ + if (SDRM_BN_IS_ODD(EC_Dst->y)) + { + if (SDRM_BN_Add(EC_Dst->y, EC_Dst->y, Mont->Mod) != CRYPTO_SUCCESS) + { + return CRYPTO_ERROR; + } + } + + if (SDRM_BN_SHR(EC_Dst->y, EC_Dst->y, 1) != CRYPTO_SUCCESS) + { + return CRYPTO_ERROR; + } + + SDRM_MONT_Mul(EC_Dst->z2, EC_Dst->z, EC_Dst->z, Mont); + SDRM_MONT_Mul(EC_Dst->z3, EC_Dst->z, EC_Dst->z2, Mont); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_Mont_Jc2Jm + * @brief ǥȯ 2 : Chundnovsky Jacobian => Modified Jacobian + * (A->y) <= 2*(A->y) + * (A->z2) <= new_a*(A->z)^4 + * + * @param A [out]destination + * @param new_a [in]first element + * @param new_b [in]second element + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + */ +int SDRM_Mont_Jc2Jm(SDRM_EC_POINT *A, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont) +{ + if (SDRM_BN_SHL(A->y, A->y, 1) != CRYPTO_SUCCESS) + { + return CRYPTO_ERROR; + } + + if (SDRM_BN_Cmp(A->y, Mont->Mod)>=0) + { + SDRM_BN_Sub(A->y, A->y, Mont->Mod); + } + + SDRM_MONT_Mul(A->z2, A->z, A->z, Mont); + SDRM_MONT_Mul(A->z2, A->z2, A->z2, Mont); + SDRM_MONT_Mul(A->z2, new_a, A->z2, Mont); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_CTX_EC_Add + * @brief Affine Coordinate (A = B + C) + * + * @param ctx [in]ECC context + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param EC_Src2 [in]second element(C) + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Add(SDRM_ECC_CTX *ctx, SDRM_EC_POINT* EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_EC_POINT *EC_Src2) +{ + SDRM_BIG_NUM *t1, *t2, *t3, *lambda, *lambda_sqr; + SDRM_BIG_NUM *x3, *y3; + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 7); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if (SDRM_CHECK_EC_POINT_ZERO(EC_Src1)) + { + SDRM_EC_COPY(EC_Dst, EC_Src2); + free(pbBuf); + return CRYPTO_SUCCESS; + } + else if (SDRM_CHECK_EC_POINT_ZERO(EC_Src2)) + { + SDRM_EC_COPY(EC_Dst, EC_Src1); + free(pbBuf); + return CRYPTO_SUCCESS; + } + + t1 = SDRM_BN_Alloc(pbBuf, SDRM_ECC_BN_BUFSIZE); + t2 = SDRM_BN_Alloc((cc_u8*)t1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + t3 = SDRM_BN_Alloc((cc_u8*)t2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + lambda = SDRM_BN_Alloc((cc_u8*)t3 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + lambda_sqr = SDRM_BN_Alloc((cc_u8*)lambda + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + x3 = SDRM_BN_Alloc((cc_u8*)lambda_sqr + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + y3 = SDRM_BN_Alloc((cc_u8*)x3 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + if (SDRM_BN_Cmp(EC_Src1->x, EC_Src2->x) == 0) /* xÇ¥ Ù¸ */ + { + if (SDRM_BN_Cmp(EC_Src1->y, EC_Src2->y) != 0) /* y Ç¥ ٸٸ */ + { // (B = -C) + SDRM_EC_SET_ZERO(EC_Dst); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + else /* y Ç¥ Ù¸ */ + { // (B = C) + SDRM_BN_ModAdd(t1, EC_Src1->y, EC_Src1->y, ctx->ECC_p); /* t1 = 2 * y1 */ + SDRM_BN_ModInv(t1, t1, ctx->ECC_p); /* t1 = 1/(2 * y1) */ + + SDRM_BN_ModMul(t2, EC_Src1->x, EC_Src1->x, ctx->ECC_p); /* t2 = x1^2 */ + SDRM_BN_ModAdd(t3, t2, t2, ctx->ECC_p); /* t3 = t2 + t2 */ + SDRM_BN_ModAdd(t3, t3, t2, ctx->ECC_p); /* t2 = t3 + t2 = 3 * x1^2*/ + SDRM_BN_ModAdd(t3, t3, ctx->ECC_a, ctx->ECC_p); /* t3 = 3 * x1^2 + a */ + + SDRM_BN_ModMul(lambda, t3, t1, ctx->ECC_p); /* lambda = (3 * x1^2 + a) / (2 * y1) */ + } + } + else /* x Ç¥ ٸٸ */ + { + SDRM_BN_ModSub(t1, EC_Src2->x, EC_Src1->x, ctx->ECC_p); /* t1 = x2 - x1 */ + SDRM_BN_ModSub(t2, EC_Src2->y, EC_Src1->y, ctx->ECC_p); /* t2 = y2 - y1 */ + + SDRM_BN_ModInv(t1, t1, ctx->ECC_p); /* t1 = t1^(-1) = 1/(x2-x1) */ + SDRM_BN_ModMul(lambda, t1, t2, ctx->ECC_p); /* lambda = (y2-y1)/(x2-x1) */ + } + + SDRM_BN_ModMul(lambda_sqr, lambda, lambda, ctx->ECC_p); /* lambda^2 */ + SDRM_BN_ModSub(t1, lambda_sqr, EC_Src1->x, ctx->ECC_p); /* x3 = lambda^2 - x1 */ + SDRM_BN_ModSub(x3, t1, EC_Src2->x, ctx->ECC_p); /* x3 = lambda^2 - x1 - x2 */ + + SDRM_BN_ModSub(t1, EC_Src1->x, x3, ctx->ECC_p); /* t1 = x1 - x3 */ + SDRM_BN_ModMul(t2, t1, lambda, ctx->ECC_p); /* t2 = (x1 - x3) * lambda */ + SDRM_BN_ModSub(y3, t2, EC_Src1->y, ctx->ECC_p); /* y3 = (x1 - x3) * lambda - y1 */ + + SDRM_BN_Copy(EC_Dst->x, x3); + SDRM_BN_Copy(EC_Dst->y, y3); + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_EC_Add_Jc + * @brief Chundnovsky Jacobian coordinate + * using montgomery (A = B + C) + * + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param EC_Src2 [in]second element(C) + * @param new_a [in]ECC_A's montgomery value + * @param new_b [in]ECC_B's montgomery value + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Add_Jc(SDRM_EC_POINT *EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_EC_POINT *EC_Src2, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont) +{ + SDRM_BIG_NUM *u1, *u2, *s1, *s2, *h, *r, *tmp1, *tmp2; + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 8); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if (EC_Src1->IsInfinity || SDRM_CHECK_EC_POINT_ZERO(EC_Src1)) + { + SDRM_EC_COPY(EC_Dst, EC_Src2); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + else if (EC_Src2->IsInfinity || SDRM_CHECK_EC_POINT_ZERO(EC_Src2)) + { + SDRM_EC_COPY(EC_Dst, EC_Src1); + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + u1 = SDRM_BN_Alloc(pbBuf , SDRM_ECC_BN_BUFSIZE); + u2 = SDRM_BN_Alloc((cc_u8*)u1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + s1 = SDRM_BN_Alloc((cc_u8*)u2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + s2 = SDRM_BN_Alloc((cc_u8*)s1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + h = SDRM_BN_Alloc((cc_u8*)s2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + r = SDRM_BN_Alloc((cc_u8*)h + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + tmp1 = SDRM_BN_Alloc((cc_u8*)r + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + tmp2 = SDRM_BN_Alloc((cc_u8*)tmp1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + // u1 + SDRM_MONT_Mul(u1, EC_Src1->x, EC_Src2->z2, Mont); + // u2 + SDRM_MONT_Mul(u2, EC_Src2->x, EC_Src1->z2, Mont); + // s1 + SDRM_MONT_Mul(s1, EC_Src1->y, EC_Src2->z3, Mont); + // s2 + SDRM_MONT_Mul(s2, EC_Src2->y, EC_Src1->z3, Mont); + + SDRM_BN_Sub(h, u2, u1); + if (h->sign) + { + SDRM_BN_Add(h, h, Mont->Mod); + } + + // r + SDRM_BN_Sub(r, s2, s1); + if (r->sign) + { + SDRM_BN_Add(r, r, Mont->Mod); + } + + // exception cases check + if (h->Length == 0) + { + if (r->Length == 0) + { + // If (h == 0) & (r == 0), CTX_EC_Double_Jc + // because B, C are same point. + free(pbBuf); + + return SDRM_CTX_EC_Double_Jc(EC_Dst, EC_Src1, new_a, new_b, Mont); + } + else + { + // If (h == 0) & (r != 0), A = Infinity point + EC_Dst->IsInfinity = 1; + free(pbBuf); + + return CRYPTO_INFINITY_INPUT; + } + } + + // EC_Dst->x + SDRM_MONT_Mul(EC_Dst->x, r, r, Mont); + SDRM_MONT_Mul(EC_Dst->y, h, h, Mont); // A->y : h^2, temp + SDRM_MONT_Mul(tmp1, EC_Dst->y, h, Mont); // tmp1 : h^3, temp + SDRM_MONT_Mul(EC_Dst->y, u1, EC_Dst->y, Mont); // A->y : u1*h^2 + + SDRM_BN_SHL(tmp2, EC_Dst->y, 1); + if (SDRM_BN_Cmp(tmp2, Mont->Mod) >= 0) + { + SDRM_BN_Sub(tmp2, tmp2, Mont->Mod); + } + + SDRM_BN_ModSub(EC_Dst->x, EC_Dst->x, tmp2, Mont->Mod); + SDRM_BN_ModSub(EC_Dst->x, EC_Dst->x, tmp1, Mont->Mod); + + // EC_Dst->y + SDRM_BN_ModSub(EC_Dst->y, EC_Dst->y, EC_Dst->x, Mont->Mod); + SDRM_MONT_Mul(EC_Dst->y, r, EC_Dst->y, Mont); + SDRM_MONT_Mul(tmp1, s1, tmp1, Mont); + SDRM_BN_ModSub(EC_Dst->y, EC_Dst->y, tmp1, Mont->Mod); + + // EC_Dst->z + SDRM_MONT_Mul(EC_Dst->z, EC_Src1->z, EC_Src2->z, Mont); + SDRM_MONT_Mul(EC_Dst->z, EC_Dst->z, h, Mont); + + // È¿ Æ· -> Ê¿ ܺο +#if 0 + // EC_Dst->z2 + SDRM_MONT_Mul(EC_Dst->z2, EC_Dst->z, EC_Dst->z, Mont); + // EC_Dst->z3 + SDRM_MONT_Mul(EC_Dst->z3, EC_Dst->z, EC_Dst->z2, Mont); +#endif + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_EC_Double_Jc + * @brief Chundnovsky Jacobian coordinate + * montgomery (A = 2B) + * + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param new_a [in]ECC_A's montgomery value + * @param new_b [in]ECC_B's montgomery value + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Double_Jc(SDRM_EC_POINT *EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont) +{ + SDRM_BIG_NUM *s, *k, *tmp1, *tmp2; + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 4); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + // If B = infinite point || (B->y) = 0, A = infinite point. + if (EC_Src1->IsInfinity || SDRM_CHECK_EC_POINT_ZERO(EC_Src1)) + { + EC_Dst->IsInfinity = 1; + free(pbBuf); + return CRYPTO_SUCCESS; + } + + s = SDRM_BN_Alloc(pbBuf , SDRM_ECC_BN_BUFSIZE); + k = SDRM_BN_Alloc((cc_u8*)s + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + tmp1 = SDRM_BN_Alloc((cc_u8*)k + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + tmp2 = SDRM_BN_Alloc((cc_u8*)tmp1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + // s + SDRM_MONT_Mul(s, EC_Src1->y, EC_Src1->y, Mont); // s = (B->y)^2 + SDRM_MONT_Mul(tmp1, s, s, Mont); // tmp1 = (B->y)^4 + SDRM_MONT_Mul(s, EC_Src1->x, s, Mont); + SDRM_BN_SHL(s, s, 2); + SDRM_BN_ModRed(s, s, Mont->Mod); + + // k + SDRM_MONT_Mul(k, EC_Src1->x, EC_Src1->x, Mont); + SDRM_BN_SHL(tmp2, k, 1); + SDRM_BN_ModAdd(tmp2, tmp2, k, Mont->Mod); + SDRM_MONT_Mul(k, EC_Src1->z, EC_Src1->z3, Mont); + SDRM_MONT_Mul(k, new_a, k, Mont); + SDRM_BN_ModAdd(k, tmp2, k, Mont->Mod); + + // t & EC_Dst->x + SDRM_BN_SHL(tmp2, s, 1); + + if (SDRM_BN_Cmp(tmp2, Mont->Mod)>=0) + { + SDRM_BN_Sub(tmp2, tmp2, Mont->Mod); + } + + SDRM_MONT_Mul(EC_Dst->x, k, k, Mont); + SDRM_BN_ModSub(EC_Dst->x, EC_Dst->x, tmp2, Mont->Mod); + + // EC_Dst->z + SDRM_MONT_Mul(EC_Dst->z, EC_Src1->y, EC_Src1->z, Mont); + SDRM_BN_SHL(EC_Dst->z, EC_Dst->z, 1); + + if (SDRM_BN_Cmp(EC_Dst->z, Mont->Mod)>=0) + { + SDRM_BN_Sub(EC_Dst->z, EC_Dst->z, Mont->Mod); + } + + // EC_Dst->y + SDRM_BN_SHL(EC_Dst->y, tmp1, 3); + while(SDRM_BN_Cmp(EC_Dst->y, Mont->Mod) >= 0) + { + SDRM_BN_Sub(EC_Dst->y, EC_Dst->y, Mont->Mod); + } + + SDRM_BN_ModSub(tmp1, s, EC_Dst->x, Mont->Mod); // tmp1 = s-t (s Ù²) + SDRM_MONT_Mul(tmp1, k, tmp1, Mont); // k(s-t) + SDRM_BN_ModSub(EC_Dst->y, tmp1, EC_Dst->y, Mont->Mod); + if (EC_Dst->y->sign) + { + SDRM_BN_Add(EC_Dst->y, EC_Dst->y, Mont->Mod); + } + + // EC_Dst->z2 + SDRM_MONT_Mul(EC_Dst->z2, EC_Dst->z, EC_Dst->z, Mont); + + // EC_Dst->z3 + SDRM_MONT_Mul(EC_Dst->z3, EC_Dst->z, EC_Dst->z2, Mont); + + // Memory Free + free(pbBuf); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_CTX_EC_Double_Jm + * @brief Modified Jacobian coordinate + * montgomery (A = 2B) + * + * @param EC_Dst [out]destination(A) + * @param EC_Src1 [in]first element(B) + * @param new_a [in]ECC_A's montgomery value + * @param new_b [in]ECC_B's montgomery value + * @param Mont [in]montgomery context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_ERROR if evaluation is failed + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CTX_EC_Double_Jm(SDRM_EC_POINT *EC_Dst, SDRM_EC_POINT *EC_Src1, SDRM_BIG_NUM *new_a, SDRM_BIG_NUM *new_b, SDRM_BIG_MONT *Mont) +{ + SDRM_BIG_NUM *a, *b, *c, *tmp1; + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 4); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + // If B is the infinite point or (B->y) is zero, A is the infinite point. + if (EC_Src1->IsInfinity || SDRM_CHECK_EC_POINT_ZERO(EC_Src1)) + { + EC_Dst->IsInfinity = 1; + free(pbBuf); + + return CRYPTO_SUCCESS; + } + + a = SDRM_BN_Alloc(pbBuf, SDRM_ECC_BN_BUFSIZE); + b = SDRM_BN_Alloc((cc_u8*)a + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + c = SDRM_BN_Alloc((cc_u8*)b + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + tmp1 = SDRM_BN_Alloc((cc_u8*)c + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + // a + SDRM_MONT_Mul(a, EC_Src1->x, EC_Src1->x, Mont); + SDRM_BN_SHL(tmp1, a, 1); + SDRM_BN_Add(a, tmp1, a); + SDRM_BN_Add(a, a, EC_Src1->z2); + while(SDRM_BN_Cmp(a, Mont->Mod) >= 0) + { + SDRM_BN_Sub(a, a, Mont->Mod); + } + + // b & c + SDRM_MONT_Mul(b, EC_Src1->y, EC_Src1->y, Mont); // b = (y1)^2 + SDRM_MONT_Mul(c, b, b, Mont); // c = (y1)^4 + SDRM_MONT_Mul(b, EC_Src1->x, b, Mont); + SDRM_BN_SHL(b, b, 1); + if (SDRM_BN_Cmp(b, Mont->Mod)>=0) + { + SDRM_BN_Sub(b, b, Mont->Mod); + } + + // EC_Dst->x + SDRM_MONT_Mul(EC_Dst->x, a, a, Mont); + SDRM_BN_ModSub(EC_Dst->x, EC_Dst->x, b, Mont->Mod); + + // EC_Dst->z + SDRM_MONT_Mul(EC_Dst->z, EC_Src1->y, EC_Src1->z, Mont); + + // EC_Dst->y + SDRM_BN_SHL(EC_Dst->y, EC_Dst->x, 1); + + if (SDRM_BN_Cmp(EC_Dst->y, Mont->Mod)>=0) + { + SDRM_BN_Sub(EC_Dst->y, EC_Dst->y, Mont->Mod); + } + + SDRM_BN_Sub(EC_Dst->y, b, EC_Dst->y); + + if (EC_Dst->y->sign) + { + SDRM_BN_Add(EC_Dst->y, EC_Dst->y, Mont->Mod); + } + + SDRM_MONT_Mul(EC_Dst->y, a, EC_Dst->y, Mont); + SDRM_BN_ModSub(EC_Dst->y, EC_Dst->y, c, Mont->Mod); + + // EC_Dst->z2 + SDRM_MONT_Mul(EC_Dst->z2, c, EC_Dst->z2, Mont); + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_EC_Chain + * @brief Chain Ô¼ + * signed wondow method : size of window = 4 + * chain for addition/subtraction of k Using sliding window method + * + * @param chain [out]destination + * @param L_Src [in]byte-length of chain + * @param Len_Src [in]number of doubling in chain + * @param k [in]source + * @param window_size [in]size of window + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if given value is incorrect + */ +int SDRM_CTX_EC_Chain(signed char *chain, cc_u32 *L_Src, cc_u32 *Len_Src, SDRM_BIG_NUM *k, int window_size) +{ + int i, j = 0, AddorSub, last = 0, doublings = 0; + int bits_k = 0, subtract=0, pos = 0, temp_1 = 0; + cc_u32 temp = 0; + cc_u32 numDoubling = 0; // number of doubling(= lshift) + + // k È¿ check + if (k->sign) + { + return CRYPTO_INVALID_ARGUMENT; + } + + bits_k=(SDRM_BN_num_bits(k)-1); + + // sliding window method ('06) + while(bits_k>=0) + { + if ((bits_k + 1) < window_size) { + window_size = bits_k + 1; + } + + if ((subtract == 0) || (subtract == 10)) + { + AddorSub = 0; + } + else + { + AddorSub = 1; + } + + for(i = bits_k; i >= bits_k - window_size + 1; i--) + { + temp <<= 1; + temp += AddorSub ^ SDRM_CheckBitUINT32(k->pData, i); + } + + bits_k -= window_size; + + if ((SDRM_CheckBitUINT32(k->pData, bits_k) == (cc_u32)1 - AddorSub) && (bits_k >= 0)) + { + temp++; + AddorSub = 1 - AddorSub; + } + + if ((bits_k == -1) && (AddorSub == 1)) { + temp++; + } + + if (bits_k>=0) + { + if (SDRM_CheckBitUINT32(k->pData, bits_k)==1) + { + if ((subtract == 0) || (subtract == 10)) + { + subtract = 1; + } + else + { + subtract = 11; + } + + for(temp_1 = 0 ; SDRM_CheckBitUINT32(k->pData, bits_k)==1; bits_k--) + { + if (bits_k >=0) + { + temp_1++; + } + } + } + else + { + if ((subtract == 0) || (subtract == 10)) + { + subtract = 0; + } + else + { + subtract = 10; + } + + for(temp_1 = 0 ; SDRM_CheckBitUINT32(k->pData, bits_k)==0; bits_k--) + { + if (bits_k >=0) + { + temp_1++; + } + } + } + + if (bits_k < 0) + { + last = 1; + } + } + else + { + if ((subtract == 0) || (subtract == 10)) + { + subtract = 0; + } + else + { + subtract = 10; + } + } + + j = temp >> window_size; + + if (temp != 0) + { + for(doublings = 0; !(temp&0x1); doublings++) + { + temp >>= 1; + } + doublings += temp_1; + } + else + { + doublings = temp_1; + } + + if (pos > 0) + { + for(i = temp ; i > j ; i>>=1) + { + chain[++pos] = 0; + numDoubling++; + } + } + + if ((subtract==10) || (subtract == 11)) + { + chain[++pos] = (char)((~temp + 1) & 0xff); + } + else + { + chain[++pos] = (char)((temp) & 0xff); + } + + for( ; doublings > 0; doublings--) + { + chain[++pos] = 0; + numDoubling++; + } + + if (last == 1) + { + if (AddorSub == 1) + { + chain[++pos] = -1; + } + } + + temp = 0; + temp_1 = 0; + } + + *L_Src = pos; + *Len_Src = numDoubling; + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_EC_kP + * @brief get EC_Dst = kP by Montgomery Method + * + * @param ctx [in]ecc context + * @param EC_Dst [out]destination + * @param EC_Src [in]first element(P) + * @param k [in]second element(k) + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if the arguemnt represents a minus value + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_INFINITY_INPUT if the argument is a infinity value + */ +int SDRM_CTX_EC_kP(SDRM_ECC_CTX *ctx, SDRM_EC_POINT* EC_Dst, SDRM_EC_POINT *EC_Src, SDRM_BIG_NUM *k) +{ + int res, i; + int window_size = 4; // window size + int w_p = (1 << (window_size-1)) + 1; // pre-computation number +// int add = 0, subtract = 0; // add : num_(addition + subtract) + // subtract : 0 - before = 0 & after = 0 + // 10 - before = 1 & after = 0 + // 1 - before = 0 & after = 1 + // 11 - before = 1 & after = 1 + // => 0 : no subtract / 1 : subtract + SDRM_EC_POINT *Pw[9] = {0}; // number of precomputation data : 9 = w_p = 2^(window_size-1) + 1 + SDRM_BIG_MONT *Mont; + SDRM_BIG_NUM *new_a, *new_b; + SDRM_BIG_NUM *t1, *t2; + signed char chain[2 * SDRM_MAX_DIMENSION_ECC]; // DIMENSION_ECC : ecdsa.h define + cc_u32 length; // addition & subtrction chain length of k1 & k2 + cc_u32 lenD; // number of doubling of addition & subtrction chain of k1 & k2 + + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 4); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + // k P È¿ check + if (k->sign) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if (EC_Src->x->sign|EC_Src->y->sign) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + Mont = SDRM_MONT_Init(ctx->ECC_p->Size); + if (Mont == NULL) + { + free(pbBuf); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_MONT_Set(Mont, ctx->ECC_p); + + new_a = SDRM_BN_Alloc(pbBuf, SDRM_ECC_BN_BUFSIZE); + new_b = SDRM_BN_Alloc((cc_u8*)new_a + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + t1 = SDRM_BN_Alloc((cc_u8*)new_b + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + t2 = SDRM_BN_Alloc((cc_u8*)t1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + if (SDRM_MONT_Zn2rzn(new_a, ctx->ECC_a, Mont) != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + return CRYPTO_ERROR; + } + + if (SDRM_MONT_Zn2rzn(new_b, ctx->ECC_b, Mont) != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + return CRYPTO_ERROR; + } + + + //chain + res = SDRM_CTX_EC_Chain(chain, &length, &lenD, k, window_size); + if (res != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + + return CRYPTO_ERROR; + } + + // pre-computation Data : Chunvosky algorithm + // Pw[1] = EC_Src + // Pw[2] = 3 * EC_Src + // Pw[3] = 5 * EC_Src + // Pw[4] = 7 * EC_Src + // .................. + for(i = 0; i < 9; i++) + { + Pw[i] = SDRM_ECC_Init(); + if (Pw[i] == NULL) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + while (i > 0) + { + free(Pw[--i]); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + } + + SDRM_EC_COPY(Pw[1], EC_Src); + + SDRM_MONT_Zn2rzn(Pw[1]->x, Pw[1]->x, Mont); + SDRM_MONT_Zn2rzn(Pw[1]->y, Pw[1]->y, Mont); + SDRM_MONT_Zn2rzn(Pw[1]->z, BN_One, Mont); + + SDRM_BN_Copy(Pw[1]->z2, Pw[1]->z); + SDRM_BN_Copy(Pw[1]->z3, Pw[1]->z); + + SDRM_EC_SET_ZERO(Pw[0]); + SDRM_CTX_EC_Double_Jc(Pw[0], Pw[1], new_a, new_b, Mont); + + for (i = 2; i < w_p; i++) + { + SDRM_EC_SET_ZERO(Pw[i]); + SDRM_CTX_EC_Add_Jc(Pw[i], Pw[i-1], Pw[0], new_a, new_b, Mont); + + SDRM_MONT_Mul(Pw[i]->z2, Pw[i]->z, Pw[i]->z, Mont); + SDRM_MONT_Mul(Pw[i]->z3, Pw[i]->z2, Pw[i]->z, Mont); + } + + EC_Dst->IsInfinity = 1; + + for(i = 0; i != (int)length; i++) + { + if (chain[i + 1]==0) + { + // EC_Dst = 2 * EC_Dst + SDRM_CTX_EC_Double_Jm(EC_Dst, EC_Dst, new_a, new_b, Mont); + lenD--; + } + else + { + SDRM_Mont_Jm2Jc(EC_Dst, new_a, new_b, Mont); + if (chain[i + 1]>0) + { + // EC_Dst = EC_Dst + Pw[(chain[i + 1]+1)/2] + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[(chain[i + 1]+1)/2], new_a, new_b, Mont); + } + else + { + // EC_Dst = EC_Dst - Pw[(chain[i + 1]]+1)/2] + SDRM_EC_COPY(Pw[0], Pw[(-chain[i + 1]+1)/2]); + SDRM_BN_Sub(Pw[0]->y, ctx->ECC_p, Pw[0]->y); + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[0], new_a, new_b, Mont); + } + SDRM_Mont_Jc2Jm(EC_Dst, new_a, new_b, Mont); + } + } + + // montgomery reduction of EC_Dst + SDRM_MONT_Rzn2zn(EC_Dst->x, EC_Dst->x, Mont); + SDRM_MONT_Rzn2zn(EC_Dst->y, EC_Dst->y, Mont); + SDRM_MONT_Rzn2zn(EC_Dst->z, EC_Dst->z, Mont); + + if (EC_Dst->z->Length == 0) + { + for(i = 0; i < 9; i++) + { + free(Pw[i]); + } + free(pbBuf); + SDRM_MONT_Free(Mont); + + EC_Dst->IsInfinity = 1; + + return CRYPTO_INFINITY_INPUT; + } + // Convert coordinate : "Modified Jacobian" => "Affine" + // (EC_Dst->x) <= (EC_Dst->x) * { ((EC_Dst->z)^2)^-1 } + // (EC_Dst->y) <= (EC_Dst->y) * { (2*((EC_Dst->z)^3))^-1 } + + SDRM_BN_ModMul(t1, EC_Dst->z, EC_Dst->z, ctx->ECC_p); + SDRM_BN_ModInv(t2, t1, ctx->ECC_p); + SDRM_BN_ModMul(EC_Dst->x, EC_Dst->x, t2, ctx->ECC_p); + + SDRM_BN_ModMul(t1, t1, EC_Dst->z, ctx->ECC_p); + SDRM_BN_SHL(t1, t1, 1); + SDRM_BN_ModInv(t2, t1, ctx->ECC_p); + SDRM_BN_ModMul(EC_Dst->y, EC_Dst->y, t2, ctx->ECC_p); + + // Memory Free + for(i = 0; i < 9; i++) + { + free(Pw[i]); + } + + free(pbBuf); + SDRM_MONT_Free(Mont); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_EC_2kP + * @brief get EC_Dst = k1*C1 + k2*C2 + * + * @param ctx [in]ecc context + * @param EC_Dst [out]destination + * @param k1 [in]first element(k1) + * @param EC_Src1 [in]second element(C1) + * @param k2 [in]third element(k2) + * @param EC_Src2 [in]fourth element(C2) + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if the arguemnt represents a minus value + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_INFINITY_INPUT if the argument is a infinity value + */ +int SDRM_CTX_EC_2kP(SDRM_ECC_CTX *ctx, SDRM_EC_POINT *EC_Dst, SDRM_BIG_NUM *k1, SDRM_EC_POINT *EC_Src1, SDRM_BIG_NUM *k2, SDRM_EC_POINT *EC_Src2) +{ + signed char chain[2][2 * SDRM_MAX_DIMENSION_ECC]; // addition/subtrction chain of k1 k2 + cc_u32 length[2]; // addition/subtrction chain length of k1 k2 + cc_u32 lenD[2]; // # of doubling of addition/subtrction chain of k1 k2 + cc_u32 idx[2]; + int window_size = 4; // window size + int w2 = (1 << (window_size - 1)) + 1; // 2^(window_size-1)+1 : the precomputation point number + int i, j, res; + SDRM_EC_POINT *Pw[2][9]; // precomputation data + SDRM_BIG_MONT *Mont=NULL; + SDRM_BIG_NUM *new_a, *new_b; + SDRM_BIG_NUM *t1, *t2; // Used in coordinate change from "Modified Jacobian" to "Affine" + + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 4); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + // k1 & k2 & C1 & C2 È¿ check + if (k1->sign | k2->sign) + { + free(pbBuf); + + return CRYPTO_ERROR; + } + + if (EC_Src1->x->sign | EC_Src1->y->sign | EC_Src2->x->sign | EC_Src2->y->sign) + { + free(pbBuf); + + return CRYPTO_ERROR; + } + + Mont = SDRM_MONT_Init(ctx->ECC_p->Size); + SDRM_MONT_Set(Mont, ctx->ECC_p); + + new_a = SDRM_BN_Alloc(pbBuf, SDRM_ECC_BN_BUFSIZE); + new_b = SDRM_BN_Alloc((cc_u8*)new_a + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + t1 = SDRM_BN_Alloc((cc_u8*)new_b + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + t2 = SDRM_BN_Alloc((cc_u8*)t1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + if (SDRM_MONT_Zn2rzn(new_a, ctx->ECC_a, Mont) != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + return CRYPTO_ERROR; + } + + if (SDRM_MONT_Zn2rzn(new_b, ctx->ECC_b, Mont) != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + return CRYPTO_ERROR; + } + + // chain + res = SDRM_CTX_EC_Chain(chain[0], &length[0], &lenD[0], k1, window_size); + if (res != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + return res; + } + + res = SDRM_CTX_EC_Chain(chain[1], &length[1], &lenD[1], k2, window_size); + if (res != CRYPTO_SUCCESS) + { + free(pbBuf); + SDRM_MONT_Free(Mont); + return res; + } + + // Precomputation data + for(i = 0; i < 2; i++) + { +// Pw[i] = (SDRM_EC_POINT **)malloc(sizeof(SDRM_EC_POINT *) * w2); +// if (!Pw[i]) return CRYPTO_MEMORY_ALLOC_FAIL; + for(j = 0; j < 9; j++) + { + Pw[i][j] = SDRM_ECC_Init(); + } + } + + SDRM_EC_COPY(Pw[0][1], EC_Src1); + SDRM_EC_COPY(Pw[1][1], EC_Src2); + + for (i=0;i<2;i++) + { + SDRM_MONT_Zn2rzn(Pw[i][1]->x, Pw[i][1]->x, Mont); + SDRM_MONT_Zn2rzn(Pw[i][1]->y, Pw[i][1]->y, Mont); + SDRM_MONT_Zn2rzn(Pw[i][1]->z, BN_One, Mont); + SDRM_BN_Copy(Pw[i][1]->z2, Pw[i][1]->z); + SDRM_BN_Copy(Pw[i][1]->z3, Pw[i][1]->z); + SDRM_CTX_EC_Double_Jc(Pw[i][0], Pw[i][1], new_a, new_b, Mont); + + for (j=2;jz2, Pw[i][j]->z, Pw[i][j]->z, Mont); + SDRM_MONT_Mul(Pw[i][j]->z3, Pw[i][j]->z2, Pw[i][j]->z, Mont); + } + } + + EC_Dst->IsInfinity = 1; + idx[0] = idx[1] = 1; + + // ì¼± doubling Å« + if (lenD[0] != lenD[1]) + { + i = ((lenD[0] > lenD[1]) ? 0 : 1); + for (;lenD[0] != lenD[1]; idx[i]++) + { + if (chain[i][idx[i]] == 0) + { + // EC_Dst = 2EC_Dst + SDRM_CTX_EC_Double_Jm(EC_Dst, EC_Dst, new_a, new_b, Mont); + lenD[i]--; + } + else + { + SDRM_Mont_Jm2Jc(EC_Dst, new_a, new_b, Mont); + + if (chain[i][idx[i]]>0) + { + // EC_Dst = EC_Dst + Pw[i][(chain[i][idx[i]]+1)/2] + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[i][(chain[i][idx[i]]+1)/2], new_a, new_b, Mont); + } + else + { + // EC_Dst = EC_Dst - Pw[i][(chain[i][idx[i]]+1)/2] + SDRM_EC_COPY(Pw[i][0], Pw[i][(-chain[i][idx[i]]+1)/2]); + SDRM_BN_Sub(Pw[i][0]->y, ctx->ECC_p, Pw[i][0]->y); + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[i][0], new_a, new_b, Mont); + } + SDRM_Mont_Jc2Jm(EC_Dst, new_a, new_b, Mont); + } + } + } + + while ((idx[0] <= length[0]) && (idx[1] <= length[1])) + { + if ((chain[0][idx[0]] == 0) && (chain[1][idx[1]] == 0)) + { + // EC_Dst = 2EC_Dst + SDRM_CTX_EC_Double_Jm(EC_Dst, EC_Dst, new_a, new_b, Mont); + idx[0]++; + idx[1]++; + continue; + } + + SDRM_Mont_Jm2Jc(EC_Dst, new_a, new_b, Mont); + + if (chain[0][idx[0]]!=0) + { + if (chain[0][idx[0]]>0) + { + // EC_Dst = EC_Dst + Pw[0][(chain[0][idx[0]]+1)/2] + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[0][(chain[0][idx[0]] + 1) / 2], new_a, new_b, Mont); + } + else + { + // EC_Dst = EC_Dst - Pw[0][(chain[0][idx[0]]+1)/2] + SDRM_EC_COPY(Pw[0][0], Pw[0][(-chain[0][idx[0]] + 1) / 2]); + SDRM_BN_Sub(Pw[0][0]->y, ctx->ECC_p, Pw[0][0]->y); + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[0][0], new_a, new_b, Mont); + } + + idx[0]++; + + if (chain[1][idx[1]] != 0) + { + // make z^2, z^3 for next computation + SDRM_MONT_Mul(EC_Dst->z2, EC_Dst->z, EC_Dst->z, Mont); + SDRM_MONT_Mul(EC_Dst->z3, EC_Dst->z2, EC_Dst->z, Mont); + } + } + + if (chain[1][idx[1]]!=0) + { + if (chain[1][idx[1]]>0) + { + // EC_Dst = EC_Dst + Pw[1][(chain[1][idx[1]]+1)/2] + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[1][(chain[1][idx[1]]+1)/2], new_a, new_b, Mont); + } + else + { + // EC_Dst = EC_Dst - Pw[1][(chain[1][idx[1]]+1)/2] + SDRM_EC_COPY(Pw[1][0], Pw[1][(-chain[1][idx[1]]+1)/2]); + SDRM_BN_Sub(Pw[1][0]->y, ctx->ECC_p, Pw[1][0]->y); + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[1][0], new_a, new_b, Mont); + } + idx[1]++; + } + SDRM_Mont_Jc2Jm(EC_Dst, new_a, new_b, Mont); + } + + if ((idx[0]==length[0]) || (idx[1]==length[1])) + { + i = ((idx[0]==length[0]) ? 0 : 1); + + SDRM_Mont_Jm2Jc(EC_Dst, new_a, new_b, Mont); + + if (chain[i][idx[i]]>0) + { + // EC_Dst = EC_Dst + Pw[i][(chain[i][idx[i]]+1)/2] + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[i][(chain[i][idx[i]] + 1) / 2], new_a, new_b, Mont); + } + else + { + // EC_Dst = EC_Dst - Pw[i][(chain[i][idx[i]]+1)/2] + SDRM_EC_COPY(Pw[i][0], Pw[i][(-chain[i][idx[i]] + 1) / 2]); + SDRM_BN_Sub(Pw[i][0]->y, ctx->ECC_p, Pw[i][0]->y); + SDRM_CTX_EC_Add_Jc(EC_Dst, EC_Dst, Pw[i][0], new_a, new_b, Mont); + } + SDRM_Mont_Jc2Jm(EC_Dst, new_a, new_b, Mont); + } + + + // montgomery reduction of EC_Dst + SDRM_MONT_Rzn2zn(EC_Dst->x, EC_Dst->x, Mont); + SDRM_MONT_Rzn2zn(EC_Dst->y, EC_Dst->y, Mont); + SDRM_MONT_Rzn2zn(EC_Dst->z, EC_Dst->z, Mont); + + if (EC_Dst->z->Length == 0) + { + for(i = 0; i < 2; i++) + { + for(j = 0; j < 9; j++) + { + free(Pw[i][j]); + } + } + + free(pbBuf); + SDRM_MONT_Free(Mont); + + EC_Dst->IsInfinity = 1; + + return CRYPTO_INFINITY_INPUT; + } + + // ǥȯ : Modified Jacobian => Affine + // (EC_Dst->x) <= (EC_Dst->x) * { ((EC_Dst->z)^2)^-1 } + // (EC_Dst->y) <= (EC_Dst->y) * { (2*((EC_Dst->z)^3))^-1 } + SDRM_BN_ModMul(t1, EC_Dst->z, EC_Dst->z, ctx->ECC_p); + SDRM_BN_ModInv(t2, t1, ctx->ECC_p); + SDRM_BN_ModMul(EC_Dst->x, EC_Dst->x, t2, ctx->ECC_p); + + SDRM_BN_ModMul(t2, t1, EC_Dst->z, ctx->ECC_p); + SDRM_BN_SHL(t2, t2, 1); + SDRM_BN_ModInv(t1, t2, ctx->ECC_p); + SDRM_BN_ModMul(EC_Dst->y, EC_Dst->y, t1, ctx->ECC_p); + + for(i = 0; i < 2; i++) + { + for(j = 0; j < 9; j++) + { + free(Pw[i][j]); + } + } + + free(pbBuf); + SDRM_MONT_Free(Mont); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/base/cc_fast_math.c b/ssflib/dep/cryptocore/source/base/cc_fast_math.c new file mode 100755 index 0000000..2718a8b --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_fast_math.c @@ -0,0 +1,914 @@ +/** + * @file fast_mathf.c + * @brief This file contains optimized implementations for severall basic arithmetical functions. + * + * [Optional] Detail description (major features, interface description, flow of control, and so on) + * @see [Optional] Related information + + * Copyright 2008 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + * + * \internal + * Author : Karen Ispiryan + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2008/08/28 +*/ + +#include +#include + +#include "CryptoCore.h" +#include "CC_Constants.h" +#include "cc_bignum.h" + +#include "cc_fast_math.h" + +/** + * @fn SDRM_ll_Cmp + * @brief Compare two large unsigned integers + * + * @param pFirstOperand [in] the first operand + * @param pSecondOperand [in] the second operand + * + * @return 0 if they are equal + * 1 if first bigger then second + * -1 if the seond one is bigger then first + */ +int SDRM_ll_Cmp(const BasicWord *pFirstOperand, const BasicWord *pSecondOperand, unsigned uOperandLength) +{ + pFirstOperand += uOperandLength; + pSecondOperand += uOperandLength; + + while (uOperandLength--) { + if (*--pFirstOperand != *--pSecondOperand) + { + if (*pFirstOperand < *pSecondOperand) + { + return -1; + } + else + { + return 1; + } + } + } + return 0; +} + +/** + * @fn SDRM_ll_Copy + * @brief Just copy two large unsigned integers from one into another + */ +void SDRM_ll_Copy(BasicWord *pFirstOperand, const BasicWord *pSecondOperand, unsigned uOperandLength) +{ + while (uOperandLength--) + { + *pFirstOperand++ = *pSecondOperand++; + } +} + +/** + * @fn SDRM_ll_bit_RShift + * @brief Shift large unsigned integer to the right by uBits + * + * @param pOperand [inout] pointer to the operand to be shifted + * + * @return Nothing + * @warning We have to be careful when using this function because it modifies uOperandLength+1 words + * that is by 1 word bigger then operand original size. + * WWW....Operand...WWW|W <- it modifies the word immediately after the last one of passed operand. + */ +void SDRM_ll_bit_RShift(IN OUT BasicWord *pOperand, IN BasicWord uOperandLength, OUT BasicWord uBits) +{ + BasicWord uLastIndex = (BasicWord)(uOperandLength - 1); + register BasicWord t; + + while (uLastIndex--) + { + t = *pOperand >> uBits; + *pOperand = t | (*(pOperand + 1) << (BASICWORD_BITS_COUNT - uBits)); + pOperand++; + } + *pOperand >>= uBits; +} + +/** + * @fn SDRM_ll_bit_LShift + * @brief Shift large unsigned integer to the left by uBits + * + * @param pOperand [inout] pointer to the operand to be shifted + * + * @return Nothing + * @warning We have to be careful when using this function because it modifies uOperandLength+1 words + * that is by 1 word bigger then operand original size. + * It modifies the word immediately prior to the first one of passed operand -> W|WWW....Operand...WWW + */ +void SDRM_ll_bit_LShift(IN OUT BasicWord *pOperand, IN BasicWord uOperandLength, OUT BasicWord uBits) +{ + BasicWord uLastIndex = (BasicWord)(uOperandLength - 1); + BasicWord t; + + pOperand += uOperandLength-1; + while (uLastIndex--) + { + t = *pOperand << uBits; + *pOperand = t | (*(pOperand - 1) >> (BASICWORD_BITS_COUNT - uBits)); + pOperand--; + } + *pOperand <<= uBits; +} + +/** + * @fn SDRM_ll_getMSW + * @brief Return index of most significant word. + * + * @param pOperand [in] pointer to the large integer. + * + * @return The index of most significant word. + * -1 if passed integer actually is equal to 0. + */ +int SDRM_ll_getMSW(IN const BasicWord *pOperand, IN BasicWord uOperandLength) +{ + int nEl; + for(nEl = uOperandLength - 1; nEl >= 0; nEl--) + { + if (0 != pOperand[nEl]) + { + break; + } + } + return nEl; +} + +/** + * @fn SDRM_ll_getMSB + * @brief Find the leftmost non-zero bit in passed unsigned integer. + * + * @param oneWord [in] value of unsigned integer + * + * @return Position of leftmost non-zero bit. + * @warning Actually this function returns the position of leftmost non-zero bit started from the end of the integer. + * For example if we considering the unsigned integer with value 0x80000000 then SDRM_ll_getMSB will return 0 as a result. + * Or in the case if integer has value equal t 1, then SDRM_ll_getMSB will return BASICWORD_BITS_COUNT as a result. + */ +int SDRM_ll_getMSB(IN BasicWord oneWord) +{ + register BasicWord mask = (1 << (BASICWORD_BITS_COUNT-1)); + int nPos = 0; + + if ( !oneWord ) { + return BASICWORD_BITS_COUNT; + } + + while (!(oneWord & mask)) + { + nPos++; + mask >>= 1; + } + + return nPos; +} + +/** + * @fn SDRM_ll_bit_getBitValue + * @brief Return one bit value in the large integer number. + * + * @param pOperand [in] pointer to large integer + * @param nBit [in] bit position in the large integer. + * + * @return 0 or 1 depends on actual bit value. + */ +int SDRM_ll_bit_getBitValue(IN BasicWord *pOperand, IN BasicWord nBit) +{ + BasicWord uOrdNum = nBit / BASICWORD_BITS_COUNT; + BasicWord uBitNum = nBit % BASICWORD_BITS_COUNT; + + return (pOperand[uOrdNum] >> uBitNum) & 0x1; +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_bit_getBitsValue(IN const BasicWord *pOperand, IN BasicWord uStartBit, IN BasicWord uBitsCount) +{ + int nValueLen, i; + BasicWord uValue = 0; + BasicWord uStartOrdNum = uStartBit / BASICWORD_BITS_COUNT; /* number of ords */ + BasicWord uStartBitNum = uStartBit % BASICWORD_BITS_COUNT; /* number of bits in remainder BasicWord */ + + if((nValueLen = (int)(uStartBitNum + 1 - uBitsCount)) >= 0) + { + for(i = uStartBitNum; i >= nValueLen; i--) + { + uValue = (BasicWord)(((pOperand[uStartOrdNum] >> i) & 1) | (uValue << 1)); + } + } + else + { + nValueLen = uBitsCount - uStartBitNum - 1; + for(i = uStartBitNum; i >= 0; i--) + { + uValue = (BasicWord)(((pOperand[uStartOrdNum] >> i) & 1) | (uValue << 1)); + } + + uStartOrdNum--; + nValueLen = BASICWORD_BITS_COUNT - nValueLen; + for(i = BASICWORD_BITS_COUNT - 1; i >= nValueLen; i--) + { + uValue = (BasicWord)(((pOperand[uStartOrdNum] >> i) & 1) | (uValue << 1)); + } + } + + do + { + if(0 != (uValue & 1)) + { + break; + } + uValue >>= 1; + } + while(1); + + uValue = uValue >> 1; /* get rid of least significant bit */ + + return uValue; +} + +/** + * @fn SDRM_ll_Add + * @brief Add two large unsigned integers that have the same size. + * + * @param pFirstOperand [in] pointer to first large integer + * @param pSecondOperand [in] pointer to second large integer + * @param uOperandsLength [in] length of the operands in words + * @param pResult [out] pointer to result of subtraction + * + * @return carry if so. + */ +int SDRM_ll_Add(IN const BasicWord *pFirstOperand, + IN const BasicWord *pSecondOperand, + IN BasicWord uOperandsLength, + OUT BasicWord *pResult) +{ + unsigned i = 1; + register BasicWord rh; + register BasicWord fo, so, rl; + + fo = *pFirstOperand++; + so = *pSecondOperand++; + _add_add_(fo,so,0,rl,rh) + *pResult++ = rl; + for (; i < uOperandsLength; i++) + { + fo = *pFirstOperand++; + so = *pSecondOperand++; + _add_add_(fo,so,rh,rl,rh) + *pResult++ = rl; + } + + return rh; +} + +/** + * @fn SDRM_ll_AddCarry + * @brief Add carry to large unsigned integer + * + * @param oneWord [in] value of carry + * @param pOperand [inout] pointer to large integer + * @param uOperandLength [in] length of the second operand in words + * + * @return carry if so. + */ +int SDRM_ll_AddCarry(IN BasicWord oneWord, IN BasicWord *pOperand, IN BasicWord uOperandLength) +{ + BasicWord i = 1; + register BasicWord ow = oneWord; + + if ((pOperand[0] += ow) >= ow) + { + return 0; + } + + while(i < uOperandLength) + { + if(++pOperand[i++] != 0) + { + return 0; + } + } + + return 1; +} + +/** + * @fn SDRM_ll_Sub + * @brief Subtract two large unsigned integers that have the same size. + * + * @param pFirstOperand [in] pointer to first large integer + * @param pSecondOperand [in] pointer to second large integer + * @param uOperandsLength [in] length of the operands in words + * @param pResult [out] pointer to result of subtraction + * + * @return borrow if so. + */ +int SDRM_ll_Sub(IN const BasicWord *pFirstOperand, + IN const BasicWord *pSecondOperand, + IN BasicWord uOperandsLength, + OUT BasicWord *pResult) +{ + register BasicWord temp, borrow = 0; + + while (uOperandsLength--) + { + temp = *pFirstOperand - *pSecondOperand - borrow; + borrow = (borrow && (*pFirstOperand == *pSecondOperand)) || (*pFirstOperand < *pSecondOperand); + *pResult++ = temp; + pFirstOperand++; + pSecondOperand++; + } + return (borrow); +} + +/** + * @fn SDRM_ll_Mul1 + * @brief Multiply large integer by one word. + * Result = oneWord*SecondOperand. + * + * @param oneWord [in] value of first multiplayer. + * @param pSecondOperand [in] pointer to large integer + * @param uSecondOperandsLength [in] length of the second operand in words + * @param pResult [out] pointer to result of multiplication + * + * @warning Routine doesn't store the last word of multiplication result, + * so we have to be carefull and take care about it after calling this function. + */ +BasicWord SDRM_ll_Mul1(IN BasicWord oneWord, + IN BasicWord *pSecondOperand, BasicWord uSecondOperandsLength, + IN OUT BasicWord *pResult) +{ + register BasicWord ow = oneWord; + register BasicWord rh, op2, r; + + op2 = *pSecondOperand++; + r = *pResult; + _mul_add_add(op2, ow, 0, 0, r, rh) + *pResult++ = r; + while ( --uSecondOperandsLength ) + { + op2 = *pSecondOperand++; + r = *pResult; + _mul_add_add(op2, ow, 0, rh, r, rh) + *pResult++ = r; + } + + return rh; +} + +/** + * @fn SDRM_ll_Mul1 + * @brief Multiply large integer by one word and add result to the another large integer. + * Result += oneWord*SecondOperand. + * + * @param oneWord [in] value of first multiplayer. + * @param pSecondOperand [in] pointer to large integer + * @param uSecondOperandsLength [in] length of the second operand in words + * @param pResult [inout] pointer to result of multiplication + * + * @warning Routine doesn't store the last word of multiplication result, + * so we have to be carefull and take care about it after calling this function. + */ +BasicWord SDRM_ll_MulAdd1(IN BasicWord oneWord, + IN BasicWord *pSecondOperand, BasicWord uSecondOperandsLength, + IN OUT BasicWord *pResult) +{ + register BasicWord ow = oneWord; + register BasicWord rh, op2, r; + + op2 = *pSecondOperand++; + r = *pResult; + _mul_add_add(op2, ow, r, 0, r, rh) + *pResult++ = r; + while (--uSecondOperandsLength) + { + op2 = *pSecondOperand++; + r = *pResult; + _mul_add_add(op2, ow, r, rh, r, rh) + *pResult++ = r; + } + + return rh; +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_MulAdd(IN BasicWord *pFirstOperand, IN BasicWord uFirstOperandsLength, + IN BasicWord *pSecondOperand, IN BasicWord uSecondOperandsLength, + OUT BasicWord *pResult) +{ + while (uFirstOperandsLength--) + { + *(pResult+uSecondOperandsLength) = SDRM_ll_MulAdd1(*pFirstOperand++, pSecondOperand, uSecondOperandsLength, pResult); + pResult++; + } +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_Mul(IN BasicWord *pFirstOperand, IN BasicWord uFirstOperandsLength, + IN BasicWord *pSecondOperand, IN BasicWord uSecondOperandsLength, + OUT BasicWord *pResult) +{ + *(pResult+uSecondOperandsLength) = SDRM_ll_Mul1(*pFirstOperand++, pSecondOperand, uSecondOperandsLength, pResult); + while (--uFirstOperandsLength) + { + *(pResult+uSecondOperandsLength) = SDRM_ll_MulAdd1(*pFirstOperand++, pSecondOperand, uSecondOperandsLength, pResult); + pResult++; + } +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_Square(IN BasicWord *pOperand, IN BasicWord uOperandLength, OUT BasicWord *pResult) +{ + BasicWord i; + BasicWord j; + BasicWord t; + BasicWord len; + + /* Compute the product of diagonal elements */ + for(i = 0; i < uOperandLength; i++) + { + BasicWord rl, rh, op; + op = pOperand[i]; + _mul_add_add(op,op,0,0,rl,rh) + pResult[i * 2] = rl; + pResult[i * 2 + 1] = rh; + } + + /* Divide the result by 2 */ + SDRM_ll_bit_RShift(pResult, (BasicWord)(uOperandLength << 1), 1); + + /* Add the half of the rest part of squaring to the half of diagonal */ + i = 0; + j = 0; + len = uOperandLength; + while (--len) + { + t = SDRM_ll_MulAdd1(pOperand[i], pOperand+i+1, (BasicWord)len, pResult + j + 1); + SDRM_ll_AddCarry(t, pResult+len+j+1, len+1); + j+=2; + i++; + } + + /* Multiply the result by 2 */ + SDRM_ll_bit_LShift(pResult, (BasicWord)(uOperandLength << 1), 1); + + /* Restore the least significant bit */ + if((pOperand[0] & 0x1L) != 0) + { + pResult[0] |= 0x1L; + } +} + +/** + * @fn SDRM_ll_Rem + * @brief Compute reminder of division. + * + * @warning This is a temporary solution. It has been created mostly for testing purposes. + */ +int SDRM_ll_Rem(IN BasicWord *pOperand, IN BasicWord uOperandLengthInBytes, + IN BasicWord *pModule, IN BasicWord uModuleLengthInBytes, + OUT BasicWord *pResult) +{ + BasicWord nWordX = DIV_BY_ORD_BYTES_COUNT(uOperandLengthInBytes); + BasicWord nWordP; + BasicWord *pTempResult; + + nWordX = SDRM_ll_getMSW(pOperand, nWordX) + 1; + nWordP = SDRM_ll_getMSW(pModule, nWordX) + 1; + + // Krishna + pTempResult = (BasicWord*) calloc(nWordX+1,BASICWORD_BYTES_COUNT); + if (!pTempResult) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_ll_Copy(pTempResult, pOperand, nWordX); + + SDRM_DWD_Classical_REDC(pTempResult, nWordX, pModule, nWordP); + + SDRM_ll_Copy(pResult, pTempResult, nWordP); + + free(pTempResult); + + return 0; +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_mont_Inverse(OUT BasicWord *out, IN BasicWord oneWord) +{ + /* + t = m^(-1) mod b + m^(-1) = t*(2-m*t) mod (b^2) + + So we are just using some simple iteration t <- t*(2-m*t) and check the condition that t*m == 1 mod b. + */ + BasicWord t = oneWord; + BasicWord r = t*t; + + while (r != 1) + { + t = t*(2 - r); + r = oneWord*t; + + if (!(r) && !(t)) + { + return -1; + } + } + + *out = (BasicWord)(-t); + + return 0; +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +void SDRM_ll_mont_Rem(IN OUT BasicWord *pFirstOperand, + IN BasicWord *pModule, + IN BasicWord uModuleLength, + IN BasicWord inv) +{ + BasicWord lp; /* leftmost non-zero element */ + BasicWord temp, temp_longs; + BasicWord carry = 0; + + temp_longs = uModuleLength; + lp = SDRM_ll_getMSW(pModule, uModuleLength) + 1; + do + { + temp = inv * pFirstOperand[0]; + temp = SDRM_ll_MulAdd1(temp, pModule, lp, pFirstOperand); + carry += SDRM_ll_AddCarry(temp, pFirstOperand+uModuleLength, temp_longs); + pFirstOperand++; + } + while(--temp_longs); + + while(carry) + { + if(SDRM_ll_Sub(pFirstOperand, pModule, uModuleLength, pFirstOperand)) { + carry--; + } + } + + while(SDRM_ll_Cmp(pFirstOperand, pModule, uModuleLength) >= 0) + { + SDRM_ll_Sub(pFirstOperand, pModule, uModuleLength, pFirstOperand); + } +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_mont_Square(IN BasicWord *pFirstOperand, + IN BasicWord *pModule, + IN BasicWord uModuleLength, + IN BasicWord Inv, + OUT BasicWord *pResult) +{ + pResult[uModuleLength * 2] = 0; + + /* Compute square */ + SDRM_ll_Square(pFirstOperand, uModuleLength, pResult); + /* Compute the modulo by the Montgomery */ + SDRM_ll_mont_Rem(pResult, pModule, uModuleLength, Inv); + + /* Note: The next step for making toolkit faster is to redesign Montgomery functions and remove all memory allocation + and copying from there. That means that exponentiation routine should be redesigne as well. */ + memcpy(pFirstOperand, pResult + uModuleLength, MUL_BY_ORD_BYTES_COUNT(uModuleLength)); + return CRYPTO_SUCCESS; +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ +int SDRM_ll_mont_Mul(IN BasicWord *pFirstOperand, + IN BasicWord *pSecondOperand, + IN BasicWord *pModule, + IN BasicWord uModuleLengthInBytes, + IN BasicWord Inv, + OUT BasicWord *pResult) +{ + BasicWord P_longs; /* number of longs in P, X and Y */ + BasicWord lx, ly; /* leftmost non-zero elements */ + BasicWord *XY; /* pointer to product result */ + + P_longs = DIV_BY_ORD_BYTES_COUNT(uModuleLengthInBytes); + XY = (BasicWord*)calloc(2 * P_longs + 1, BASICWORD_BYTES_COUNT); + if(!XY) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + /* Find leftmost non-zero elements */ + lx = SDRM_ll_getMSW(pFirstOperand, P_longs) + 1; + ly = SDRM_ll_getMSW(pSecondOperand, P_longs) + 1; + /* Compute the product of FirstOperand and SecondOperand */ + SDRM_ll_MulAdd(pFirstOperand, lx, pSecondOperand, ly, XY); + /* Compute the modulo by the Montgomery */ + SDRM_ll_mont_Rem(XY, pModule, P_longs, Inv); + + /* Note: The next step for making toolkit faster is to redesign Montgomery functions and remove all memory allocation + and copying from there. That means that exponentiation routine should be redesigne as well. */ + memcpy(pResult, XY + P_longs, uModuleLengthInBytes); + free(XY); + return CRYPTO_SUCCESS; +} + +/** + * @fn [Mandatory] Function name + * @brief [Mandatory] Description of major features and algorithms + * + * @param [Optional] description of parameters ([one among in, out, inout]) + * + * @return [Optional] description of return value + * @warning [Optional] constraints or notices + * @see [Optional] related information + */ + +#define _win_pval(i) (BasicWord*)(temp_1 + (i) * uOrdsP) +int SDRM_ll_ExpMod( IN BasicWord *pBase, IN BasicWord uBaseLengthInBytes, + IN BasicWord *pExponent, IN BasicWord uExponentLengthInBytes, + IN BasicWord *pModule, IN BasicWord uModuleLengthInBytes, + OUT BasicWord *pResult) +{ + int nStatus = CRYPTO_SUCCESS; + BasicWord *temp_1, inv; + BasicWord *m_temp, *m_sq; + int n_mem, win_len; + BasicWord uOrdsY, uOrdsP; + int i, j, k, eb = 0; + BasicWord nIndex; + int ly; + /* The values of num_squar array given below represents the lengths of particular window values in bits */ + /* We have to take into account that we store only odd values. */ + /* window values -> 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, etc... */ + /* num_squar -> 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, etc... */ + int num_squar[32] = {1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,}; + + uOrdsY = DIV_BY_ORD_BYTES_COUNT(uExponentLengthInBytes); + uOrdsP = DIV_BY_ORD_BYTES_COUNT(uModuleLengthInBytes); + /* Find the leftmost non-zero element of modulo */ + if(-1 == SDRM_ll_getMSW(pModule, uOrdsP)) { + return CRYPTO_INVALID_ARGUMENT; + } + /* Find the leftmost non-zero element of exponent */ + ly = SDRM_ll_getMSW(pExponent, uOrdsY); + + /* if exponent equal to 0 result is 1 */ + if(-1 == ly) + { + memset(pResult, 0, uModuleLengthInBytes); + pResult[0] = 1; + return CRYPTO_SUCCESS; + } + + /* Find the leftmost non-zero bit in this element */ + eb = SDRM_ll_getMSB(pExponent[ly]); + + /* Choose window length */ + k = BASICWORD_BITS_COUNT * (ly + 1) - eb - 1; + if(k < 512) + { + win_len = 4; + } + else if((k >= 512) && (k < 1024)) + { + win_len = 5; + } + else + { /* for any k >= 1024 */ + win_len = 6; + } + + /* Obtain number of precomputed elements */ + n_mem = (1 << (win_len - 1)) + 1; + /* Allocate storage for precomputetd values */ + temp_1 = (BasicWord*)calloc((n_mem + 1) * uOrdsP, BASICWORD_BYTES_COUNT); + if (!temp_1) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + /* Allocate temporary storages */ + m_temp = (BasicWord*)calloc(2 * uOrdsP + 1, BASICWORD_BYTES_COUNT); + if (!m_temp) + { + free(temp_1); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + m_sq = (BasicWord*)malloc(2 * uModuleLengthInBytes + BASICWORD_BYTES_COUNT); + if (!m_sq) + { + free(temp_1); + free(m_temp); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + do + { + /* Convert Base to Montgomery form */ + inv = *pModule; + if (SDRM_ll_mont_Inverse(&inv, inv) != 0) + { + nStatus = CRYPTO_INVERSE_NOT_EXIST; + break; + } + /* Move n up "mlen" words into a */ + /* Actually we obtain X*R where R is Montgomery reduction coefficient */ + memcpy(m_temp + uOrdsP, pBase, uBaseLengthInBytes); + + /* Do the division - dump the quotient in the high-order words */ + if((nStatus = SDRM_ll_Rem(m_temp, (BasicWord)(uBaseLengthInBytes + uModuleLengthInBytes), pModule, uModuleLengthInBytes, temp_1)) != CRYPTO_SUCCESS) + { + break; + } + + /* After this operation we will obtain X*R mod P */ + memcpy(m_temp, temp_1, uModuleLengthInBytes); + + /* Initialization */ + /* Compute X^2*R mod P */ + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + memcpy(_win_pval(n_mem), m_temp, uModuleLengthInBytes); + + /* We have to calculate X^3, X^5 and so on ... */ + /* For making that we just use previously calculated value of X^2 and use it as multiplayer consecutively. */ + /* element (0) <- X*R mod P */ + /* element (1) <- X^3*R = element (0) * X^2*R mod P */ + /* element (2) <- X^5*R = element (1) * X^2*R mod P */ + /* element (3) <- X^7*R = element (2) * X^2*R mod P */ + /* element (4) <- ... */ + for(i = 1; i < n_mem; i++) + { + SDRM_ll_mont_Mul(_win_pval(i - 1), _win_pval(n_mem), pModule, uModuleLengthInBytes, inv, _win_pval(i)); + } + + /* OK, now let compute R mod P */ + memset(m_temp, 0, 2 * uModuleLengthInBytes + 1); + m_temp[uOrdsP] = 1; + if((nStatus = SDRM_ll_Rem(m_temp, (BasicWord)(uModuleLengthInBytes + BASICWORD_BYTES_COUNT), pModule, uModuleLengthInBytes, m_temp)) != CRYPTO_SUCCESS) { + break; + } + + /* Compute the exponent */ + for(i = k; i >= win_len-1; ) + { + /* Note: I don't like this solution, but it was easy and from that point of view was suitable for short development cycle. + During further refactoring exponent bits processing should be changed in a way that makes possible to perform + all computations inside of the one cycle. See some additional related comments right after the body of this cycle.*/ + + /* Find next suitable bits for computations */ + nIndex = (BasicWord)SDRM_ll_bit_getBitsValue(pExponent, (BasicWord)i, (BasicWord)win_len); + + /* Square the intermediate result */ + for(j = 0; j < num_squar[nIndex]; j++) + { + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + } + + /* Multiply with the precomputed data */ + SDRM_ll_mont_Mul(m_temp, _win_pval(nIndex), pModule, uModuleLengthInBytes, inv, m_temp); + + /* Square (win_len - num_squar) times */ + for(j = 0 ; j < win_len - num_squar[nIndex]; j++) + { + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + } + + i -= win_len; + + /* perform squering till first nonzero bit */ + while((i >= win_len - 1) && !SDRM_ll_bit_getBitValue(pExponent, (BasicWord)i)) + { + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + i--; + } + } + + /* Note: Actually it would be batter to perform remeined last bits processing inside of the exponent computation main cycle. + So the next refactoring step is to modify this routine and make things in that way. */ + + /* if we still have some bit(s) ... */ + /* perform squering till first nonzero bit */ + while((i >= 0) && !SDRM_ll_bit_getBitValue(pExponent, (BasicWord)i)) + { + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + i--; + } + + /* if we still have some nonzero bit(s) ... */ + if(i >= 0) + { + nIndex = (BasicWord)SDRM_ll_bit_getBitsValue(pExponent, (BasicWord)i, (BasicWord)(i + 1)); + for(j = 0; j < num_squar[nIndex]; j++) + { + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + } + + /* Multiply with precomputed data*/ + SDRM_ll_mont_Mul(m_temp, _win_pval(nIndex), pModule, uModuleLengthInBytes, inv, m_temp); + + /* Square (win_len - num_squar) times */ + for(j = 0 ; j <= i - num_squar[nIndex]; j++) + { + SDRM_ll_mont_Square(m_temp, pModule, uOrdsP, inv, m_sq); + } + } + + /* Convert the result out of Montgomery form */ + SDRM_ll_mont_Rem(m_temp, pModule, uOrdsP, inv); + memcpy(pResult, m_temp + uOrdsP, uModuleLengthInBytes); + /* This is the tricky place :) Actually we have (X*R+R) mod P. */ + /* So we just need to remove that additional R */ + pResult[0]--; + + break; /* always break this loop */ + } + while(0); + + free(temp_1); + free(m_temp); + free(m_sq); + + return nStatus; +} diff --git a/ssflib/dep/cryptocore/source/base/cc_hash.c b/ssflib/dep/cryptocore/source/base/cc_hash.c new file mode 100755 index 0000000..0ee058c --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_hash.c @@ -0,0 +1,578 @@ +/** + * \file hash.c + * @brief hash API function + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/08 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_hash.h" +#include "cc_sha1.h" +#include "cc_sha2.h" +#include "cc_md5.h" + +//////////////////////////////////////////////////////////////////////////// +// functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_SHA1_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_init(CryptoCoreContainer *crt) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA1_Init(crt->ctx->sha1ctx); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA1_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]cc_u8-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA1_Update(crt->ctx->sha1ctx, msg, msglen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA1_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_final(CryptoCoreContainer *crt, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA1_Final(crt->ctx->sha1ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA1_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA1_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA1_Init(crt->ctx->sha1ctx); + SDRM_SHA1_Update(crt->ctx->sha1ctx, msg, msglen); + SDRM_SHA1_Final(crt->ctx->sha1ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA224_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_init(CryptoCoreContainer *crt) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA224_Init(crt->ctx->sha224ctx); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA224_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA224_Update(crt->ctx->sha224ctx, msg, msglen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA224_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_final(CryptoCoreContainer *crt, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (output == NULL)) { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA224_Final(crt->ctx->sha224ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA224_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA224_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA224_Init(crt->ctx->sha224ctx); + SDRM_SHA224_Update(crt->ctx->sha224ctx, msg, msglen); + SDRM_SHA224_Final(crt->ctx->sha224ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA256_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_init(CryptoCoreContainer *crt) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA256_Init(crt->ctx->sha256ctx); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA256_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA256_Update(crt->ctx->sha256ctx, msg, msglen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA256_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_final(CryptoCoreContainer *crt, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (output == NULL)) { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA256_Final(crt->ctx->sha256ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA256_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA256_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA256_Init(crt->ctx->sha256ctx); + SDRM_SHA256_Update(crt->ctx->sha256ctx, msg, msglen); + SDRM_SHA256_Final(crt->ctx->sha256ctx, output); + + return CRYPTO_SUCCESS; +} + +#ifndef _OP64_NOTSUPPORTED + +/* + * @fn SDRM_SHA384_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_init(CryptoCoreContainer *crt) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA384_Init(crt->ctx->sha384ctx); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA384_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA384_Update(crt->ctx->sha384ctx, msg, msglen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA384_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_final(CryptoCoreContainer *crt, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA384_Final(crt->ctx->sha384ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA384_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA384_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA384_Init(crt->ctx->sha384ctx); + SDRM_SHA384_Update(crt->ctx->sha384ctx, msg, msglen); + SDRM_SHA384_Final(crt->ctx->sha384ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA512_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_init(CryptoCoreContainer *crt) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA512_Init(crt->ctx->sha512ctx); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA512_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA512_Update(crt->ctx->sha512ctx, msg, msglen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA512_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_final(CryptoCoreContainer *crt, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA512_Final(crt->ctx->sha512ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SHA512_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_SHA512_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_SHA512_Init(crt->ctx->sha512ctx); + SDRM_SHA512_Update(crt->ctx->sha512ctx, msg, msglen); + SDRM_SHA512_Final(crt->ctx->sha512ctx, output); + + return CRYPTO_SUCCESS; +} + +#endif //_OP64_NOTSUPPORTED + +/* + * @fn SDRM_MD5_init + * @brief initialize CryptoCoreContainer context + * + * @param crt [out]CryptoCoreContainer context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_init(CryptoCoreContainer *crt) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_MD5_Init(crt->ctx->md5ctx); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_MD5_update + * @brief process a message block + * + * @param crt [out]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_MD5_Update(crt->ctx->md5ctx, msg, msglen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_MD5_final + * @brief get hashed message + * + * @param crt [in]CryptoCoreContainer context + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_final(CryptoCoreContainer *crt, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_MD5_Final(crt->ctx->md5ctx, output); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_MD5_hash + * @brief get hashed message from message + * + * @param crt [in]CryptoCoreContainer context + * @param msg [in]message + * @param msglen [in]byte-length of msg + * @param output [out]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_MD5_hash(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msglen, cc_u8 *output) +{ + if ((crt == NULL) || (crt->ctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_MD5_Init(crt->ctx->md5ctx); + SDRM_MD5_Update(crt->ctx->md5ctx, msg, msglen); + SDRM_MD5_Final(crt->ctx->md5ctx, output); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/base/cc_md5.c b/ssflib/dep/cryptocore/source/base/cc_md5.c new file mode 100755 index 0000000..e11e034 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_md5.c @@ -0,0 +1,267 @@ +/* + * MD5 implementation + */ + +#include "cc_md5.h" + +//Constants for MD5Transform routine. +static cc_u8 S[4][4] = { + {7, 12, 17, 22}, + {5, 9, 14, 20}, + {4, 11, 16, 23}, + {6, 10, 15, 21} +}; + +static void SDRM_MD5Transform(cc_u32 [4], const unsigned char*); +static void SDRM_Encode (unsigned char *, cc_u32 *, cc_u32); +static void SDRM_Decode (cc_u32 *, const unsigned char *, cc_u32); + +static unsigned char PADDING[64] = {0x80, 0,}; + +/* F, G, H and I are basic MD5 functions. + */ +//#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +//#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +//#define H(x, y, z) ((x) ^ (y) ^ (z)) +//#define I(x, y, z) ((y) ^ ((x) | (~z))) + +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) F(z, x, y) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (cc_u32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ +} +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (cc_u32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ +} +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (cc_u32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ +} +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (cc_u32)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ +} + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void SDRM_MD5_Init(SDRM_MD5Context *ctx) +{ + ctx->count[0] = 0; + ctx->count[1] = 0; + + // Load magic initialization constants. + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xefcdab89; + ctx->state[2] = 0x98badcfe; + ctx->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void SDRM_MD5_Update(SDRM_MD5Context *ctx, cc_u8* input, cc_u32 inputLen) +{ + cc_u32 i, idx, partLen; + + /* Compute number of bytes mod 64 */ + idx = (cc_u32)((ctx->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((ctx->count[0] += ((cc_u32)inputLen << 3)) < ((cc_u32)inputLen << 3)) + { + ctx->count[1]++; + } + + ctx->count[1] += ((cc_u32)inputLen >> 29); + + partLen = 64 - idx; + + // Transform as many times as possible. + if (inputLen >= partLen) + { + memcpy(&ctx->buffer[idx], input, partLen); + SDRM_MD5Transform(ctx->state, ctx->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + { + SDRM_MD5Transform(ctx->state, &input[i]); + } + + idx = 0; + } + else + { + i = 0; + } + + /* Buffer remaining input */ + memcpy(&ctx->buffer[idx], &input[i], inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void SDRM_MD5_Final(SDRM_MD5Context *ctx, cc_u8* digest) +{ + unsigned char bits[8]; + cc_u32 idx, padLen; + + /* Save number of bits */ + SDRM_Encode(bits, ctx->count, 8); + + // Pad out to 56 mod 64. + idx = (cc_u32)((ctx->count[0] >> 3) & 0x3f); + padLen = (idx < 56) ? (56 - idx) : (120 - idx); + SDRM_MD5_Update (ctx, PADDING, padLen); + + /* Append length (before padding) */ + SDRM_MD5_Update (ctx, bits, 8); + + /* Store state in digest */ + SDRM_Encode (digest, ctx->state, 16); + + // Zeroize sensitive information. + memset(ctx, 0, sizeof(*ctx)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void SDRM_MD5Transform (cc_u32 state[4], const unsigned char* block) +{ + cc_u32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + SDRM_Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S[0][0], 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S[0][1], 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S[0][2], 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S[0][3], 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S[0][0], 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S[0][1], 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S[0][2], 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S[0][3], 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S[0][0], 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S[0][1], 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S[0][2], 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S[0][3], 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S[0][0], 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S[0][1], 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S[0][2], 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S[0][3], 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S[1][0], 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S[1][1], 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S[1][2], 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S[1][3], 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S[1][0], 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S[1][1], 0x02441453); /* 22 */ + GG (c, d, a, b, x[15], S[1][2], 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S[1][3], 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S[1][0], 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S[1][1], 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S[1][2], 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S[1][3], 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S[1][0], 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S[1][1], 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S[1][2], 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S[1][3], 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S[2][0], 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S[2][1], 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S[2][2], 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S[2][3], 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S[2][0], 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S[2][1], 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S[2][2], 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S[2][3], 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S[2][0], 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S[2][1], 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S[2][2], 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S[2][3], 0x04881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S[2][0], 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S[2][1], 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S[2][2], 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S[2][3], 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S[3][0], 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S[3][1], 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S[3][2], 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S[3][3], 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S[3][0], 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S[3][1], 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S[3][2], 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S[3][3], 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S[3][0], 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S[3][1], 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S[3][2], 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S[3][3], 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S[3][0], 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S[3][1], 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S[3][2], 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S[3][3], 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + //Zeroize sensitive information. + memset (x, 0, sizeof (x)); +} + +/* Encodes input (cc_u4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void SDRM_Encode (unsigned char *output, cc_u32 *input, cc_u32 len) +{ + cc_u32 i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[j ] = (unsigned char)((input[i] ) & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void SDRM_Decode (cc_u32 *output, const unsigned char *input, cc_u32 len) +{ + cc_u32 i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + { + output[i] = ( + (((cc_u32)input[j] ) ) | + (((cc_u32)input[j + 1]) << 8) | + (((cc_u32)input[j + 2]) << 16) | + (((cc_u32)input[j + 3]) << 24)); + } +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/base/cc_moo.c b/ssflib/dep/cryptocore/source/base/cc_moo.c new file mode 100755 index 0000000..95c465c --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_moo.c @@ -0,0 +1,487 @@ +/** + * \file moo.c + * @brief implementation of mode of operations + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/08/04 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_moo.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_ECB_Enc + * @brief Encrypt a block with ECB mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_ECB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key) +{ + switch(Algorithm) + { + case ID_AES128 : + SDRM_rijndaelEncrypt((cc_u32*)(void*)key, 10, in, out); + return CRYPTO_SUCCESS; + case ID_AES192 : + SDRM_rijndaelEncrypt((cc_u32*)(void*)key, 12, in, out); + return CRYPTO_SUCCESS; + case ID_AES256 : + SDRM_rijndaelEncrypt((cc_u32*)(void*)key, 14, in, out); + return CRYPTO_SUCCESS; + case ID_DES : + return SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, in, out); + case ID_TDES : + return SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, in, out); + default : + break; + } + + return CRYPTO_INVALID_ARGUMENT; +} + +/* + * @fn SDRM_ECB_Dec + * @brief Decrypt a block with ECB mode + * + * @param Algorithm [in]algorithm + * @param out [out]plain text block + * @param in [in]cipher text block + * @param key [in]user key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_ECB_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key) +{ + switch(Algorithm) + { + case ID_AES128 : + SDRM_rijndaelDecrypt((const cc_u32*)(void*)key, 10, in, out); + return CRYPTO_SUCCESS; + case ID_AES192 : + SDRM_rijndaelDecrypt((const cc_u32*)(void*)key, 12, in, out); + return CRYPTO_SUCCESS; + case ID_AES256 : + SDRM_rijndaelDecrypt((const cc_u32*)(void*)key, 14, in, out); + return CRYPTO_SUCCESS; + case ID_DES : + return SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, in, out); + case ID_TDES : + return SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, in, out); + default : + break; + } + + return CRYPTO_INVALID_ARGUMENT; +} + +/* + * @fn SDRM_CBC_Enc + * @brief Encrypt a block with CBC mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CBC_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) +{ + int i; + + switch(Algorithm) + { + case ID_AES128 : + for (i = 0; i < 16; i++) + { + IV[i] ^= in[i]; + } + + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 10, IV, out); + + memcpy(IV, out, 16); + + break; + case ID_AES192 : + for (i = 0; i < 16; i++) + { + IV[i] ^= in[i]; + } + + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 12, IV, out); + + memcpy(IV, out, 16); + + break; + case ID_AES256 : + for (i = 0; i < 16; i++) + { + IV[i] ^= in[i]; + } + + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 14, IV, out); + + memcpy(IV, out, 16); + + break; + case ID_DES : + for (i = 0; i < 8; i++) + { + IV[i] ^= in[i]; + } + + SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + + memcpy(IV, out, 8); + + break; + case ID_TDES : + for (i = 0; i < 8; i++) + { + IV[i] ^= in[i]; + } + + SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + + memcpy(IV, out, 8); + + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CBC_Dec + * @brief Decrypt a block with CBC mode + * + * @param Algorithm [in]algorithm + * @param out [out]plain text block + * @param in [in]cipher text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CBC_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV){ + int i, BlockLen; + cc_u8 buf[16]; + + switch(Algorithm) + { + case ID_AES128 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelDecrypt((const cc_u32*)(void*)key, 10, in, out); + break; + case ID_AES192 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelDecrypt((const cc_u32*)(void*)key, 12, in, out); + break; + case ID_AES256 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelDecrypt((const cc_u32*)(void*)key, 14, in, out); + break; + case ID_DES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, in, out); + break; + case ID_TDES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, in, out); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + for (i = 0; i < BlockLen; i++) + { + out[i] ^= IV[i]; + } + + memcpy(IV, buf, BlockLen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CFB_Enc + * @brief Encrypt a block with CFB mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CFB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) +{ + int i, BlockLen; + cc_u8 buf[16]; + + switch(Algorithm) + { + case ID_AES128 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 10, IV, out); + break; + case ID_AES192 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 12, IV, out); + break; + case ID_AES256 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 14, IV, out); + break; + case ID_DES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + case ID_TDES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + for (i = 0; i < BlockLen; i++) + { + out[i] ^= buf[i]; + } + + memcpy(IV, out, BlockLen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CFB_Dec + * @brief Decrypt a block with CFB mode + * + * @param Algorithm [in]algorithm + * @param out [out]plain text block + * @param in [in]cipher text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CFB_Dec(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) +{ + int i, BlockLen; + cc_u8 buf[16]; + + switch(Algorithm) + { + case ID_AES128 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 10, IV, out); + break; + case ID_AES192 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 12, IV, out); + break; + case ID_AES256 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 14, IV, out); + break; + case ID_DES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + case ID_TDES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + for (i = 0; i < BlockLen; i++) + { + out[i] ^= buf[i]; + } + + memcpy(IV, buf, BlockLen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_OFB_Enc + * @brief Encrypt a block with OFB mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_OFB_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV) +{ + int i, BlockLen; + cc_u8 buf[16]; + + switch(Algorithm) + { + case ID_AES128 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 10, IV, out); + break; + case ID_AES192 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 12, IV, out); + break; + case ID_AES256 : + BlockLen = 16; + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 14, IV, out); + break; + case ID_DES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + case ID_TDES : + BlockLen = 8; + memcpy(buf, in, BlockLen); + SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + memcpy(IV, out, BlockLen); + + for (i = 0; i < BlockLen; i++) + { + out[i] ^= buf[i]; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTR_Enc + * @brief Encrypt a block with CTR mode + * + * @param Algorithm [in]algorithm + * @param out [out]cipher text block + * @param in [in]plain text block + * @param key [in]user key + * @param IV [in]initial vector + * @param counter [in] + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_INVALID_ARGUMENT if parameter is invalid + */ +int SDRM_CTR_Enc(int Algorithm, cc_u8 *out, cc_u8 *in, cc_u8 *key, cc_u8 *IV, cc_u32 counter) +{ + int i, BlockLen; + cc_u8 buf[16]; + + switch(Algorithm) + { + case ID_AES128 : + BlockLen = 16; + IV[12] = (cc_u8)(0xff & (counter >> 24)); + IV[13] = (cc_u8)(0xff & (counter >> 16)); + IV[14] = (cc_u8)(0xff & (counter >> 8 )); + IV[15] = (cc_u8)(0xff & (counter )); + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 10, IV, out); + break; + case ID_AES192 : + BlockLen = 16; + IV[12] = (cc_u8)(0xff & (counter >> 24)); + IV[13] = (cc_u8)(0xff & (counter >> 16)); + IV[14] = (cc_u8)(0xff & (counter >> 8 )); + IV[15] = (cc_u8)(0xff & (counter )); + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 12, IV, out); + break; + case ID_AES256 : + BlockLen = 16; + IV[12] = (cc_u8)(0xff & (counter >> 24)); + IV[13] = (cc_u8)(0xff & (counter >> 16)); + IV[14] = (cc_u8)(0xff & (counter >> 8 )); + IV[15] = (cc_u8)(0xff & (counter )); + memcpy(buf, in, BlockLen); + SDRM_rijndaelEncrypt((const cc_u32*)(void*)key, 14, IV, out); + break; + case ID_DES : + BlockLen = 8; + IV[4] = (cc_u8)(0xff & (counter >> 24)); + IV[5] = (cc_u8)(0xff & (counter >> 16)); + IV[6] = (cc_u8)(0xff & (counter >> 8 )); + IV[7] = (cc_u8)(0xff & (counter )); + memcpy(buf, in, BlockLen); + SDRM_DES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + case ID_TDES : + BlockLen = 8; + IV[4] = (cc_u8)(0xff & (counter >> 24)); + IV[5] = (cc_u8)(0xff & (counter >> 16)); + IV[6] = (cc_u8)(0xff & (counter >> 8 )); + IV[7] = (cc_u8)(0xff & (counter )); + memcpy(buf, in, BlockLen); + SDRM_TDES_Encryption((cc_u32(*)[2])(void*)key, IV, out); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + for (i = 0; i < BlockLen; i++) + { + out[i] ^= buf[i]; + } + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/base/cc_pkcs1_v21.c b/ssflib/dep/cryptocore/source/base/cc_pkcs1_v21.c new file mode 100755 index 0000000..53f5845 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_pkcs1_v21.c @@ -0,0 +1,1068 @@ +/** + * \file pkcs1_v21.c + * @brief PKCS#1 V1.5, V2.0(RSAES-OAEP), V2.1(RSASSA-PSS) Implemetation + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/20 + * Note : Edited for Big-Endian Machine support, 2008/12/16 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_pkcs1_v21.h" +#include "cc_md5.h" +#include "cc_sha1.h" +#include "cc_sha2.h" +#include "cc_ANSI_x931.h" + +////////////////////////////////////////////////////////////////////////// +// Functions +////////////////////////////////////////////////////////////////////////// +static int SDRM_MGF1(int HASH_Algorithm, cc_u8* mask, cc_u8* pbSeed, cc_u32 SeedLen, cc_u32 dMaskLen); + +/* +* @fn int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +* @brief RSAES PKCS#1 v1.5 enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +{ + cc_u8 Si_ANSI_X9_31[SDRM_X931_SEED_SIZ]; + cc_u32 i; + + if (mLen > k - 11) + { + return CRYPTO_MSG_TOO_LONG; + } + + EM[0] = 0x00; + EM[1] = 0x02; + + for (i = 0; i < 16; i++) + { + Si_ANSI_X9_31[i] = ((rand() << 16) + rand()) & 0xff; + } + + srand(time(NULL)); + + SDRM_RNG_X931(Si_ANSI_X9_31, (k - mLen - 3) * 8, &EM[2]); + + EM[k - mLen - 1] = 0x00; + + for (i = 2; i < (k - mLen - 1); i++) + { + if (EM[i] == 0) + { + EM[i--] = (cc_u8)(((rand() << 16) + rand()) & 0xff); + continue; + } + } + + memcpy(EM + k - mLen, m, mLen); + + memset(Si_ANSI_X9_31, 0x00, 16); + + return CRYPTO_SUCCESS; +} + +/* +* @fn int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +* @brief RSAES PKCS#1 v1.5 depadding +* +* @param m [out]Depadded msg +* @param mLen [out]byte-size of m +* @param EM [in]Enpadded msg +* @param emLen [in]byte-size of EM +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_INVALID_ARGUMENT if enpadded message is out of RSA padding scheme +*/ +int SDRM_Depad_Rsaes_pkcs15(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k) +{ + cc_u32 i; + + if ((emLen == k) && (EM[0] == 0)) + { + EM = EM + 1; + emLen = emLen - 1; + } + + if ((emLen != k - 1) || (EM[0] != 0x02)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + EM = EM + 1; + emLen = emLen - 1; + + for (i = 0; i < emLen; i++) + { + if (EM[i] == 0) + { + break; + } + } + + //i : length of PS + if ((i == emLen) || (i < 8)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + EM = EM + i + 1; + emLen = emLen - i - 1; + + memmove(m, EM, emLen); + + if (mLen != NULL) + { + *mLen = emLen; + } + + return CRYPTO_SUCCESS; +} + + + +/* +* @fn int SDRM_Enpad_Rsaes_oaep(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k, int HASH_Algorithm) +* @brief RSAES OAEP enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsaes_oaep(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k, int HASH_Algorithm) +{ + cc_u8 Si_ANSI_X9_31[SDRM_X931_SEED_SIZ]; + cc_u8 *DB, *seed, *dbMask, *maskedDB, *seedMask, *maskedSeed; + cc_u32 i, dbLen; + cc_u32 hLen = 0; + + SDRM_MD5Context md5_ctx; //Hash env var + SDRM_SHA1Context sha1_ctx; //Hash env var + SDRM_SHA224Context sha224_ctx; //Hash env var + SDRM_SHA256Context sha256_ctx; //Hash env var +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context sha384_ctx; //Hash env var + SDRM_SHA512Context sha512_ctx; //Hash env var +#endif //_OP64_NOTSUPPORTED + + switch (HASH_Algorithm) + { + case ID_MD5: + hLen = SDRM_MD5_BLOCK_SIZ; + break; + case 0: + case ID_SHA1: + hLen = SDRM_SHA1_BLOCK_SIZ; + break; + case ID_SHA224 : + hLen = SDRM_SHA224_BLOCK_SIZ; + break; + case ID_SHA256: + hLen = SDRM_SHA256_BLOCK_SIZ; + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + hLen = SDRM_SHA384_BLOCK_SIZ; + break; + case ID_SHA512: + hLen = SDRM_SHA512_BLOCK_SIZ; + break; +#endif //_OP64_NOTSUPPORTED + default: + return CRYPTO_INVALID_ARGUMENT; + } + + dbLen = k - hLen - 1; + + //Memory allocation + DB = (cc_u8*)malloc(k * 2); + if (DB == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + maskedSeed = EM + 1; + maskedDB = maskedSeed + hLen; + + dbMask = DB + dbLen; + seed = dbMask + dbLen; + seedMask = seed + hLen; + + //Check message length + if (mLen > k - 2 * hLen - 2) + { + free(DB); + return CRYPTO_MSG_TOO_LONG; + } + + //Get hash of 'L' + switch (HASH_Algorithm) + { + case ID_MD5: + SDRM_MD5_Init(&md5_ctx); //Init hash function + SDRM_MD5_Final(&md5_ctx, DB); //'L' is an empty string, so get output immediately + break; + case 0: + case ID_SHA1: + SDRM_SHA1_Init(&sha1_ctx); //Init hash function + SDRM_SHA1_Final(&sha1_ctx, DB); //'L' is an empty string, so get output immediately + break; + case ID_SHA224 : + SDRM_SHA224_Init(&sha224_ctx); //Init hash function + SDRM_SHA224_Final(&sha224_ctx, DB); //'L' is an empty string, so get output immediately + break; + case ID_SHA256: + SDRM_SHA256_Init(&sha256_ctx); //Init hash function + SDRM_SHA256_Final(&sha256_ctx, DB); //'L' is an empty string, so get output immediately + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + SDRM_SHA384_Init(&sha384_ctx); //Init hash function + SDRM_SHA384_Final(&sha384_ctx, DB); //'L' is an empty string, so get output immediately + break; + case ID_SHA512: + SDRM_SHA512_Init(&sha512_ctx); //Init hash function + SDRM_SHA512_Final(&sha512_ctx, DB); //'L' is an empty string, so get output immediately + break; +#endif //_OP64_NOTSUPPORTED + default: + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + + //DB = lHash||PS||M + memset(DB + hLen, 0x00, k - mLen - 2 * hLen - 2); + DB[dbLen - mLen - 1] = 0x01; + memcpy(DB + dbLen - mLen, m, mLen); + + //Generate random seed + for (i = 0; i < 16; i++) + { + Si_ANSI_X9_31[i] = ((rand() << 16) + rand()) & 0xff; + } + + SDRM_RNG_X931(Si_ANSI_X9_31, hLen * 8, seed); + + //dbMask = MGF(Seed, dbLen), maskedDB = DB ^ dbMask + SDRM_MGF1(HASH_Algorithm, dbMask, seed, hLen, dbLen); + + for (i = 0; i < dbLen; i++) + { + maskedDB[i] = DB[i] ^ dbMask[i]; + } + + //seedMask = MGF(maskedDB, SDRM_SHA1_BLOCK_SIZ), maskedSeed = Seed ^ seedMask + SDRM_MGF1(HASH_Algorithm, seedMask, maskedDB, dbLen, hLen); + + for (i = 0; i < hLen; i++) + { + maskedSeed[i] = seed[i] ^ seedMask[i]; + } + + //EM = 0x00||maskedSeed||maskedDB + EM[0] = 0x00; + + memset(Si_ANSI_X9_31, 0x00, 16); + memset(DB, 0x00, k * 2); + free(DB); + + return CRYPTO_SUCCESS; +} + +/* +* @fn int SDRM_Depad_Rsaes_oaep(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k, int HASH_Algorithm) +* @brief RSAES PKCS#1 v1.5 depadding +* +* @param m [out]Depadded msg +* @param mLen [out]byte-size of m +* @param EM [in]Enpadded msg +* @param emLen [in]byte-size of EM +* @param k [in]byte-size of n(RSA modulus) +* @param HASH_Algorithm [in]hash algorithm id +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_INVALID_ARGUMENT if enpadded message is out of RSA padding scheme +*/ +int SDRM_Depad_Rsaes_oaep(cc_u8 *m, cc_u32* mLen, cc_u8 *EM, cc_u32 emLen, cc_u32 k, int HASH_Algorithm) +{ + cc_u8 *DB, *seed, *dbMask, *maskedDB, *seedMask, *maskedSeed; + cc_u8 hash[SDRM_SHA512_DATA_SIZE]; + cc_u32 i, dbLen; + cc_u32 hLen = 0; + + SDRM_MD5Context md5_ctx; //Hash env var + SDRM_SHA1Context sha1_ctx; //Hash env var + SDRM_SHA224Context sha224_ctx; //Hash env var + SDRM_SHA256Context sha256_ctx; //Hash env var +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context sha384_ctx; //Hash env var + SDRM_SHA512Context sha512_ctx; //Hash env var +#endif //_OP64_NOTSUPPORTED + + if ((emLen == k) && (EM[0] == 0)) + { + EM = EM + 1; + emLen = emLen - 1; + } + + if (emLen != k - 1) + { + return CRYPTO_INVALID_ARGUMENT; + } + /* + EM = EM + 1; + emLen = emLen - 1; + */ + switch (HASH_Algorithm) + { + case ID_MD5: + hLen = SDRM_MD5_BLOCK_SIZ; + break; + case 0: + case ID_SHA1: + hLen = SDRM_SHA1_BLOCK_SIZ; + break; + case ID_SHA224: + hLen = SDRM_SHA224_BLOCK_SIZ; + break; + case ID_SHA256: + hLen = SDRM_SHA256_BLOCK_SIZ; + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + hLen = SDRM_SHA384_BLOCK_SIZ; + break; + case ID_SHA512: + hLen = SDRM_SHA512_BLOCK_SIZ; + break; +#endif //_OP64_NOTSUPPORTED + default: + return CRYPTO_INVALID_ARGUMENT; + } + + dbLen = k - hLen - 1; + + //Memory allocation + DB = (cc_u8*)malloc(k * 2); + if (DB == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + maskedSeed = EM; + maskedDB = maskedSeed + hLen; + + dbMask = DB + dbLen; + seed = dbMask + dbLen; + seedMask = seed + hLen; + + //seedMask = MGF(maskedDB, SDRM_SHA1_BLOCK_SIZ), Seed = maskedSeed ^ seedMask + SDRM_MGF1(HASH_Algorithm, seedMask, maskedDB, dbLen, hLen); + for (i = 0; i < hLen; i++) + { + seed[i] = maskedSeed[i] ^ seedMask[i]; + } + + //dbMask = MGF(Seed, dbLen), DB = maskedDB ^ dbMask + SDRM_MGF1(HASH_Algorithm, dbMask, seed, hLen, dbLen); + for (i = 0; i < dbLen; i++) + { + DB[i] = maskedDB[i] ^ dbMask[i]; + } + + //Get hash of 'L' + switch (HASH_Algorithm) + { + case ID_MD5: + SDRM_MD5_Init(&md5_ctx); //Init hash function + SDRM_MD5_Final(&md5_ctx, hash); //'L' is an empty string, so get output immediately + break; + case 0: + case ID_SHA1: + SDRM_SHA1_Init(&sha1_ctx); //Init hash function + SDRM_SHA1_Final(&sha1_ctx, hash); //'L' is an empty string, so get output immediately + break; + case ID_SHA224 : + SDRM_SHA224_Init(&sha224_ctx); //Init hash function + SDRM_SHA224_Final(&sha224_ctx, hash); //'L' is an empty string, so get output immediately + break; + case ID_SHA256: + SDRM_SHA256_Init(&sha256_ctx); //Init hash function + SDRM_SHA256_Final(&sha256_ctx, hash); //'L' is an empty string, so get output immediately + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + SDRM_SHA384_Init(&sha384_ctx); //Init hash function + SDRM_SHA384_Final(&sha384_ctx, hash); //'L' is an empty string, so get output immediately + break; + case ID_SHA512: + SDRM_SHA512_Init(&sha512_ctx); //Init hash function + SDRM_SHA512_Final(&sha512_ctx, hash); //'L' is an empty string, so get output immediately + break; +#endif //_OP64_NOTSUPPORTED + default: + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + + //Compare hash value + for (i = 0; i < hLen; i++) + { + if (hash[i] != DB[i]) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + } + + //ignore 0x00s after hash(PS) + for (; i < dbLen; i++) + { + if (DB[i] != 0x00) + { + break; + } + } + + if ((i == dbLen) || (DB[i] != 0x01)) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + + memmove(m, DB + i + 1, dbLen - i - 1); + + if (mLen != NULL) + { + *mLen = dbLen - i - 1; + } + + memset(DB, 0x00, k * 2); + free(DB); + + return CRYPTO_SUCCESS; +} + +cc_u8 SDRM_DER_MD5[SDRM_DIGESTINFO_MD5_LEN] = SDRM_DIGESTINFO_MD5_VALUE; +cc_u8 SDRM_DER_SHA1[SDRM_DIGESTINFO_SHA1_LEN] = SDRM_DIGESTINFO_SHA1_VALUE; +cc_u8 SDRM_DER_SHA224[SDRM_DIGESTINFO_SHA224_LEN] = SDRM_DIGESTINFO_SHA224_VALUE; +cc_u8 SDRM_DER_SHA256[SDRM_DIGESTINFO_SHA256_LEN] = SDRM_DIGESTINFO_SHA256_VALUE; +cc_u8 SDRM_DER_SHA384[SDRM_DIGESTINFO_SHA384_LEN] = SDRM_DIGESTINFO_SHA384_VALUE; +cc_u8 SDRM_DER_SHA512[SDRM_DIGESTINFO_SHA512_LEN] = SDRM_DIGESTINFO_SHA512_VALUE; + +/* +* @fn int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +* @brief RSAES PKCS#1 v1.5 enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_EMSA_PKCS1_v1_5_Encode(cc_u8 *EM, cc_u32 emLen, cc_u8 *h, cc_u32 hLen, int HASH_Algorithm) +{ + cc_u32 tLen; + cc_u32 DigestInfoLen = 0; + cc_u8 DER[32]; + + switch (HASH_Algorithm) + { + case ID_MD5: + if (hLen != SDRM_MD5_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + DigestInfoLen = SDRM_DIGESTINFO_MD5_LEN; + memcpy(DER, SDRM_DER_MD5, SDRM_DIGESTINFO_MD5_LEN); + tLen = DigestInfoLen + SDRM_MD5_BLOCK_SIZ; + break; + case 0: + case ID_SHA1: + if (hLen != SDRM_SHA1_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + DigestInfoLen = SDRM_DIGESTINFO_SHA1_LEN; + memcpy(DER, SDRM_DER_SHA1, SDRM_DIGESTINFO_SHA1_LEN); + tLen = DigestInfoLen + SDRM_SHA1_BLOCK_SIZ; + break; + case ID_SHA224: + if (hLen != SDRM_SHA224_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + DigestInfoLen = SDRM_DIGESTINFO_SHA224_LEN; + memcpy(DER, SDRM_DER_SHA224, SDRM_DIGESTINFO_SHA224_LEN); + tLen = DigestInfoLen + SDRM_SHA224_BLOCK_SIZ; + break; + case ID_SHA256: + if (hLen != SDRM_SHA256_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + DigestInfoLen = SDRM_DIGESTINFO_SHA256_LEN; + memcpy(DER, SDRM_DER_SHA256, SDRM_DIGESTINFO_SHA256_LEN); + tLen = DigestInfoLen + SDRM_SHA256_BLOCK_SIZ; + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + if (hLen != SDRM_SHA384_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + DigestInfoLen = SDRM_DIGESTINFO_SHA384_LEN; + memcpy(DER, SDRM_DER_SHA384, SDRM_DIGESTINFO_SHA384_LEN); + tLen = DigestInfoLen + SDRM_SHA384_BLOCK_SIZ; + break; + case ID_SHA512: + if (hLen != SDRM_SHA512_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + DigestInfoLen = SDRM_DIGESTINFO_SHA512_LEN; + memcpy(DER, SDRM_DER_SHA512, SDRM_DIGESTINFO_SHA512_LEN); + tLen = DigestInfoLen + SDRM_SHA512_BLOCK_SIZ; + break; +#endif //_OP64_NOTSUPPORTED + default: + return CRYPTO_INVALID_ARGUMENT; + } + + if (emLen < tLen + 11) + { + return CRYPTO_INVALID_ARGUMENT; + } + + EM[0] = 0x00; + EM[1] = 0x01; + memset(EM + 2, 0xff, emLen - tLen - 3); + EM[emLen - tLen - 1] = 0x00; + + memcpy(EM + emLen - tLen, DER, DigestInfoLen); + memcpy(EM + emLen - hLen, h, hLen); + + return CRYPTO_SUCCESS; +} + + +/* +* @fn int SDRM_Enpad_Rsaes_pkcs15(cc_u8 *EM, cc_u8 *m, cc_u32 mLen, cc_u32 k) +* @brief RSAES PKCS#1 v1.5 enpadding +* +* @param EM [out]Enpadded msg +* @param m [in]Message to pad +* @param mLen [in]byte-size of m +* @param k [in]byte-size of n(RSA modulus) +* +* @return CRYPTO_SUCCESS if no error is occured +* \n CRYPTO_MSG_TOO_LONG if message is longer then key +*/ +int SDRM_Enpad_Rsassa_pkcs15(cc_u8 *EM, cc_u32 emLen, cc_u8 *h, cc_u32 hLen, int HASH_Algorithm) +{ + return SDRM_EMSA_PKCS1_v1_5_Encode(EM, emLen, h, hLen, HASH_Algorithm); +} + +int SDRM_Depad_Rsassa_pkcs15(cc_u8 *EM, cc_u32 emLen, cc_u8 *h, cc_u32 hLen, int HASH_Algorithm) +{ + int ret; + cc_u8* EM_; + cc_u32 em_Len; + + if (EM[0] == 0x00) + { + EM = EM + 1; + emLen = emLen - 1; + } + + if (EM[0] != 0x01) + { + return CRYPTO_INVALID_ARGUMENT; + } + + em_Len = emLen + 1; + EM_ = (cc_u8*)malloc(em_Len); + if (EM_ == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + ret = SDRM_EMSA_PKCS1_v1_5_Encode(EM_, em_Len, h, hLen, HASH_Algorithm); + if (ret != CRYPTO_SUCCESS) + { + free(EM_); + return ret; + } + + if (memcmp(EM_ + 1, EM, emLen) == 0) + { + ret = CRYPTO_VALID_SIGN; + } + else + { + ret = CRYPTO_INVALID_SIGN; + } + + memset(EM_, 0x00, em_Len); + free(EM_); + + return ret; + +} + +int SDRM_Enpad_Rsassa_pss(cc_u8 *EM, cc_u32 nBits, cc_u8 *h, cc_u32 hLen, cc_u32 k, int HASH_Algorithm) +{ + cc_u8 Si_ANSI_X9_31[SDRM_X931_SEED_SIZ]; + cc_u8 salt[64]; + cc_u8 eight_zeros[8] = { 0 }; + cc_u32 sLen = hLen; + cc_u32 msBits = (nBits - 1) & 0x07; + cc_u32 emLen = k; + cc_u32 dbLen; + cc_u32 i; + + SDRM_MD5Context md5_ctx; //Hash env var + SDRM_SHA1Context sha1_ctx; //Hash env var + SDRM_SHA224Context sha224_ctx; //Hash env var + SDRM_SHA256Context sha256_ctx; //Hash env var +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context sha384_ctx; //Hash env var + SDRM_SHA512Context sha512_ctx; //Hash env var +#endif //_OP64_NOTSUPPORTED + + if (msBits == 0) + { + EM[0] = 0; + EM = EM + 1; + emLen = emLen - 1; + } + + if (emLen < hLen + sLen + 2) + { + return CRYPTO_INVALID_ARGUMENT; + } + + dbLen = emLen - hLen - 1; + + for (i = 0; i < 16; i++) + { + Si_ANSI_X9_31[i] = ((rand() << 16) + rand()) & 0xff; + } + + SDRM_RNG_X931(Si_ANSI_X9_31, sLen * 8, salt); + + //Get Hash of M' + switch (HASH_Algorithm) + { + case ID_MD5: + if (hLen != SDRM_MD5_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_MD5_Init(&md5_ctx); //Init hash function + SDRM_MD5_Update(&md5_ctx, eight_zeros, 8); //Input data + SDRM_MD5_Update(&md5_ctx, h, hLen); + SDRM_MD5_Update(&md5_ctx, salt, sLen); + SDRM_MD5_Final(&md5_ctx, EM + dbLen); //Get Output + break; + case 0: + case ID_SHA1: + if (hLen != SDRM_SHA1_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA1_Init(&sha1_ctx); //Init hash function + SDRM_SHA1_Update(&sha1_ctx, eight_zeros, 8); //Input data + SDRM_SHA1_Update(&sha1_ctx, h, hLen); + SDRM_SHA1_Update(&sha1_ctx, salt, sLen); + SDRM_SHA1_Final(&sha1_ctx, EM + dbLen); //Get Output + break; + case ID_SHA224: + if (hLen != SDRM_SHA224_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA224_Init(&sha224_ctx); //Init hash function + SDRM_SHA224_Update(&sha224_ctx, eight_zeros, 8); //Input data + SDRM_SHA224_Update(&sha224_ctx, h, hLen); + SDRM_SHA224_Update(&sha224_ctx, salt, sLen); + SDRM_SHA224_Final(&sha224_ctx, EM + dbLen); //Get Output + break; + case ID_SHA256: + if (hLen != SDRM_SHA256_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA256_Init(&sha256_ctx); //Init hash function + SDRM_SHA256_Update(&sha256_ctx, eight_zeros, 8); //Input data + SDRM_SHA256_Update(&sha256_ctx, h, hLen); + SDRM_SHA256_Update(&sha256_ctx, salt, sLen); + SDRM_SHA256_Final(&sha256_ctx, EM + dbLen); //Get Output + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + if (hLen != SDRM_SHA384_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA384_Init(&sha384_ctx); //Init hash function + SDRM_SHA384_Update(&sha384_ctx, eight_zeros, 8); //Input data + SDRM_SHA384_Update(&sha384_ctx, h, hLen); + SDRM_SHA384_Update(&sha384_ctx, salt, sLen); + SDRM_SHA384_Final(&sha384_ctx, EM + dbLen); //Get Output + break; + case ID_SHA512: + if (hLen != SDRM_SHA512_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA512_Init(&sha512_ctx); //Init hash function + SDRM_SHA512_Update(&sha512_ctx, eight_zeros, 8); //Input data + SDRM_SHA512_Update(&sha512_ctx, h, hLen); + SDRM_SHA512_Update(&sha512_ctx, salt, sLen); + SDRM_SHA512_Final(&sha512_ctx, EM + dbLen); //Get Output + break; +#endif //_OP64_NOTSUPPORTED + default: + return CRYPTO_INVALID_ARGUMENT; + } + + SDRM_MGF1(HASH_Algorithm, EM, EM + dbLen, hLen, dbLen); + EM[emLen - sLen - hLen - 2] ^= 0x01; + + + //memset(EM, 0x00, emLen - sLen - hLen - 2); + for (i = 0; i < sLen; i++) + { + EM[emLen - sLen - hLen - 1 + i] ^= salt[i]; + } + + if (msBits != 0) + { + EM[0] &= (0xff >> (8 - msBits)); + } + + EM[emLen - 1] = 0xbc; + + memset(Si_ANSI_X9_31, 0, 16); + memset(salt, 0, 64); + + return CRYPTO_SUCCESS; +} + + +int SDRM_Depad_Rsassa_pss(cc_u8 *EM, cc_u32 nBits, cc_u8 *h, cc_u32 hLen, cc_u32 k, int HASH_Algorithm) +{ + cc_u8* DB; + cc_u8 eight_zeros[8] = { 0 }; + cc_u32 msBits = (nBits - 1) & 0x07; + cc_u32 emLen = k; + cc_u32 sLen; + cc_u32 dbLen; + cc_u32 i; + cc_u8 hash[64] = {0}; + + SDRM_MD5Context md5_ctx; //Hash env var + SDRM_SHA1Context sha1_ctx; //Hash env var + SDRM_SHA224Context sha224_ctx; //Hash env var + SDRM_SHA256Context sha256_ctx; //Hash env var +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context sha384_ctx; //Hash env var + SDRM_SHA512Context sha512_ctx; //Hash env var +#endif //_OP64_NOTSUPPORTED + + if (EM[0] & (0xff << msBits)) + { + return CRYPTO_INVALID_SIGN; + } + + if (msBits == 0) + { + EM = EM + 1; + emLen = emLen - 1; + } + + if (EM[emLen - 1] != 0xbc) + { + return CRYPTO_INVALID_SIGN; + } + + dbLen = emLen - hLen - 1; + DB = (cc_u8*)malloc(dbLen); + if (DB == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_MGF1(HASH_Algorithm, DB, EM + dbLen, hLen, dbLen); + + for (i = 0; i < dbLen; i++) + { + DB[i] = DB[i] ^ EM[i]; + } + + if (msBits) + { + DB[0] &= (0xff >> (8 - msBits)); + } + + for (i = 0; i < dbLen; i++) + { + if (DB[i] != 0) + { + break; + } + } + + if ((i == dbLen) || (DB[i] != 0x01)) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + + sLen = dbLen - i - 1; + + //Get Hash of M' + switch (HASH_Algorithm) + { + case ID_MD5: + if (hLen != SDRM_MD5_BLOCK_SIZ) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_MD5_Init(&md5_ctx); //Init hash function + SDRM_MD5_Update(&md5_ctx, eight_zeros, 8); //Input data + SDRM_MD5_Update(&md5_ctx, h, hLen); + SDRM_MD5_Update(&md5_ctx, DB + i + 1, sLen); + SDRM_MD5_Final(&md5_ctx, hash); //Get Output + break; + case 0: + case ID_SHA1: + if (hLen != SDRM_SHA1_BLOCK_SIZ) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA1_Init(&sha1_ctx); //Init hash function + SDRM_SHA1_Update(&sha1_ctx, eight_zeros, 8); //Input data + SDRM_SHA1_Update(&sha1_ctx, h, hLen); + SDRM_SHA1_Update(&sha1_ctx, DB + i + 1, sLen); + SDRM_SHA1_Final(&sha1_ctx, hash); //Get Output + break; + case ID_SHA224: + if (hLen != SDRM_SHA224_BLOCK_SIZ) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA224_Init(&sha224_ctx); //Init hash function + SDRM_SHA224_Update(&sha224_ctx, eight_zeros, 8); //Input data + SDRM_SHA224_Update(&sha224_ctx, h, hLen); + SDRM_SHA224_Update(&sha224_ctx, DB + i + 1, sLen); + SDRM_SHA224_Final(&sha224_ctx, hash); //Get Output + break; + case ID_SHA256: + if (hLen != SDRM_SHA256_BLOCK_SIZ) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA256_Init(&sha256_ctx); //Init hash function + SDRM_SHA256_Update(&sha256_ctx, eight_zeros, 8); //Input data + SDRM_SHA256_Update(&sha256_ctx, h, hLen); + SDRM_SHA256_Update(&sha256_ctx, DB + i + 1, sLen); + SDRM_SHA256_Final(&sha256_ctx, hash); //Get Output + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384: + if (hLen != SDRM_SHA384_BLOCK_SIZ) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA384_Init(&sha384_ctx); //Init hash function + SDRM_SHA384_Update(&sha384_ctx, eight_zeros, 8); //Input data + SDRM_SHA384_Update(&sha384_ctx, h, hLen); + SDRM_SHA384_Update(&sha384_ctx, DB + i + 1, sLen); + SDRM_SHA384_Final(&sha384_ctx, hash); //Get Output + break; + case ID_SHA512: + if (hLen != SDRM_SHA512_BLOCK_SIZ) + { + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + SDRM_SHA512_Init(&sha512_ctx); //Init hash function + SDRM_SHA512_Update(&sha512_ctx, eight_zeros, 8); //Input data + SDRM_SHA512_Update(&sha512_ctx, h, hLen); + SDRM_SHA512_Update(&sha512_ctx, DB + i + 1, sLen); + SDRM_SHA512_Final(&sha512_ctx, hash); //Get Output + break; +#endif //_OP64_NOTSUPPORTED + default: + free(DB); + return CRYPTO_INVALID_ARGUMENT; + } + + memset(DB, 0x00, dbLen); + free(DB); + + if (memcmp(hash, EM + dbLen, hLen) == 0) + { + return CRYPTO_VALID_SIGN; + } + else + { + return CRYPTO_INVALID_SIGN; + } +} + +/* + * @fn int SDRM_MGF1(int HASH_Algorithm, cc_u8* mask, cc_u8* pbSeed, cc_u32 SeedLen, cc_u32 dMaskLen) + * @brief SDRM_MGF1 Function (Mask Generation Function based on a hash function) + * + * @param mask [out]byte-length of generated mask + * @param pbSeed [in]seed for MGF + * @param SeedLen [in]byte-length of pbSeed + * @param dMaskLen [in]byte-length of mask + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if malloc is failed + */ +static int SDRM_MGF1(int HASH_Algorithm, cc_u8* mask, cc_u8* pbSeed, cc_u32 SeedLen, cc_u32 dMaskLen) +{ + cc_u8 *T, *Seed, *pbBuf; + cc_u32 counter; + cc_u8 hash[64]; //SHA-1 output size is 160 bit + cc_u8 hashlen; + SDRM_MD5Context md5_ctx; //Hash env var + SDRM_SHA1Context sha1_ctx; //Hash env var + SDRM_SHA224Context sha224_ctx; //Hash env var + SDRM_SHA256Context sha256_ctx; //Hash env var +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context sha384_ctx; //Hash env var + SDRM_SHA512Context sha512_ctx; //Hash env var +#endif //_OP64_NOTSUPPORTED + + switch(HASH_Algorithm) + { + case ID_MD5 : + hashlen = SDRM_MD5_BLOCK_SIZ; + break; + case 0 : + case ID_SHA1 : + hashlen = SDRM_SHA1_BLOCK_SIZ; + break; + case ID_SHA224 : + hashlen = SDRM_SHA224_BLOCK_SIZ; + break; + case ID_SHA256 : + hashlen = SDRM_SHA256_BLOCK_SIZ; + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384 : + hashlen = SDRM_SHA384_BLOCK_SIZ; + break; + case ID_SHA512 : + hashlen = SDRM_SHA512_BLOCK_SIZ; + break; +#endif //_OP64_NOTSUPPORTED + default : + return CRYPTO_INVALID_ARGUMENT; + } + + pbBuf = (cc_u8*)malloc(dMaskLen + hashlen + SeedLen + 4); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + T = pbBuf; + Seed = T + dMaskLen + hashlen; + + memset(mask, 0, dMaskLen); + memcpy(Seed, pbSeed, SeedLen); + + for (counter = 0; counter < (dMaskLen - 1) / hashlen + 1; counter++) + { + Seed[SeedLen ] = (cc_u8)(counter >> 24); + Seed[SeedLen + 1] = (cc_u8)(counter >> 16); + Seed[SeedLen + 2] = (cc_u8)(counter >> 8 ); + Seed[SeedLen + 3] = (cc_u8)(counter ); + + //Hash(Seed||counter) + switch(HASH_Algorithm) + { + case ID_MD5 : + SDRM_MD5_Init(&md5_ctx); //Init hash function + SDRM_MD5_Update(&md5_ctx, Seed, SeedLen + 4); //Input data + SDRM_MD5_Final(&md5_ctx, hash); //Get Output + break; + case 0 : + case ID_SHA1 : + SDRM_SHA1_Init(&sha1_ctx); //Init hash function + SDRM_SHA1_Update(&sha1_ctx, Seed, SeedLen + 4); //Input data + SDRM_SHA1_Final(&sha1_ctx, hash); //Get Output + break; + case ID_SHA224 : + SDRM_SHA224_Init(&sha224_ctx); //Init hash function + SDRM_SHA224_Update(&sha224_ctx, Seed, SeedLen + 4); //Input data + SDRM_SHA224_Final(&sha224_ctx, hash); //Get Output + break; + case ID_SHA256 : + SDRM_SHA256_Init(&sha256_ctx); //Init hash function + SDRM_SHA256_Update(&sha256_ctx, Seed, SeedLen + 4); //Input data + SDRM_SHA256_Final(&sha256_ctx, hash); //Get Output + break; +#ifndef _OP64_NOTSUPPORTED + case ID_SHA384 : + SDRM_SHA384_Init(&sha384_ctx); //Init hash function + SDRM_SHA384_Update(&sha384_ctx, Seed, SeedLen + 4); //Input data + SDRM_SHA384_Final(&sha384_ctx, hash); //Get Output + break; + case ID_SHA512 : + SDRM_SHA512_Init(&sha512_ctx); //Init hash function + SDRM_SHA512_Update(&sha512_ctx, Seed, SeedLen + 4); //Input data + SDRM_SHA512_Final(&sha512_ctx, hash); //Get Output + break; +#endif //_OP64_NOTSUPPORTED + default : + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + memcpy(T + counter * hashlen, hash, hashlen); + } + + memcpy(mask, T, dMaskLen); + memset(pbBuf, 0x00, dMaskLen + hashlen + SeedLen + 4); + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/base/cc_rc4.c b/ssflib/dep/cryptocore/source/base/cc_rc4.c new file mode 100755 index 0000000..6db4ea7 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_rc4.c @@ -0,0 +1,161 @@ +/** + * \file rc4.c + * @brief implementation of RC4 encryption scheme + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/01 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_rc4.h" + + +//////////////////////////////////////////////////////////////////////////// +// initial vector of s +//////////////////////////////////////////////////////////////////////////// +static cc_u32 RC4_S_VALUE_LITTLE[] = { + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x23222120, 0x27262524, 0x2b2a2928, 0x2f2e2d2c, + 0x33323130, 0x37363534, 0x3b3a3938, 0x3f3e3d3c, + 0x43424140, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, + 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, + 0x63626160, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, + 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, + 0x83828180, 0x87868584, 0x8b8a8988, 0x8f8e8d8c, + 0x93929190, 0x97969594, 0x9b9a9998, 0x9f9e9d9c, + 0xa3a2a1a0, 0xa7a6a5a4, 0xabaaa9a8, 0xafaeadac, + 0xb3b2b1b0, 0xb7b6b5b4, 0xbbbab9b8, 0xbfbebdbc, + 0xc3c2c1c0, 0xc7c6c5c4, 0xcbcac9c8, 0xcfcecdcc, + 0xd3d2d1d0, 0xd7d6d5d4, 0xdbdad9d8, 0xdfdedddc, + 0xe3e2e1e0, 0xe7e6e5e4, 0xebeae9e8, 0xefeeedec, + 0xf3f2f1f0, 0xf7f6f5f4, 0xfbfaf9f8, 0xfffefdfc, +}; + +static cc_u32 RC4_S_VALUE_BIG[] = { + 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, + 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f, + 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f, + 0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f, + 0x40414243, 0x44454647, 0x48494a4b, 0x4c4d4e4f, + 0x50515253, 0x54555657, 0x58595a5b, 0x5c5d5e5f, + 0x60616263, 0x64656667, 0x68696a6b, 0x6c6d6e6f, + 0x70717273, 0x74757677, 0x78797a7b, 0x7c7d7e7f, + 0x80818283, 0x84858687, 0x88898a8b, 0x8c8d8e8f, + 0x90919293, 0x94959697, 0x98999a9b, 0x9c9d9e9f, + 0xa0a1a2a3, 0xa4a5a6a7, 0xa8a9aaab, 0xacadaeaf, + 0xb0b1b2b3, 0xb4b5b6b7, 0xb8b9babb, 0xbcbdbebf, + 0xc0c1c2c3, 0xc4c5c6c7, 0xc8c9cacb, 0xcccdcecf, + 0xd0d1d2d3, 0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf, + 0xe0e1e2e3, 0xe4e5e6e7, 0xe8e9eaeb, 0xecedeeef, + 0xf0f1f2f3, 0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff +}; + +/* + * @fn SDRM_RC4_Setup + * @brief intialize s + * + * @param ctx [in]crypto context + * @param UserKey [in]user key + * @param keyLen [out]byte-length of UserKey + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_RC4_Setup(SDRM_RC4Context *ctx, cc_u8 *UserKey, cc_u32 keyLen) +{ + cc_u32 i, j, loc = keyLen; + cc_u8 temp; + + //initialization + i = 0xff; + if (((cc_u8*)&i)[0] == 0xff) + { +// LOG4DRM_INFO(&CryptoLogCTX), "is Little Endian machine\n"); + memcpy(ctx->s, RC4_S_VALUE_LITTLE, 256); + } + else + { +// LOG4DRM_INFO(&CryptoLogCTX), "is Big Endian machine\n"); + memcpy(ctx->s, RC4_S_VALUE_BIG, 256); + } + + memcpy(ctx->key, UserKey, keyLen); + + ctx->keyLen = keyLen; + ctx->i = 0; + ctx->j = 0; + + //scrambling + if ((keyLen == 16) || (keyLen == 32)) + { + loc--; + for (i = 0, j = 0; i < 256; ++i) + { + j= (j + ctx->key[i & loc] + ctx->s[i]) & 0xff; + temp = ctx->s[i]; + ctx->s[i] = ctx->s[j]; + ctx->s[j] = temp; + } + } + else + { + for (i = 0, j = 0; i < 256; ++i) + { + j = (j + ctx->key[i % ctx->keyLen] + ctx->s[i]) & 0xff; + temp = ctx->s[i]; + ctx->s[i] = ctx->s[j]; + ctx->s[j] = temp; + } + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_RC4_PRNG + * @brief process stream data + * + * @param ctx [in]crypto context + * @param in [in]plaintext + * @param inLen [in]byte-length of in + * @param out [out]cipher text + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_RC4_PRNG(SDRM_RC4Context *ctx, cc_u8 *in, cc_u32 inLen, cc_u8 *out) +{ + cc_u32 i, j, k; + cc_u8 temp; + + i = ctx->i; + j = ctx->j; + + for (k = 0; k < inLen; k++) + { + i++; + i &= 0xff; + j += ctx->s[i]; + j &= 0xff; + + temp = ctx->s[i]; + ctx->s[i] = ctx->s[j]; + ctx->s[j] = temp; + + temp = ctx->s[i] + ctx->s[j]; + + out[k] = in[k]^(ctx->s[temp]); + } + + ctx->i = i; + ctx->j = j; + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/base/cc_sha1.c b/ssflib/dep/cryptocore/source/base/cc_sha1.c new file mode 100755 index 0000000..be9dd2a --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_sha1.c @@ -0,0 +1,477 @@ +/* For torrentcheck.c, main() commented out */ +/* sha1.c : Implementation of the Secure Hash Algorithm */ + +/* SHA: NIST's Secure Hash Algorithm */ + +/* This version written November 2000 by David Ireland of + DI Management Services Pty Limited + + Adapted from code in the Python Cryptography Toolkit, + version 1.0.0 by A.M. Kuchling 1995. +*/ + +/* AM Kuchling's posting:- + Based on SHA code originally posted to sci.crypt by Peter Gutmann + in message <30ajo5$oe8@ccu2.auckland.ac.nz>. + Modified to test for endianness on creation of SHA objects by AMK. + Also, the original specification of SHA was found to have a weakness + by NSA/NIST. This code implements the fixed version of SHA. +*/ + +/* Here's the first paragraph of Peter Gutmann's posting: + +The following is my SHA (FIPS 180) code updated to allow use of the "fixed" +SHA, thanks to Jim Gillogly and an anonymous contributor for the information on +what's changed in the new version. The fix is a simple change which involves +adding a single rotate in the initial expansion function. It is unknown +whether this is an optimal solution to the problem which was discovered in the +SHA or whether it's simply a bandaid which fixes the problem with a minimum of +effort (for example the reengineering of a great many Capstone chips). +*/ + +/* JS Park's posting: + Modification for naming confilct. + - Attach prefix 'SDRM_SHA1_' for all function and constants. + - Change name of data context to 'SDRM_SHA1Context' + endianTest code is modified to avoid gcc warning. + Primitive data types are used, instead of user-defined data types. + Prototypes are moved to header file. + Not using functions are commented out. + */ + + +void SDRM_endianTest(int *endianness); + +/* sha.c */ + +#include "cc_sha1.h" + +static void SDRM_SHAtoByte(unsigned char *output, unsigned int *input, unsigned int len); + +/* The SHS block size and message digest sizes, in bytes */ + +#define SDRM_SHA1_DATASIZE 64 +#define SDRM_SHA1_DIGESTSIZE 20 + + +/* The SHS f()-functions. The f1 and f3 functions can be optimized to + save one boolean operation each - thanks to Rich Schroeppel, + rcs@cs.arizona.edu for discovering this */ + +/*#define SDRM_SHA1_f1(x,y,z) ((x & y) | (~x & z)) // Rounds 0-19 */ +#define SDRM_SHA1_f1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) /* Rounds 0-19 */ +#define SDRM_SHA1_f2(x,y,z) ((x) ^ (y) ^ (z)) /* Rounds 20-39 */ +/*#define SDRM_SHA1_f3(x,y,z) ((x & y) | (x & z) | (y & z)) // Rounds 40-59 */ +#define SDRM_SHA1_f3(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) /* Rounds 40-59 */ +#define SDRM_SHA1_f4(x,y,z) ((x) ^ (y) ^ (z)) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define SDRM_SHA1_K1 0x5A827999L /* Rounds 0-19 */ +#define SDRM_SHA1_K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define SDRM_SHA1_K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define SDRM_SHA1_K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define SDRM_SHA1_h0init 0x67452301L +#define SDRM_SHA1_h1init 0xEFCDAB89L +#define SDRM_SHA1_h2init 0x98BADCFEL +#define SDRM_SHA1_h3init 0x10325476L +#define SDRM_SHA1_h4init 0xC3D2E1F0L + +/* Note that it may be necessary to add parentheses to these macros if they + are to be called with expressions as arguments */ +/* 32-bit rotate left - kludged with shifts */ + +#define SDRM_SHA1_ROTL(n, X) (((X) << (n)) | ((X) >> (32 - (n)))) + +/* The initial expanding function. The hash function is defined over an + 80-UINT2 expanded input array W, where the first 16 are copies of the input + data, and the remaining 64 are defined by + + W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] + + This implementation generates these values on the fly in a circular + buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this + optimization. + + The updated SHS changes the expanding function by adding a rotate of 1 + bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor + for this information */ + +#define SDRM_SHA1_expand(W, i) (W[(i) & 15] = SDRM_SHA1_ROTL(1, (W[(i) & 15] ^ W[((i) - 14) & 15] ^ \ + W[((i) - 8) & 15] ^ W[((i) - 3) & 15]))) + + +/* The prototype SHS sub-round. The fundamental sub-round is: + + a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; + b' = a; + c' = ROTL( 30, b ); + d' = c; + e' = d; + + but this is implemented by unrolling the loop 5 times and renaming the + variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. + This code is then replicated 20 times for each of the 4 functions, using + the next 20 values from the W[] array each time */ + +#define SDRM_SHA1_subRound(a, b, c, d, e, f, k, data) \ + (e += SDRM_SHA1_ROTL(5, a) + f(b, c, d) + (k) + (data), b = SDRM_SHA1_ROTL(30, b)) + +/* Initialize the SHS values */ + +void SDRM_SHA1_Init(SDRM_SHA1Context *shsInfo) +{ + SDRM_endianTest(&shsInfo->Endianness); + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = SDRM_SHA1_h0init; + shsInfo->digest[ 1 ] = SDRM_SHA1_h1init; + shsInfo->digest[ 2 ] = SDRM_SHA1_h2init; + shsInfo->digest[ 3 ] = SDRM_SHA1_h3init; + shsInfo->digest[ 4 ] = SDRM_SHA1_h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0; +} + + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers due to the complexity of the expressions + and the size of the basic block. It may be necessary to split it into + sections, e.g. based on the four subrounds + + Note that this corrupts the shsInfo->data area */ + +static void SDRM_SHSTransform(unsigned int *digest, unsigned int *data ) + { + unsigned int A, B, C, D, E; /* Local vars */ + unsigned int eData[ 16 ]; /* Expanded data */ + + /* Set up first buffer and local data buffer */ + A = digest[ 0 ]; + B = digest[ 1 ]; + C = digest[ 2 ]; + D = digest[ 3 ]; + E = digest[ 4 ]; + memcpy( (unsigned char*)eData, (unsigned char*)data, SDRM_SHA1_DATASIZE ); + + /* Heavy mangling, in 4 sub-rounds of 20 interations each. */ + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 0 ] ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 1 ] ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 2 ] ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 3 ] ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 4 ] ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 5 ] ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 6 ] ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 7 ] ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 8 ] ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 9 ] ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 10 ] ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 11 ] ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 12 ] ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 13 ] ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 14 ] ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f1, SDRM_SHA1_K1, eData[ 15 ] ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f1, SDRM_SHA1_K1, SDRM_SHA1_expand( eData, 16 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f1, SDRM_SHA1_K1, SDRM_SHA1_expand( eData, 17 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f1, SDRM_SHA1_K1, SDRM_SHA1_expand( eData, 18 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f1, SDRM_SHA1_K1, SDRM_SHA1_expand( eData, 19 ) ); + + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 20 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 21 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 22 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 23 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 24 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 25 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 26 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 27 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 28 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 29 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 30 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 31 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 32 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 33 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 34 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 35 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 36 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 37 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 38 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f2, SDRM_SHA1_K2, SDRM_SHA1_expand( eData, 39 ) ); + + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 40 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 41 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 42 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 43 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 44 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 45 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 46 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 47 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 48 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 49 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 50 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 51 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 52 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 53 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 54 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 55 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 56 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 57 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 58 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f3, SDRM_SHA1_K3, SDRM_SHA1_expand( eData, 59 ) ); + + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 60 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 61 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 62 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 63 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 64 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 65 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 66 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 67 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 68 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 69 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 70 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 71 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 72 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 73 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 74 ) ); + SDRM_SHA1_subRound( A, B, C, D, E, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 75 ) ); + SDRM_SHA1_subRound( E, A, B, C, D, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 76 ) ); + SDRM_SHA1_subRound( D, E, A, B, C, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 77 ) ); + SDRM_SHA1_subRound( C, D, E, A, B, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 78 ) ); + SDRM_SHA1_subRound( B, C, D, E, A, SDRM_SHA1_f4, SDRM_SHA1_K4, SDRM_SHA1_expand( eData, 79 ) ); + + /* Build message digest */ + digest[ 0 ] += A; + digest[ 1 ] += B; + digest[ 2 ] += C; + digest[ 3 ] += D; + digest[ 4 ] += E; + } + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of long words. */ + +static void SDRM_longReverse(unsigned int *buffer, int byteCount, int Endianness) +{ + unsigned int value; + + if (Endianness == !(0)) { + return; + } + byteCount /= sizeof( unsigned int ); + while(byteCount--) + { + value = *buffer; + value = ((value & 0xFF00FF00L) >> 8) | \ + ((value & 0x00FF00FFL ) << 8); + *buffer++ = (value << 16) | (value >> 16); + } +} + +/* Update SHS for a block of data */ + +void SDRM_SHA1_Update(SDRM_SHA1Context *shsInfo, const unsigned char *buffer, int count) +{ + unsigned int tmp; + int dataCount; + + /* Update bitcount */ + tmp = shsInfo->countLo; + if ((shsInfo->countLo = tmp + ((unsigned int)count << 3)) < tmp) { + shsInfo->countHi++; /* Carry from low to high */ + } + + shsInfo->countHi += count >> 29; + + /* Get count of bytes already in data */ + dataCount = (int)(tmp >> 3) & 0x3F; + + /* Handle any leading odd-sized chunks */ + if (dataCount) + { + unsigned char *p = (unsigned char*) shsInfo->data + dataCount; + + dataCount = SDRM_SHA1_DATASIZE - dataCount; + if(count < dataCount) + { + memcpy(p, buffer, count); + return; + } + memcpy(p, buffer, dataCount); + SDRM_longReverse(shsInfo->data, SDRM_SHA1_DATASIZE, shsInfo->Endianness); + SDRM_SHSTransform(shsInfo->digest, shsInfo->data); + buffer += dataCount; + count -= dataCount; + } + + /* Process data in SHS_DATASIZE chunks */ + while(count >= SDRM_SHA1_DATASIZE) + { + memcpy((unsigned char*)shsInfo->data, buffer, SDRM_SHA1_DATASIZE); + SDRM_longReverse(shsInfo->data, SDRM_SHA1_DATASIZE, shsInfo->Endianness); + SDRM_SHSTransform(shsInfo->digest, shsInfo->data); + buffer += SDRM_SHA1_DATASIZE; + count -= SDRM_SHA1_DATASIZE; + } + + /* Handle any remaining bytes of data. */ + memcpy( (unsigned char*)shsInfo->data, buffer, count); + } + +/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern + 1 0* (64-bit count of bits processed, MSB-first) */ + +void SDRM_SHA1_Final(SDRM_SHA1Context *shsInfo, unsigned char *output) +{ + int count; + unsigned char *dataPtr; + + /* Compute number of bytes mod 64 */ + count = (int) shsInfo->countLo; + count = (count >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + dataPtr = (unsigned char*) shsInfo->data + count; + *dataPtr++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = SDRM_SHA1_DATASIZE - 1 - count; + + /* Pad out to 56 mod 64 */ + if( count < 8 ) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(dataPtr, 0, count); + SDRM_longReverse(shsInfo->data, SDRM_SHA1_DATASIZE, shsInfo->Endianness); + SDRM_SHSTransform(shsInfo->digest, shsInfo->data); + + /* Now fill the next block with 56 bytes */ + memset((unsigned char*)shsInfo->data, 0, SDRM_SHA1_DATASIZE - 8); + } + else + /* Pad block to 56 bytes */ + { + memset(dataPtr, 0, count - 8); + } + + /* Append length in bits and transform */ + shsInfo->data[14] = shsInfo->countHi; + shsInfo->data[15] = shsInfo->countLo; + + SDRM_longReverse(shsInfo->data, SDRM_SHA1_DATASIZE - 8, shsInfo->Endianness); + SDRM_SHSTransform(shsInfo->digest, shsInfo->data); + + /* Output to an array of bytes */ + SDRM_SHAtoByte(output, shsInfo->digest, SDRM_SHA1_DIGESTSIZE); + + /* Zeroise sensitive stuff */ + memset((unsigned char*)shsInfo, 0, sizeof(SDRM_SHA1Context)); +} + +static void SDRM_SHAtoByte(unsigned char *output, unsigned int *input, unsigned int len) +{ /* Output SHA digest in byte array */ + unsigned int i, j; + + for(i = 0, j = 0; j < len; i++, j += 4) + { + output[j+3] = (unsigned char)( input[i] & 0xff); + output[j+2] = (unsigned char)((input[i] >> 8 ) & 0xff); + output[j+1] = (unsigned char)((input[i] >> 16) & 0xff); + output[j ] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + + +//unsigned char digest[20]; +//unsigned char message[3] = {'a', 'b', 'c' }; +//unsigned char *mess56 = +// "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + +/* Correct solutions from FIPS PUB 180-1 */ +//char *dig1 = "A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D"; +//char *dig2 = "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1"; +//char *dig3 = "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F"; + +/* Output should look like:- + a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D <= correct + 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 <= correct + 34aa973c d4c4daa4 f61eeb2b dbad2731 6534016f + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F <= correct +*/ + +//main() +//{ +// SHA_CTX sha; +// int i; +// BYTE big[1000]; +// +// SHAInit(&sha); +// SHAUpdate(&sha, message, 3); +// SHAFinal(digest, &sha); +// +// for (i = 0; i < 20; i++) +// { +// if ((i % 4) == 0) printf(" "); +// printf("%02x", digest[i]); +// } +// printf("\n"); +// printf(" %s <= correct\n", dig1); +// +// SHAInit(&sha); +// SHAUpdate(&sha, mess56, 56); +// SHAFinal(digest, &sha); +// +// for (i = 0; i < 20; i++) +// { +// if ((i % 4) == 0) printf(" "); +// printf("%02x", digest[i]); +// } +// printf("\n"); +// printf(" %s <= correct\n", dig2); +// +// /* Fill up big array */ +// for (i = 0; i < 1000; i++) +// big[i] = 'a'; +// +// SHAInit(&sha); +// /* Digest 1 million x 'a' */ +// for (i = 0; i < 1000; i++) +// SHAUpdate(&sha, big, 1000); +// SHAFinal(digest, &sha); +// +// for (i = 0; i < 20; i++) +// { +// if ((i % 4) == 0) printf(" "); +// printf("%02x", digest[i]); +// } +// printf("\n"); +// printf(" %s <= correct\n", dig3); +// +// return 0; +//} + +/* endian.c */ + +void SDRM_endianTest(int *endian_ness) +{ + static short test = 1; + + if ( *((char *) &test) != 1) + { + /* printf("Big endian = no change\n"); */ + *endian_ness = !(0); + } + else + { + /* printf("Little endian = swap\n"); */ + *endian_ness = 0; + } +} + +/***************************** End of File *****************************/ + diff --git a/ssflib/dep/cryptocore/source/base/cc_sha2.c b/ssflib/dep/cryptocore/source/base/cc_sha2.c new file mode 100755 index 0000000..75ad2a9 --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_sha2.c @@ -0,0 +1,660 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * 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 project 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 PROJECT 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 PROJECT 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. + */ + +/* JS Park's posting: + Modification for naming confilct. + Attach prefix 'SDRM_' for all function and constants. + Change name of data context to 'SDRM_SHAxxxContext' (xxx is bit length of digest) +*/ + +#include + +#include "cc_sha2.h" + +#define SDRM_SHA2_SHFR(x, n) ((x) >> (n)) +#define SDRM_SHA2_ROTR(x, n) (((x) >> (n)) | ((x) << ((sizeof(x) << 3) - (n)))) +#define SDRM_SHA2_ROTL(x, n) (((x) << (n)) | ((x) >> ((sizeof(x) << 3) - (n)))) +#define SDRM_SHA2_CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define SDRM_SHA2_MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define SDRM_SHA2_SHA256_F1(x) (SDRM_SHA2_ROTR(x, 2) ^ SDRM_SHA2_ROTR(x, 13) ^ SDRM_SHA2_ROTR(x, 22)) +#define SDRM_SHA2_SHA256_F2(x) (SDRM_SHA2_ROTR(x, 6) ^ SDRM_SHA2_ROTR(x, 11) ^ SDRM_SHA2_ROTR(x, 25)) +#define SDRM_SHA2_SHA256_F3(x) (SDRM_SHA2_ROTR(x, 7) ^ SDRM_SHA2_ROTR(x, 18) ^ SDRM_SHA2_SHFR(x, 3)) +#define SDRM_SHA2_SHA256_F4(x) (SDRM_SHA2_ROTR(x, 17) ^ SDRM_SHA2_ROTR(x, 19) ^ SDRM_SHA2_SHFR(x, 10)) + +#define SDRM_SHA2_SHA512_F1(x) (SDRM_SHA2_ROTR(x, 28) ^ SDRM_SHA2_ROTR(x, 34) ^ SDRM_SHA2_ROTR(x, 39)) +#define SDRM_SHA2_SHA512_F2(x) (SDRM_SHA2_ROTR(x, 14) ^ SDRM_SHA2_ROTR(x, 18) ^ SDRM_SHA2_ROTR(x, 41)) +#define SDRM_SHA2_SHA512_F3(x) (SDRM_SHA2_ROTR(x, 1) ^ SDRM_SHA2_ROTR(x, 8) ^ SDRM_SHA2_SHFR(x, 7)) +#define SDRM_SHA2_SHA512_F4(x) (SDRM_SHA2_ROTR(x, 19) ^ SDRM_SHA2_ROTR(x, 61) ^ SDRM_SHA2_SHFR(x, 6)) + +#define SDRM_SHA2_UNPACK32(x, str) \ +do { \ + *((str) + 3) = (cc_u8) ((x) ); \ + *((str) + 2) = (cc_u8) ((x) >> 8); \ + *((str) + 1) = (cc_u8) ((x) >> 16); \ + *((str) + 0) = (cc_u8) ((x) >> 24); \ +} while(0) + +#define SDRM_SHA2_PACK32(str, x) \ +do { \ + *(x) = ((cc_u32) *((str) + 3) ) \ + | ((cc_u32) *((str) + 2) << 8) \ + | ((cc_u32) *((str) + 1) << 16) \ + | ((cc_u32) *((str) + 0) << 24); \ +} while(0) + +#define SDRM_SHA2_UNPACK64(x, str) \ +do { \ + *((str) + 7) = (cc_u8) ((x) ); \ + *((str) + 6) = (cc_u8) ((x) >> 8); \ + *((str) + 5) = (cc_u8) ((x) >> 16); \ + *((str) + 4) = (cc_u8) ((x) >> 24); \ + *((str) + 3) = (cc_u8) ((x) >> 32); \ + *((str) + 2) = (cc_u8) ((x) >> 40); \ + *((str) + 1) = (cc_u8) ((x) >> 48); \ + *((str) + 0) = (cc_u8) ((x) >> 56); \ +} while(0) + +#define SDRM_SHA2_PACK64(str, x) \ +do { \ + *(x) = ((cc_u64) *((str) + 7) ) \ + | ((cc_u64) *((str) + 6) << 8) \ + | ((cc_u64) *((str) + 5) << 16) \ + | ((cc_u64) *((str) + 4) << 24) \ + | ((cc_u64) *((str) + 3) << 32) \ + | ((cc_u64) *((str) + 2) << 40) \ + | ((cc_u64) *((str) + 1) << 48) \ + | ((cc_u64) *((str) + 0) << 56); \ +} while(0) + +/* Macros used for loops unrolling */ + +#define SDRM_SHA2_SHA256_SCR(i) \ +{ \ + w[i] = SDRM_SHA2_SHA256_F4(w[(i) - 2]) + w[(i) - 7] \ + + SDRM_SHA2_SHA256_F3(w[(i) - 15]) + w[(i) - 16]; \ +} + +#define SDRM_SHA2_SHA512_SCR(i) \ +{ \ + w[i] = SDRM_SHA2_SHA512_F4(w[(i) - 2]) + w[(i) - 7] \ + + SDRM_SHA2_SHA512_F3(w[(i) - 15]) + w[(i) - 16]; \ +} + +#define SDRM_SHA2_SHA256_EXP(a, b, c, d, e, f, g, h, j) \ +{ \ + t1 = wv[h] + SDRM_SHA2_SHA256_F2(wv[e]) + SDRM_SHA2_CH(wv[e], wv[f], wv[g]) \ + + sha256_k[j] + w[j]; \ + t2 = SDRM_SHA2_SHA256_F1(wv[a]) + SDRM_SHA2_MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ +} + +#define SDRM_SHA2_SHA512_EXP(a, b, c, d, e, f, g ,h, j) \ +{ \ + t1 = wv[h] + SDRM_SHA2_SHA512_F2(wv[e]) + SDRM_SHA2_CH(wv[e], wv[f], wv[g]) \ + + sha512_k[j] + w[j]; \ + t2 = SDRM_SHA2_SHA512_F1(wv[a]) + SDRM_SHA2_MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ +} + +cc_u32 sha224_h0[8] = + {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; + +cc_u32 sha256_h0[8] = + {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +cc_u32 sha256_k[64] = + {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +#ifndef _OP64_NOTSUPPORTED + +#ifdef _WIN32 +cc_u64 sha384_h0[8] = + {0xcbbb9d5dc1059ed8, 0x629a292a367cd507, + 0x9159015a3070dd17, 0x152fecd8f70e5939, + 0x67332667ffc00b31, 0x8eb44a8768581511, + 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4}; + +cc_u64 sha512_h0[8] = + {0x6a09e667f3bcc908, 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179}; + +cc_u64 sha512_k[80] = + {0x428a2f98d728ae22, 0x7137449123ef65cd, + 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, + 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, + 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, + 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, + 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, + 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, + 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, + 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, + 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, + 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, + 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, + 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, + 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, + 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, + 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, + 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, + 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, + 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, + 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, + 0x5fcb6fab3ad6faec, 0x6c44198c4a475817}; +#else +cc_u64 sha384_h0[8] = + {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL}; + +cc_u64 sha512_h0[8] = + {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL}; + +cc_u64 sha512_k[80] = + {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL}; +#endif //_WIN32 +#endif //_OP64_NOTSUPPORTED + +/* SHA-256 functions */ + +void SDRM_SHA256_Transf(SDRM_SHA256Context* ctx, const cc_u8 *message, cc_u32 block_nb) +{ + cc_u32 w[64]; + cc_u32 wv[8]; + cc_u32 t1, t2; + const cc_u8 *sub_block; + int i; + + int j; + + for (i = 0; i < (int) block_nb; i++) + { + sub_block = message + (i << 6); + + for (j = 0; j < 16; j++) + { + SDRM_SHA2_PACK32(&sub_block[j << 2], &w[j]); + } + + for (j = 16; j < 64; j++) + { + SDRM_SHA2_SHA256_SCR(j); + } + + for (j = 0; j < 8; j++) + { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 64; j++) + { + t1 = wv[7] + SDRM_SHA2_SHA256_F2(wv[4]) + SDRM_SHA2_CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j]; + t2 = SDRM_SHA2_SHA256_F1(wv[0]) + SDRM_SHA2_MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) + { + ctx->h[j] += wv[j]; + } + } +} + +void SDRM_SHA256_Init(SDRM_SHA256Context* ctx) +{ + int i; + for (i = 0; i < 8; i++) + { + ctx->h[i] = sha256_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void SDRM_SHA256_Update(SDRM_SHA256Context* ctx, const cc_u8 *message, cc_u32 len) +{ + cc_u32 block_nb; + cc_u32 new_len, rem_len, tmp_len; + const cc_u8 *shifted_message; + + tmp_len = SDRM_SHA256_DATA_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SDRM_SHA256_DATA_SIZE) + { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SDRM_SHA256_DATA_SIZE; + + shifted_message = message + rem_len; + + SDRM_SHA256_Transf(ctx, ctx->block, 1); + SDRM_SHA256_Transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SDRM_SHA256_DATA_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void SDRM_SHA256_Final(SDRM_SHA256Context* ctx, cc_u8 *digest) +{ + cc_u32 block_nb; + cc_u32 pm_len; + cc_u32 len_b; + + int i; + + block_nb = (1 + ((SDRM_SHA256_DATA_SIZE - 9) < (ctx->len % SDRM_SHA256_DATA_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + SDRM_SHA2_UNPACK32(len_b, ctx->block + pm_len - 4); + + SDRM_SHA256_Transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 8; i++) + { + SDRM_SHA2_UNPACK32(ctx->h[i], &digest[i << 2]); + } +} + +#ifndef _OP64_NOTSUPPORTED + +/* SHA-512 functions */ + +void SDRM_SHA512_Transf(SDRM_SHA512Context* ctx, const cc_u8 *message, cc_u32 block_nb) +{ + cc_u64 w[80]; + cc_u64 wv[8]; + cc_u64 t1, t2; + const cc_u8 *sub_block; + int i, j; + + for (i = 0; i < (int) block_nb; i++) + { + sub_block = message + (i << 7); + + for (j = 0; j < 16; j++) + { + SDRM_SHA2_PACK64(&sub_block[j << 3], &w[j]); + } + + for (j = 16; j < 80; j++) + { + SDRM_SHA2_SHA512_SCR(j); + } + + for (j = 0; j < 8; j++) + { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 80; j++) + { + t1 = wv[7] + SDRM_SHA2_SHA512_F2(wv[4]) + SDRM_SHA2_CH(wv[4], wv[5], wv[6]) + + sha512_k[j] + w[j]; + t2 = SDRM_SHA2_SHA512_F1(wv[0]) + SDRM_SHA2_MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) + { + ctx->h[j] += wv[j]; + } + } +} + +void SDRM_SHA512_Init(SDRM_SHA512Context* ctx) +{ + int i; + for (i = 0; i < 8; i++) + { + ctx->h[i] = sha512_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void SDRM_SHA512_Update(SDRM_SHA512Context* ctx, const cc_u8 *message, cc_u32 len) +{ + cc_u32 block_nb; + cc_u32 new_len, rem_len, tmp_len; + const cc_u8 *shifted_message; + + tmp_len = SDRM_SHA512_DATA_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SDRM_SHA512_DATA_SIZE) + { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SDRM_SHA512_DATA_SIZE; + + shifted_message = message + rem_len; + + SDRM_SHA512_Transf(ctx, ctx->block, 1); + SDRM_SHA512_Transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SDRM_SHA512_DATA_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void SDRM_SHA512_Final(SDRM_SHA512Context* ctx, cc_u8 *digest) +{ + cc_u32 block_nb; + cc_u32 pm_len; + cc_u32 len_b; + + int i; + + block_nb = 1 + ((SDRM_SHA512_DATA_SIZE - 17) < (ctx->len % SDRM_SHA512_DATA_SIZE)); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + SDRM_SHA2_UNPACK32(len_b, ctx->block + pm_len - 4); + + SDRM_SHA512_Transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 8; i++) + { + SDRM_SHA2_UNPACK64(ctx->h[i], &digest[i << 3]); + } +} + +/* SHA-384 functions */ + +void SDRM_SHA384_Init(SDRM_SHA384Context* ctx) +{ + int i; + for (i = 0; i < 8; i++) + { + ctx->h[i] = sha384_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void SDRM_SHA384_Update(SDRM_SHA384Context* ctx, const cc_u8 *message, cc_u32 len) +{ + cc_u32 block_nb; + cc_u32 new_len, rem_len, tmp_len; + const cc_u8 *shifted_message; + + tmp_len = SDRM_SHA384_DATA_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SDRM_SHA384_DATA_SIZE) + { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SDRM_SHA384_DATA_SIZE; + + shifted_message = message + rem_len; + + SDRM_SHA512_Transf(ctx, ctx->block, 1); + SDRM_SHA512_Transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SDRM_SHA384_DATA_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 7], rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 7; +} + +void SDRM_SHA384_Final(SDRM_SHA384Context* ctx, cc_u8 *digest) +{ + cc_u32 block_nb; + cc_u32 pm_len; + cc_u32 len_b; + + int i; + + block_nb = (1 + ((SDRM_SHA384_DATA_SIZE - 17) < (ctx->len % SDRM_SHA384_DATA_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 7; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + SDRM_SHA2_UNPACK32(len_b, ctx->block + pm_len - 4); + + SDRM_SHA512_Transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 6; i++) + { + SDRM_SHA2_UNPACK64(ctx->h[i], &digest[i << 3]); + } +} + +#endif //_OP64_NOTSUPPORTED + +/* SHA-224 functions */ + +void SDRM_SHA224_Init(SDRM_SHA224Context *ctx) +{ + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha224_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void SDRM_SHA224_Update(SDRM_SHA224Context *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SDRM_SHA224_DATA_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SDRM_SHA224_DATA_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SDRM_SHA224_DATA_SIZE; + + shifted_message = message + rem_len; + + SDRM_SHA256_Transf(ctx, ctx->block, 1); + SDRM_SHA256_Transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SDRM_SHA224_DATA_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void SDRM_SHA224_Final(SDRM_SHA224Context *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + + int i; + + block_nb = (1 + ((SDRM_SHA224_DATA_SIZE - 9) + < (ctx->len % SDRM_SHA224_DATA_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + SDRM_SHA2_UNPACK32(len_b, ctx->block + pm_len - 4); + + SDRM_SHA256_Transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 7; i++) { + SDRM_SHA2_UNPACK32(ctx->h[i], &digest[i << 2]); + } +} diff --git a/ssflib/dep/cryptocore/source/base/cc_snow2.c b/ssflib/dep/cryptocore/source/base/cc_snow2.c new file mode 100755 index 0000000..700863d --- /dev/null +++ b/ssflib/dep/cryptocore/source/base/cc_snow2.c @@ -0,0 +1,404 @@ +/** + * \file snow2.c + * @brief implementation of SNOW 2.0 encryption scheme + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/02 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_snow2.h" + +//////////////////////////////////////////////////////////////////////////// +// pre-computated values +//////////////////////////////////////////////////////////////////////////// +static cc_u32 SNOW2_MUL_a[256]= { + 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, + 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, + 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, + 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, + 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, + 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, + 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, + 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, + 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, + 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, + 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, + 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, + 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, + 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, + 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, + 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, + 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, + 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, + 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, + 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, + 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, + 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, + 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, + 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, + 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, + 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, + 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, + 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, + 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, + 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, + 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, + 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB +}; + +static cc_u32 SNOW2_MUL_ainverse[256]= { + 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, + 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, + 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, + 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, + 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, + 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, + 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, + 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, + 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, + 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, + 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, + 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, + 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, + 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, + 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, + 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, + 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, + 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, + 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, + 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, + 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, + 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, + 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, + 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, + 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, + 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, + 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, + 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, + 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, + 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, + 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, + 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 +}; + +static cc_u32 SNOW2_T0[256]= { + 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, + 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, + 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, + 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, + 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, + 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, + 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, + 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, + 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, + 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, + 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, + 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, + 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, + 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, + 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, + 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, + 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, + 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, + 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, + 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, + 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, + 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, + 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, + 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c, + 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, + 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, + 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, + 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c +}; + +static cc_u32 SNOW2_T1[256]= { + 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, + 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, + 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, + 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, + 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, + 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, + 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, + 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, + 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, + 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397, + 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, + 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, + 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, + 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, + 0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, + 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, + 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, + 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, + 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83, + 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, + 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, + 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, + 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, + 0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, + 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, + 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, + 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12, + 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, + 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, + 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, + 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, + 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a +}; + +static cc_u32 SNOW2_T2[256]= { + 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, + 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, + 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, + 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, + 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, + 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, + 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, + 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, + 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, + 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784, + 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, + 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, + 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, + 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, + 0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, + 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, + 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, + 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, + 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388, + 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, + 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, + 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, + 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, + 0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, + 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, + 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, + 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e, + 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, + 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, + 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, + 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, + 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 +}; + +static cc_u32 SNOW2_T3[256]= { + 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, + 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, + 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, + 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, + 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, + 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, + 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0xa0f0505, 0x2fb59a9a, + 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, + 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, + 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484, + 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, + 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, + 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, + 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, + 0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, + 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, + 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, + 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, + 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888, + 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, + 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, + 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, + 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, + 0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, + 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, + 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, + 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e, + 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, + 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, + 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, + 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, + 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 +}; + +//////////////////////////////////////////////////////////////////////////// +// Macros +//////////////////////////////////////////////////////////////////////////// +#define a_MUL(w) (((w) << 8) ^ SNOW2_MUL_a[(w) >> 24]) +#define ainv_MUL(w) (((w) >> 8) ^ SNOW2_MUL_ainverse[(w) & 0xff]) + +#define BYTE0(w) ( (w) & 0xff) +#define BYTE1(w) (((w) >> 8) & 0xff) +#define BYTE2(w) (((w) >> 16) & 0xff) +#define BYTE3(w) (((w) >> 24) & 0xff) + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_SNOW2_Setup + * @brief Setup FSM and s values + * + * @param ctx [out]crypto context + * @param UserKey [in]User Key, 128 or 256 bit + * @param keyLen [in]byte-size of User Key, 16 or 32 + * @param IV [in]16 byte initial vector + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_SNOW2_Setup(SDRM_SNOW2Context *ctx, cc_u8 *UserKey, cc_u32 keyLen, cc_u8 *IV) +{ + cc_u32 IV0, IV1, IV2, IV3; + cc_u32 *s = ctx->s; + cc_u32 r1, r2, i; + cc_u32 Ft, R1_next; + + //test endian + i = 0xff; + ctx->endian = (*((cc_u8*)&i) == 0xff) ? CRYPTO_LITTLE_ENDIAN : CRYPTO_BIG_ENDIAN; + + //Initialize IV + GET_UINT32(IV3, IV, 0) + GET_UINT32(IV2, IV, 4) + GET_UINT32(IV1, IV, 8) + GET_UINT32(IV0, IV, 12) + + //Load Key + if (keyLen == 16) { + GET_UINT32(s[15], UserKey, 0) + GET_UINT32(s[14], UserKey, 4) + GET_UINT32(s[13], UserKey, 8) + GET_UINT32(s[12], UserKey, 12) + s[11] = ~s[15]; + s[10] = ~s[14]; + s[ 9] = ~s[13]; + s[ 8] = ~s[12]; + s[ 7] = s[15]; + s[ 6] = s[14]; + s[ 5] = s[13]; + s[ 4] = s[12]; + s[ 3] = ~s[15]; + s[ 2] = ~s[14]; + s[ 1] = ~s[13]; + s[ 0] = ~s[12]; + } + else { + GET_UINT32(s[15], UserKey, 0) + GET_UINT32(s[14], UserKey, 4) + GET_UINT32(s[13], UserKey, 8) + GET_UINT32(s[12], UserKey, 12) + GET_UINT32(s[11], UserKey, 16) + GET_UINT32(s[10], UserKey, 20) + GET_UINT32(s[ 9], UserKey, 24) + GET_UINT32(s[ 8], UserKey, 28) + s[ 7] = ~s[15]; + s[ 6] = ~s[14]; + s[ 5] = ~s[13]; + s[ 4] = ~s[12]; + s[ 3] = ~s[11]; + s[ 2] = ~s[10]; + s[ 1] = ~s[ 9]; + s[ 0] = ~s[ 8]; + } + + s[15] ^= IV0; + s[12] ^= IV1; + s[10] ^= IV2; + s[ 9] ^= IV3; + + r1 = 0; + r2 = 0; + + // clock 32 times without producing any output + for (i = 0; i < 16; i++) + { + Ft = (r1 + s[(i - 1) & 0x0f]) ^ r2; + s[i] = a_MUL(s[i]) ^ s[(i + 2) & 0x0f] ^ ainv_MUL(s[(i + 11) & 0x0f]) ^ Ft; + R1_next = r2 + s[(i + 5) & 0x0f]; + r2 = SNOW2_T0[BYTE0(r1)] ^ SNOW2_T1[BYTE1(r1)] ^ SNOW2_T2[BYTE2(r1)] ^ SNOW2_T3[BYTE3(r1)]; + r1 = R1_next; + } + + for (i = 0; i < 16; i++) + { + Ft = (r1 + s[(i - 1) & 0x0f]) ^ r2; + s[i] = a_MUL(s[i]) ^ s[(i + 2) & 0x0f] ^ ainv_MUL(s[(i + 11) & 0x0f]) ^ Ft; + R1_next = r2 + s[(i + 5) & 0x0f]; + r2 = SNOW2_T0[BYTE0(r1)] ^ SNOW2_T1[BYTE1(r1)] ^ SNOW2_T2[BYTE2(r1)] ^ SNOW2_T3[BYTE3(r1)]; + r1 = R1_next; + } + + ctx->r1 = r1; + ctx->r2 = r2; + + ctx->t = 0; + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SNOW2_getKeyStream64 + * @brief get 64 byte key stream + * + * @param ctx [out]crypto context + * @param keyStream64 [in]generated key stream + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_SNOW2_getKeyStream64(SDRM_SNOW2Context *ctx, cc_u32 *keyStream64) +{ + cc_u32 R1_next, i; + cc_u32 *s = ctx->s; + cc_u32 t = ctx->t; + + for (i = t; i < t + 16; i++) + { + s[i & 0x0f] = a_MUL(s[i & 0x0f]) ^ s[(i + 2) & 0x0f] ^ ainv_MUL(s[(i + 11) & 0x0f]); + R1_next = ctx->r2 + s[(i + 5) & 0x0f]; + ctx->r2 = SNOW2_T0[BYTE0(ctx->r1)] ^ SNOW2_T1[BYTE1(ctx->r1)] ^ SNOW2_T2[BYTE2(ctx->r1)] ^ SNOW2_T3[BYTE3(ctx->r1)]; + ctx->r1 = R1_next; + + keyStream64[i] = (ctx->r1 + s[i & 0x0f]) ^ ctx->r2 ^ s[(i + 1) & 0x0f]; + } + + ctx->t = t & 0x0f; + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_SNOW2_getKeyStream + * @brief get 4 byte key stream + * + * @param ctx [out]crypto context + * @param keyStream [in]generated key stream + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_SNOW2_getKeyStream(SDRM_SNOW2Context *ctx, cc_u32 *keyStream) +{ + cc_u32 R1_next; + cc_u32 *s = ctx->s; + cc_u32 t = ctx->t; + + s[t & 0x0f] = a_MUL(s[t & 0x0f]) ^ s[(t + 2) & 0x0f] ^ ainv_MUL(s[(t + 11) & 0x0f]); + R1_next = ctx->r2 + s[(t + 5) & 0x0f]; + ctx->r2 = SNOW2_T0[BYTE0(ctx->r1)] ^ SNOW2_T1[BYTE1(ctx->r1)] ^ SNOW2_T2[BYTE2(ctx->r1)] ^ SNOW2_T3[BYTE3(ctx->r1)]; + ctx->r1 = R1_next; + + *keyStream = (ctx->r1 + s[t & 0x0f]) ^ ctx->r2 ^ s[(t + 1) & 0x0f]; + + ctx->t = (t + 1) & 0x0f; + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_cmac.c b/ssflib/dep/cryptocore/source/middle/cc_cmac.c new file mode 100755 index 0000000..cda9d3c --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_cmac.c @@ -0,0 +1,260 @@ +/** + * \file cmac.c + * @brief funciton for c-mac code generation by AES-128 + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/20 + */ + + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_cmac.h" + + +//////////////////////////////////////////////////////////////////////////// +// Constants +//////////////////////////////////////////////////////////////////////////// +/*! @brief max block columns */ +#define CMAC_MAXBC (256/32) + +/*! @brief max key columns */ +#define CMAC_MAXKC (256/32) + +/*! @brief max rounds */ +#define CMAC_MAXROUNDS 14 + +/*! @brief constant - defined in OMAC1a(One-Key CBC MAC1, submitted by Iwata and Kurosawa) */ +static cc_u8 R_b[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; + + +/* + * @fn int SDRM_CMAC_init(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen) + * + * @brief Parameter setting for mac code generation + * @param crt [out]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CMAC_init(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen) +{ + cc_u8 *K1, *K2, temp[16] = {0}; + cc_u8 ZERO[16] = {0}; + int i; + cc_u32 *RoundKey; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->cmacctx == NULL) || (Key == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (KeyLen != 16) + { + return CRYPTO_INVALID_ARGUMENT; + } + + memset(crt->ctx->cmacctx->IV, 0, SDRM_AES_BLOCK_SIZ); + + crt->ctx->cmacctx->BlockLen = 0; + + RoundKey = (cc_u32*)(void*)(crt->ctx->cmacctx->RoundKey); + K1 = crt->ctx->cmacctx->K1; + K2 = crt->ctx->cmacctx->K2; + + SDRM_rijndaelKeySetupEnc(RoundKey, Key, 128); + + SDRM_rijndaelEncrypt(RoundKey, 10, ZERO, temp); + + if((temp[0] >> 7) == 0x00) // L << 1 + { + for (i = 0; i < 15; i++) + { + K1[i] = (temp[i] << 1) | (temp[i+1] >> 7); + } + K1[15] = temp[i] << 1; + } + else if ((temp[0] >> 7) == 0x01) + { + for (i = 0; i < 15; i++) + { + K1[i] = (temp[i] << 1) | (temp[i+1] >> 7); + } + K1[15] = temp[i] << 1; + BlockXor(K1, K1, R_b); + } + + if((K1[0] >> 7) == 0x00) // K1 << 1 + { + for (i = 0; i < 15; i++) + { + K2[i] = (K1[i] << 1) | (K1[i+1] >> 7); + } + K2[15] = K1[i] << 1; + } + else if ((K1[0] >> 7) == 0x01) + { + for (i = 0; i < 15; i++) + { + K2[i] = (K1[i] << 1) | (K1[i+1] >> 7); + } + K2[15] = K1[i] << 1; + BlockXor(K2, K2, R_b); + } + +// LOG4DRM_BUFFER(&CryptoLogCTX), LOG_DEBUG, "K1", K1, 16); +// LOG4DRM_BUFFER(&CryptoLogCTX), LOG_DEBUG, "K2", K2, 16); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn int SDRM_CMAC_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen) + * @brief process data blocks + * + * @param crt [out]crypto parameter + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CMAC_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen) +{ + int Loop; + cc_u8 *ptr; + + if (msgLen == 0) + { + return CRYPTO_SUCCESS; + } + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->cmacctx == NULL) || (msg == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (msgLen + crt->ctx->cmacctx->BlockLen <= SDRM_AES_BLOCK_SIZ) + { + memcpy(crt->ctx->cmacctx->Block + crt->ctx->cmacctx->BlockLen, msg, msgLen); + crt->ctx->cmacctx->BlockLen += msgLen; + return CRYPTO_SUCCESS; + } + + memcpy(crt->ctx->cmacctx->Block + crt->ctx->cmacctx->BlockLen, msg, SDRM_AES_BLOCK_SIZ - crt->ctx->cmacctx->BlockLen); + SDRM_CBC_Enc(ID_AES128, crt->ctx->cmacctx->IV, crt->ctx->cmacctx->Block, crt->ctx->cmacctx->RoundKey, crt->ctx->cmacctx->IV); + + Loop = (msgLen + crt->ctx->cmacctx->BlockLen - 1) / SDRM_AES_BLOCK_SIZ - 1; + ptr = msg + SDRM_AES_BLOCK_SIZ - crt->ctx->cmacctx->BlockLen; + crt->ctx->cmacctx->BlockLen = (cc_u32)(msg + msgLen - ptr) - Loop * SDRM_AES_BLOCK_SIZ; + + while (Loop > 0) + { + SDRM_CBC_Enc(ID_AES128, crt->ctx->cmacctx->IV, ptr, crt->ctx->cmacctx->RoundKey, crt->ctx->cmacctx->IV); + Loop--; + ptr += SDRM_AES_BLOCK_SIZ; + } + +// LOG4DRM_BUFFER(&CryptoLogCTX), LOG_DEBUG, "Block", crt->ctx->cmacctx->IV, 16); + + memcpy(crt->ctx->cmacctx->Block, ptr, crt->ctx->cmacctx->BlockLen); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn int SDRM_CMAC_final(CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen) + * @brief process last data block + * + * @param crt [in]crypto parameter + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_CMAC_final(CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen) +{ + cc_u8 *K1, *K2; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->cmacctx == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + K1 = crt->ctx->cmacctx->K1; + K2 = crt->ctx->cmacctx->K2; + + if (crt->ctx->cmacctx->BlockLen == SDRM_AES_BLOCK_SIZ) + { + BlockXor(crt->ctx->cmacctx->Block, crt->ctx->cmacctx->Block, K1); + } + else + { + crt->ctx->cmacctx->IV[crt->ctx->cmacctx->BlockLen] ^= 0x80; + BlockXor(crt->ctx->cmacctx->IV, crt->ctx->cmacctx->IV, K2); // input = input XOR K2 + memset(crt->ctx->cmacctx->Block + crt->ctx->cmacctx->BlockLen, 0, SDRM_AES_BLOCK_SIZ - crt->ctx->cmacctx->BlockLen); + } + + SDRM_CBC_Enc(ID_AES128, output, crt->ctx->cmacctx->Block, crt->ctx->cmacctx->RoundKey, crt->ctx->cmacctx->IV); + + if (outputLen != NULL) + { + *outputLen = 16; + } + + return CRYPTO_SUCCESS; +} + + +/* + * @fn int SDRM_CMAC_getMAC(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen) + * @brief generate c-mac code + * + * @param crt [in]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_CMAC_getMAC(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen) +{ + int result; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->cmacctx == NULL) || (Key == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + result = SDRM_CMAC_init(crt, Key, KeyLen); + if (result != CRYPTO_SUCCESS) + { + return result; + } + + result = SDRM_CMAC_update(crt, msg, msgLen); + if (result != CRYPTO_SUCCESS) + { + return result; + } + + return SDRM_CMAC_final(crt, output, outputLen); +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_dh.c b/ssflib/dep/cryptocore/source/middle/cc_dh.c new file mode 100755 index 0000000..3bfffbc --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_dh.c @@ -0,0 +1,333 @@ +/** + * \file ecdh.c + * @brief implementation of EC Diffie-Hellman Key Exchange Protocol + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/27 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_ANSI_x931.h" +#include "cc_bignum.h" +#include "cc_fast_math.h" +#include "cc_dh.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/** + * @fn SDRM_GenerateDHParam(CryptoCoreContainer* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned int* pGenerator) + * @brief generate parameters for Diffie-Hellman protocol + * + * @param [out] crt context + * @param [out] pPrime prime number + * @param [in] nPrimeLen size of pPrime buffer + * @param [out] pGenerator generator value + * + * @return int + */ +int SDRM_GenerateDHParam(CryptoCoreContainer* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned char* pGenerator) +{ + SDRM_DHContext* ctx; + cc_u32 Seed[4]; + int i, sp, t1; + SDRM_BIG_NUM *p = NULL; + SDRM_BIG_NUM *g = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dhctx == NULL) || (pPrime == NULL) || (pGenerator == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->dhctx; + + p = SDRM_BN_Init(nPrimeLen / 2 + 1); + if (p == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + g = SDRM_BN_Init(nPrimeLen / 2 + 1); + if (g == NULL) + { + free(p); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + + t1 = (nPrimeLen * 8 - 1) % 32; + + //set security parameter for miller-rabin probabilistic primality test + if (nPrimeLen >= 128) + { + sp = 3; + } + else if (nPrimeLen >= 64) + { + sp = 5; + } + else if (nPrimeLen >= 15) + { + sp = 15; + } + else + { + sp = 30; + } + + //generate p + p->Length = (nPrimeLen + 3) / 4; + do { + SDRM_RNG_X931((cc_u8 *)Seed, nPrimeLen * 8, (cc_u8*)p->pData); + p->pData[0] |= 1L; + p->pData[p->Length - 1] &= ~((-1L) << t1); + p->pData[p->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(p, sp) != CRYPTO_ISPRIME); + + SDRM_I2OSP(p, nPrimeLen, pPrime); + + memset(pGenerator, 0x00, nPrimeLen - 1); + pGenerator[nPrimeLen - 1] = DH_DEFAULT_GENERATOR; + + SDRM_OS2BN(pGenerator, nPrimeLen, g); + + if (ctx->p != NULL) + { + free(ctx->p); + } + ctx->p = p; + + if (ctx->g != NULL) + { + free(ctx->g); + } + ctx->g = g; + + ctx->PrimeLen = nPrimeLen; + + return CRYPTO_SUCCESS; +} + +/** + * @fn SDRM_SetDHParam(CryptoCoreContainer* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned int pGenerator) + * @brief set parameters for Diffie-Hellman protocol + * + * @param [out] crt context + * @param [in] pPrime prime number + * @param [in] nPrimeLen size of pPrime buffer + * @param [in] pGenerator generator value + * + * @return int + */ +int SDRM_SetDHParam(CryptoCoreContainer* crt, unsigned char* pPrime, unsigned int nPrimeLen, unsigned char* pGenerator, unsigned int nGeneratorLen) +{ + SDRM_DHContext* ctx; + SDRM_BIG_NUM* p = NULL; + SDRM_BIG_NUM* g = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dhctx == NULL) || (pPrime == NULL) || (pGenerator == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->dhctx; + + p = SDRM_BN_Init(nPrimeLen / 2 + 1); + if (p == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + g = SDRM_BN_Init(nPrimeLen / 2 + 1); + if (g == NULL) + { + free(p); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_OS2BN(pPrime, nPrimeLen, p); + SDRM_OS2BN(pGenerator, nGeneratorLen, g); + + ctx->PrimeLen = nPrimeLen; + ctx->p = p; + ctx->g = g; + + return CRYPTO_SUCCESS; +} + +/** + * @fn SDRM_GenerateDHPrivate(CryptoCoreContainer* crt, unsigned char* pPub) + * @brief generate private value and calculate public value + * + * @param [in] crt context + * @param [out] pPriv private value + * @param [out] pPub public value + * + * @return int + */ +int SDRM_GenerateDHPrivate(CryptoCoreContainer* crt, unsigned char* pPriv, unsigned char* pPub) +{ + SDRM_DHContext* ctx; + cc_u32 Seed[4] = {0,}; + int retVal; + SDRM_BIG_NUM* priv = NULL; + SDRM_BIG_NUM* pub = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dhctx == NULL) || (pPriv == NULL) || (pPub == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->dhctx; + + priv = SDRM_BN_Init(ctx->PrimeLen / 2 + 1); + if (priv == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + pub = SDRM_BN_Init(ctx->PrimeLen / 2 + 1); + if (pub == NULL) + { + free(priv); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + //generate priv + priv->Length = (ctx->PrimeLen + 3) / 4; + SDRM_RNG_X931((cc_u8 *)Seed, ctx->PrimeLen * 8, (cc_u8*)priv->pData); + SDRM_BN_ModRed(priv, priv, ctx->p); + +#ifndef _OP64_NOTSUPPORTED + retVal = SDRM_BN_ModExp2(pub, ctx->g, priv, ctx->p); +#else + retVal = SDRM_BN_ModExp(pub, ctx->g, priv, ctx->p); +#endif //_OP64_NOTSUPPORTED + + if (retVal != CRYPTO_SUCCESS) + { + free(priv); + free(pub); + + return retVal; + } + + SDRM_I2OSP(priv, ctx->PrimeLen, pPriv); + SDRM_I2OSP(pub, ctx->PrimeLen, pPub); + + free(priv); + free(pub); + + return CRYPTO_SUCCESS; +} + +/** + * @fn SDRM_GetDHSharedSecret(CryptoCoreContainer* crt, unsigned char* pPriv, unsigned char* pPub, unsigned char* pSharedSecret) + * @brief calculate shared secret + * + * @param [in] crt context + * @param [in] Priv private value + * @param [in] pPub guest's public value + * @param [out] pSharedSecret public value + * + * @return int + */ +int SDRM_GetDHSharedSecret(CryptoCoreContainer* crt, unsigned char* pPriv, unsigned char* pPub, unsigned char* pSharedSecret) +{ + SDRM_DHContext* ctx; + SDRM_BIG_NUM* priv = NULL; + SDRM_BIG_NUM* pub = NULL; + SDRM_BIG_NUM* SharedSecret = NULL; + int retVal; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dhctx == NULL) || (pPriv == NULL) || (pPub == NULL) || (pSharedSecret == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->dhctx; + + priv = SDRM_BN_Init(ctx->PrimeLen / 2 + 1); + if (priv == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + pub = SDRM_BN_Init(ctx->PrimeLen / 2 + 1); + if (pub == NULL) + { + free(priv); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SharedSecret = SDRM_BN_Init(ctx->PrimeLen / 2 + 1); + if (SharedSecret == NULL) + { + free(priv); + free(pub); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_OS2BN(pPriv, ctx->PrimeLen, priv); + SDRM_OS2BN(pPub, ctx->PrimeLen, pub); + +#ifndef _OP64_NOTSUPPORTED + retVal = SDRM_BN_ModExp2(SharedSecret, pub, priv, ctx->p); +#else + retVal = SDRM_BN_ModExp(SharedSecret, pub, priv, ctx->p); +#endif //_OP64_NOTSUPPORTED + + if (retVal != CRYPTO_SUCCESS) + { + free(priv); + free(pub); + free(SharedSecret); + + return retVal; + } + + SDRM_I2OSP(SharedSecret, ctx->PrimeLen, pSharedSecret); + + free(priv); + free(pub); + free(SharedSecret); + + return CRYPTO_SUCCESS; +} + +/** + * @fn SDRM_FreeDHContext(CryptoCoreContainer* crt) + * @brief free context buffer + * + * @param [in] crt context + */ +void SDRM_FreeDHContext(SDRM_DHContext* ctx) +{ + if (ctx != NULL) + { + if (ctx->p != NULL) + { + free(ctx->p); + } + + if (ctx->g != NULL) + { + free(ctx->g); + } + + memset(ctx, 0x00, sizeof(SDRM_DHContext)); + } +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_dsa.c b/ssflib/dep/cryptocore/source/middle/cc_dsa.c new file mode 100755 index 0000000..c933f85 --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_dsa.c @@ -0,0 +1,608 @@ +/** + * \file dsa.c + * @brief implementation of dsa signature/verifycation + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/23 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_dsa.h" +#include "cc_bignum.h" +#include "cc_sha1.h" +#include "cc_ANSI_x931.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_Add_DW2BA + * @brief Add a UINT32 value to a Byte Array + * function works correctly only when dLen >= 4 + * + * @param BA [i/o]byte array + * @param dLen [in]byte-length of BA + * @param val [in]value to add + * + * @return void + */ +void SDRM_Add_DW2BA(cc_u8* BA, cc_u32 dLen, cc_u32 val) +{ + cc_u32 i, DIGIT = 0; + + if (dLen >= 4) + { + DIGIT = BA[dLen - 4] ^ (BA[dLen - 3] << 8) ^ (BA[dLen - 2] << 16) ^ (BA[dLen - 1] << 24); + DIGIT += val; + BA[dLen - 4] = (cc_u8)(DIGIT ) & 0xff; + BA[dLen - 3] = (cc_u8)(DIGIT >> 8 ) & 0xff; + BA[dLen - 2] = (cc_u8)(DIGIT >> 16) & 0xff; + BA[dLen - 1] = (cc_u8)(DIGIT >> 24) & 0xff; + + if (DIGIT < val) + { + for (i = dLen - 5; i != (cc_u32)-1; i--) + { + if (++BA[i] != 0) + { + return; + } + } + } + } + + return; +} + +/* + * @fn SDRM_DSA_InitCrt + * @brief generate DSA Context + * + * @return pointer to the generated context + * \n NULL if memory allocation is failed + */ +SDRM_DSAContext *SDRM_DSA_InitCrt() +{ + SDRM_DSAContext *ctx; + cc_u8 *pbBuf = (cc_u8*)malloc(sizeof(SDRM_DSAContext) + SDRM_DSA_ALLOC_SIZE * 5); + + if (pbBuf == NULL) + { + return NULL; + } + + ctx = (SDRM_DSAContext*)(void*)pbBuf; + ctx->p = SDRM_BN_Alloc((cc_u8*)ctx + sizeof(SDRM_DSAContext), SDRM_DSA_BN_BUFSIZE); + ctx->q = SDRM_BN_Alloc((cc_u8*)ctx->p + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + ctx->al = SDRM_BN_Alloc((cc_u8*)ctx->q + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + ctx->y = SDRM_BN_Alloc((cc_u8*)ctx->al + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + ctx->a = SDRM_BN_Alloc((cc_u8*)ctx->y + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + + return ctx; +} + +/* + * @fn int SDRM_DSA_SetParam(CryptoCoreContainer *crt, + cc_u8 *DSA_P_Data, cc_u32 DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 DSA_G_Len) + * @brief set DSA parameters + * + * @param crt [out]dsa context + * @param DSA_P_Data [in]octet string of p value + * @param DSA_P_Len [in]legnth of p_val + * @param DSA_Q_Data [in]octet string of q value + * @param DSA_Q_Len [in]legnth of q_val + * @param DSA_G_Data [in]octet string of al value + * @param DSA_G_Len [in]legnth of al_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_SetParam(CryptoCoreContainer *crt, + cc_u8 *DSA_P_Data, cc_u32 DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 DSA_G_Len) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dsactx == NULL) || (DSA_P_Data == NULL) || (DSA_Q_Data == NULL) || (DSA_G_Data == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_OS2BN(DSA_P_Data, DSA_P_Len, crt->ctx->dsactx->p); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->dsactx->p); + + SDRM_OS2BN(DSA_Q_Data, DSA_Q_Len, crt->ctx->dsactx->q); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->dsactx->q); + + SDRM_OS2BN(DSA_G_Data, DSA_G_Len, crt->ctx->dsactx->al); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->dsactx->al); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn int SDRM_DSA_SetKeyPair(CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 DSA_X_Len) + * @brief set DSA parameters + * + * @param crt [out]dsa context + * @param DSA_Y_Data [in]octet string of y value + * @param DSA_Y_Len [in]legnth of y_val + * @param DSA_X_Data [in]octet string of a value + * @param DSA_X_Len [in]legnth of a_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_SetKeyPair(CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 DSA_X_Len) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (DSA_Y_Data != NULL) + { + SDRM_OS2BN(DSA_Y_Data, DSA_Y_Len, crt->ctx->dsactx->y); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->dsactx->y); + } + + if (DSA_X_Data != NULL) + { + SDRM_OS2BN(DSA_X_Data, DSA_X_Len, crt->ctx->dsactx->a); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->dsactx->a); + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_DSA_GenParam(CryptoCoreContainer *crt, cc_u32 T_Siz, + cc_u8 *DSA_P_Data, cc_u32 *DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 *DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 *DSA_G_Len) + * @brief generate and set DSA parameters + * + * @param crt [out]dsa context + * @param T_Siz [in]fix the length of p to 512 + 64t bit (0 <= T_Siz <= 8) + * @param DSA_P_Data [out]octet string of p value + * @param DSA_P_Len [out]legnth of p_val + * @param DSA_Q_Data [out]octet string of q value + * @param DSA_Q_Len [out]legnth of q_val + * @param DSA_G_Data [out]octet string of al value + * @param DSA_G_Len [out]legnth of al_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_GenParam(CryptoCoreContainer *crt, cc_u32 T_Siz, + cc_u8 *DSA_P_Data, cc_u32 *DSA_P_Len, + cc_u8 *DSA_Q_Data, cc_u32 *DSA_Q_Len, + cc_u8 *DSA_G_Data, cc_u32 *DSA_G_Len) +{ + cc_u32 i, k, L, n/*, g*/; + cc_u8 pbTemp[260], pbSeed[64]; + SDRM_SHA1Context ctx; + SDRM_BIG_NUM /**BN_A, */*BN_G, *BN_P, *BN_Q, *BN_AL, *BN_Temp; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (T_Siz > 8) + { + return CRYPTO_INVALID_ARGUMENT; + } + + L = 512 + 64 * T_Siz; + n = (L - 1) / 160; +// g = (L - 1) % 160; + + + pbBuf = (cc_u8*)malloc(SDRM_DSA_ALLOC_SIZE * 2); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_G = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_DSA_BN_BUFSIZE); + BN_Temp = SDRM_BN_Alloc((cc_u8*)BN_G + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + + BN_P = crt->ctx->dsactx->p; + BN_Q = crt->ctx->dsactx->q; + BN_AL = crt->ctx->dsactx->al; +// BN_A = crt->ctx->dsactx->a; + + //generate p and q + while(1) + { + do + { + //choose a random seed s of bitlength g >= 160 + for (i = 0; i < SDRM_SHA1_BLOCK_SIZ; i++) + { + pbSeed[i] = (rand() << 16) ^ rand(); + } + pbSeed[0] |= 0x80; + pbSeed[SDRM_SHA1_BLOCK_SIZ - 1] |= 0x01; + + //U = H(s) xor H((s + 1) mod g) + SDRM_SHA1_Init(&ctx); + SDRM_SHA1_Update(&ctx, pbSeed, SDRM_SHA1_BLOCK_SIZ); + SDRM_SHA1_Final(&ctx, pbTemp); + + SDRM_INC_BA(pbSeed, SDRM_SHA1_BLOCK_SIZ); + + SDRM_SHA1_Init(&ctx); + SDRM_SHA1_Update(&ctx, pbSeed, SDRM_SHA1_BLOCK_SIZ); + SDRM_SHA1_Final(&ctx, pbTemp + SDRM_SHA1_BLOCK_SIZ); + + for (i = 0; i < SDRM_SHA1_BLOCK_SIZ / sizeof(cc_u32); i++) + { + ((cc_u32*)(void*)pbTemp)[i] ^= ((cc_u32*)(void*)pbTemp)[i + SDRM_SHA1_BLOCK_SIZ / sizeof(cc_u32)]; + } + + pbTemp[0] |= 0x80; + pbTemp[SDRM_SHA1_BLOCK_SIZ - 1] |= 0x01; + + SDRM_OS2BN(pbTemp, SDRM_SHA1_BLOCK_SIZ, BN_Q); + } + while(SDRM_BN_MILLER_RABIN(BN_Q, 18) != CRYPTO_SUCCESS); + + SDRM_INC_BA(pbSeed, SDRM_SHA1_BLOCK_SIZ); + + for (i = 0; i < 4096; i++) + { + for (k = 0; k <= n; k++) + { + SDRM_SHA1_Init(&ctx); + SDRM_SHA1_Update(&ctx, pbSeed, SDRM_SHA1_BLOCK_SIZ); + SDRM_SHA1_Final(&ctx, pbTemp + (n - k) * SDRM_SHA1_BLOCK_SIZ); + SDRM_Add_DW2BA(pbSeed, SDRM_SHA1_BLOCK_SIZ, n + 2); + } + + pbTemp[(n + 1) * SDRM_SHA1_BLOCK_SIZ - L / 8] |= 0x80; + SDRM_OS2BN(pbTemp + (n + 1) * SDRM_SHA1_BLOCK_SIZ - L / 8, L / 8, BN_P); + + SDRM_BN_SHL(BN_Q, BN_Q, 1); + SDRM_BN_ModRed(BN_Temp, BN_P, BN_Q); + SDRM_BN_SHR(BN_Q, BN_Q, 1); + SDRM_BN_Sub(BN_P, BN_P, BN_Temp); + SDRM_BN_Add(BN_P, BN_P, BN_One); + + if (SDRM_CheckBitUINT32(BN_P->pData, L - 1)) + { + if (SDRM_BN_MILLER_RABIN(BN_P, 5) == CRYPTO_ISPRIME) + { + goto SUCCESS; + } + else + { + break; + } + } + } + } + +SUCCESS : + //select a generator al(alpha) of the unique cyclic group of order q in Zp + SDRM_BN_Clr(BN_Temp); + //temp = (p-1)/q + SDRM_BN_Sub(BN_Temp, BN_P, BN_One); + SDRM_BN_Div(BN_Temp, NULL, BN_Temp, BN_Q); + + do { + //select an element g excluded in Zp* + do { + SDRM_RNG_X931(pbSeed, L, (cc_u8*)BN_G->pData); + BN_G->Length = L / 32 + 1; + SDRM_BN_OPTIMIZE_LENGTH(BN_G); + } + while(SDRM_BN_Cmp(BN_G, BN_P) >= 0); + + //al(alpha) = g^temp mod p + SDRM_BN_ModExp(BN_AL, BN_G, BN_Temp, BN_P); + } + while (SDRM_BN_Cmp(BN_AL, BN_One) == 0); + + //write output + if (DSA_P_Data != NULL) + { + SDRM_I2OSP(BN_P, L / 8, DSA_P_Data); + } + + if (DSA_P_Len != NULL) + { + *DSA_P_Len = L / 8; + } + + if (DSA_Q_Data != NULL) + { + SDRM_I2OSP(BN_Q, 20, DSA_Q_Data); + } + + if (DSA_Q_Len != NULL) + { + *DSA_Q_Len = 20; + } + + if (DSA_G_Data != NULL) + { + SDRM_I2OSP(BN_AL, BN_AL->Length * 4, DSA_G_Data); + } + + if (DSA_G_Len != NULL) + { + *DSA_G_Len = BN_AL->Length * 4; + } + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_DSA_GenKeypair(CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 *DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 *DSA_X_Len) + * @brief generate and set DSA parameters + * + * @param crt [out]dsa context + * @param DSA_Y_Data [out]octet string of y value + * @param DSA_Y_Len [out]legnth of y_val + * @param DSA_X_Data [out]octet string of a value + * @param DSA_X_Len [out]legnth of a_val + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if input parameter pointer is null + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_ERROR if conversion is failed + */ +int SDRM_DSA_GenKeypair(CryptoCoreContainer *crt, + cc_u8 *DSA_Y_Data, cc_u32 *DSA_Y_Len, + cc_u8 *DSA_X_Data, cc_u32 *DSA_X_Len) +{ + SDRM_BIG_NUM *BN_A; + cc_u32 Seed[4], i; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + BN_A = crt->ctx->dsactx->a; + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + + //Select a random integer a such that 1 <= a <= q-1 + do { + SDRM_RNG_X931((cc_u8*)Seed, 160, (cc_u8*)BN_A->pData); + BN_A->Length = 6; //6 = 160 / 32 + 1 + SDRM_BN_OPTIMIZE_LENGTH(BN_A); + } + while(SDRM_BN_Cmp(BN_A, crt->ctx->dsactx->q) >= 0); + + //y = al ^ a mod p + SDRM_BN_ModExp(crt->ctx->dsactx->y, crt->ctx->dsactx->al, BN_A, crt->ctx->dsactx->p); + + + //write output + if (DSA_Y_Data != NULL) + { + SDRM_I2OSP(crt->ctx->dsactx->y, crt->ctx->dsactx->y->Length * 4, DSA_Y_Data); + } + + if (DSA_Y_Len != NULL) + { + *DSA_Y_Len = crt->ctx->dsactx->y->Length * 4; + } + + if (DSA_X_Data != NULL) + { + SDRM_I2OSP(BN_A, BN_A->Length * 4, DSA_X_Data); + } + + if (DSA_X_Len != NULL) + { + *DSA_X_Len = BN_A->Length * 4; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_DSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [out]generated signature + * @param signLen [out]byte-length of signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_DSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) +{ + cc_u8 pbSeed[16] = {0}; + SDRM_BIG_NUM *BN_P, *BN_Q, *BN_AL, *BN_A; + SDRM_BIG_NUM *BN_r, *BN_s, *BN_k, *BN_hash, *BN_ar, *temp1, *temp2; + + cc_u8* pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dsactx == NULL) || (crt->ctx->dsactx->a == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + pbBuf = (cc_u8*)malloc(SDRM_DSA_ALLOC_SIZE * 7); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_r = SDRM_BN_Alloc( pbBuf, SDRM_DSA_BN_BUFSIZE); + BN_s = SDRM_BN_Alloc((cc_u8*)BN_r + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + BN_k = SDRM_BN_Alloc((cc_u8*)BN_s + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + BN_hash = SDRM_BN_Alloc((cc_u8*)BN_k + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + BN_ar = SDRM_BN_Alloc((cc_u8*)BN_hash + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)BN_ar + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + + BN_P = crt->ctx->dsactx->p; + BN_Q = crt->ctx->dsactx->q; + BN_AL = crt->ctx->dsactx->al; + BN_A = crt->ctx->dsactx->a; + + //select a random secret integer k, 0 < k < q + do { + SDRM_RNG_X931(pbSeed, 160, (cc_u8*)BN_k->pData); + BN_k->Length = 6; //6 = 160 / 32 + 1 + SDRM_BN_OPTIMIZE_LENGTH(BN_k); + } + while(SDRM_BN_Cmp(BN_k, BN_Q) > 0); + + SDRM_BN_ModExp(temp1, BN_AL, BN_k, BN_P); + //r = (al ^ k mod p) mod q + SDRM_BN_ModRed(BN_r, temp1, BN_Q); + + SDRM_BN_ModInv(temp1, BN_k, BN_Q); + + SDRM_OS2BN((cc_u8*)hash, hashLen, BN_hash); + + SDRM_BN_Mul(BN_ar, BN_A, BN_r); + SDRM_BN_Add(temp2, BN_hash, BN_ar); + + SDRM_BN_ModRed(temp2, temp2, BN_Q); + + SDRM_BN_ModMul(BN_s, temp1, temp2, BN_Q); + + SDRM_I2OSP(BN_r, 20, signature); + SDRM_I2OSP(BN_s, 20, signature + 20); + + if (signLen != NULL) + { + *signLen = 40; + } + + free(pbBuf); + + return CRYPTO_SUCCESS; + } + +/* + * @fn int SDRM_DSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [in]signature + * @param signLen [in]byte-length of signature + * @param result [in]result of veryfing signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if the length of signature is invalid + */ +int SDRM_DSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result) +{ + SDRM_BIG_NUM *w, *u1, *u2, *v, *BNH_m, *BN_r, *BN_s; + SDRM_BIG_NUM *temp1, *temp2, *temp3; + + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->dsactx == NULL) || (crt->ctx->dsactx->y == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + pbBuf = (cc_u8*)malloc(SDRM_DSA_ALLOC_SIZE * 10); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + w = SDRM_BN_Alloc( pbBuf, SDRM_DSA_BN_BUFSIZE); + u1 = SDRM_BN_Alloc((cc_u8*)w + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + u2 = SDRM_BN_Alloc((cc_u8*)u1 + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + v = SDRM_BN_Alloc((cc_u8*)u2 + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + BNH_m = SDRM_BN_Alloc((cc_u8*)v + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + BN_r = SDRM_BN_Alloc((cc_u8*)BNH_m + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + BN_s = SDRM_BN_Alloc((cc_u8*)BN_r + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)BN_s + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + temp3 = SDRM_BN_Alloc((cc_u8*)temp2 + SDRM_DSA_ALLOC_SIZE, SDRM_DSA_BN_BUFSIZE); + + + if ((SDRM_BN_Cmp(BN_r, crt->ctx->dsactx->q) >= 0) || (SDRM_BN_Cmp(BN_s, crt->ctx->dsactx->q) >= 0)) //r < q and s < q + { + free(pbBuf); + return CRYPTO_ERROR; + } + + if (signLen != 40) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + + SDRM_OS2BN((cc_u8*)signature, 20, BN_r); + SDRM_OS2BN((cc_u8*)signature + 20, 20, BN_s); + + + SDRM_BN_ModInv(w, BN_s, crt->ctx->dsactx->q); //w = s^-1 mod q + SDRM_OS2BN((cc_u8*)hash, 20, BNH_m); + + SDRM_BN_ModMul(u1, w, BNH_m, crt->ctx->dsactx->q); //u1 = w x h(m) mod q + SDRM_BN_ModMul(u2, BN_r, w, crt->ctx->dsactx->q); //u2 = rw mod q + + SDRM_BN_ModExp(temp1, crt->ctx->dsactx->al, u1, crt->ctx->dsactx->p); //temp1 = alpha^u1 mod p + SDRM_BN_ModExp(temp2, crt->ctx->dsactx->y, u2, crt->ctx->dsactx->p); //temp2 = y^u2 mod p + + SDRM_BN_ModMul(temp3, temp1, temp2, crt->ctx->dsactx->p); //temp3 = (alpha^u1 x y^u2 mod p) mod p + + SDRM_BN_ModRed(v, temp3, crt->ctx->dsactx->q); //v = (alpha^u1 x y^u2 mod p) mod q + +// SDRM_PrintBN("v : ", v); +// SDRM_PrintBN("Hash : ", BNH_m); + + if (SDRM_BN_Cmp(v, BN_r) == 0) + { + *result = CRYPTO_VALID_SIGN; + } + else + { + *result = CRYPTO_INVALID_SIGN; + } + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_ecdh.c b/ssflib/dep/cryptocore/source/middle/cc_ecdh.c new file mode 100755 index 0000000..5882576 --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_ecdh.c @@ -0,0 +1,204 @@ +/** + * \file ecdh.c + * @brief implementation of EC Diffie-Hellman Key Exchange Protocol + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/27 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_ecdh.h" +#include "cc_ANSI_x931.h" +#include "cc_ecc.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_generateDH1stPhaseKey + * @brief generate Xk and its Xv + * + * @param crt [in]crypto context + * @param pchXk [out]Generated Random Number + * @param pchXv [out]DH 1st phase value + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_generateDH1stPhaseKey(CryptoCoreContainer *crt, cc_u8 *pchXk, cc_u8 *pchXv) +{ + cc_u8 Si_ANSI_X9_31[SDRM_X931_SEED_SIZ]; + + SDRM_BIG_NUM *BN_Xk, *BN_Temp; + SDRM_EC_POINT *kP; + SDRM_ECC_CTX *ctx; + int i; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdhctx == NULL) || (pchXk == NULL) || (pchXv == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->ecdhctx; + + for (i = 0; i < SDRM_X931_SEED_SIZ; i++) + { + Si_ANSI_X9_31[i] = ((rand() << 16) + rand()) & 0xff; + } + + + BN_Temp = SDRM_BN_Init(crt->ctx->ecdsactx->uDimension >> 3); + if (BN_Temp == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_Xk = SDRM_BN_Init(crt->ctx->ecdsactx->uDimension >> 3); + if (BN_Xk == NULL) + { + free(BN_Temp); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_BN_Sub(BN_Temp, ctx->ECC_n, BN_One); + do { + SDRM_RNG_X931(Si_ANSI_X9_31, crt->ctx->ecdsactx->uDimension, pchXk); + SDRM_OS2BN(pchXk, crt->ctx->ecdsactx->uDimension >> 3, BN_Xk); + } + while ((SDRM_BN_Cmp(BN_Xk, BN_One) < 0) || (SDRM_BN_Cmp(BN_Xk, BN_Temp) > 0)); + + kP = SDRM_ECC_Init(); + if (kP == NULL) + { + free(BN_Temp); + free(BN_Xk); + + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if (SDRM_CTX_EC_kP(ctx, kP, ctx->ECC_G, BN_Xk) == CRYPTO_MEMORY_ALLOC_FAIL) + { + free(BN_Temp); + free(BN_Xk); + free(kP); + + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_BN2OS(kP->x, crt->ctx->ecdsactx->uDimension >> 3, pchXv); + SDRM_BN2OS(kP->y, crt->ctx->ecdsactx->uDimension >> 3, pchXv + (crt->ctx->ecdsactx->uDimension >> 3)); + + free(BN_Temp); + free(BN_Xk); + free(kP); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_generateDHKey + * @brief genenrate auth key with Xk and Yv + * + * @param crt [in]crypto context + * @param pchXk [in]Generated Random Number + * @param pchYv [in]DH 1st phase value + * @param pchKauth [out]authentication key + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_generateDHKey(CryptoCoreContainer *crt, cc_u8* pchXk, cc_u8* pchYv, cc_u8* pchKauth) +{ + SDRM_BIG_NUM *BN_Xk; + SDRM_EC_POINT *kP, *EC_Yv; + SDRM_ECC_CTX *ctx; + int retVal; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdhctx == NULL) || (pchXk == NULL) || (pchYv == NULL) || (pchKauth == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->ecdhctx; + + BN_Xk = SDRM_BN_Init(crt->ctx->ecdsactx->uDimension >> 3); + if (BN_Xk == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + retVal = SDRM_OS2BN(pchXk, crt->ctx->ecdsactx->uDimension >> 3, BN_Xk); + if (retVal != CRYPTO_SUCCESS) + { + free(BN_Xk); + return retVal; + } + + kP = SDRM_ECC_Init(); + if (kP == NULL) + { + free(BN_Xk); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + EC_Yv = SDRM_ECC_Init(); + if (EC_Yv == NULL) + { + free(BN_Xk); + free(kP); + + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_EC_CLR(EC_Yv); + retVal = SDRM_OS2BN(pchYv, crt->ctx->ecdsactx->uDimension >> 3, EC_Yv->x); + if (retVal != CRYPTO_SUCCESS) + { + free(BN_Xk); + free(kP); + free(EC_Yv); + + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + retVal = SDRM_OS2BN(pchYv + (crt->ctx->ecdsactx->uDimension >> 3), crt->ctx->ecdsactx->uDimension >> 3, EC_Yv->y); + if (retVal != CRYPTO_SUCCESS) + { + free(BN_Xk); + free(kP); + free(EC_Yv); + + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if (SDRM_CTX_EC_kP(ctx, kP, EC_Yv, BN_Xk) == CRYPTO_MEMORY_ALLOC_FAIL) + { + free(BN_Xk); + free(kP); + free(EC_Yv); + + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + retVal = SDRM_BN2OS(kP->x, crt->ctx->ecdsactx->uDimension >> 3, pchKauth); + if (retVal != CRYPTO_SUCCESS) + { + free(BN_Xk); + free(kP); + free(EC_Yv); + + return retVal; + } + + free(BN_Xk); + free(kP); + free(EC_Yv); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_ecdsa.c b/ssflib/dep/cryptocore/source/middle/cc_ecdsa.c new file mode 100755 index 0000000..7a7918c --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_ecdsa.c @@ -0,0 +1,666 @@ +/** + * \file ecdsa.c + * @brief implementation of public key signature algorithm + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/13 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32_WCE +#include +#endif +#include +#include "cc_ecdsa.h" +#include "cc_ANSI_x931.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_CTX_ECDSA_KEY_GEN + * @brief generate signature + * + * @param ctx [out]ecc context + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_NULL_POINTER if any argument is a null pointer + */ +int SDRM_CTX_ECDSA_KEY_GEN(SDRM_ECC_CTX *ctx) +{ + int i, retVal; + cc_u32 Seed[4]; + SDRM_BIG_NUM *BN_d, *BN_temp; + SDRM_EC_POINT *kP; + + cc_u8 *pbBuf = NULL; + + if (ctx == NULL) + { + return CRYPTO_NULL_POINTER; + } + + pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 2); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_d = SDRM_BN_Alloc( pbBuf , SDRM_ECC_BN_BUFSIZE); + BN_temp = SDRM_BN_Alloc((cc_u8*)BN_d + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + kP = SDRM_ECC_Init(); + if (kP == NULL) + { + free(pbBuf); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + + SDRM_BN_Sub(BN_temp, ctx->ECC_n, BN_One); + do { + SDRM_RNG_X931((cc_u8 *)Seed, ctx->uDimension, (cc_u8*)BN_d->pData); + BN_d->Length = ctx->uDimension / 32; + } + while ((SDRM_BN_Cmp(BN_d, BN_One) < 0) || (SDRM_BN_Cmp(BN_d, BN_temp) > 0)); + + SDRM_BN_OPTIMIZE_LENGTH(BN_d); + + SDRM_EC_SET_ZERO(kP); + retVal = SDRM_CTX_EC_kP(ctx, kP, ctx->ECC_G, BN_d); + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + free(kP); + + return retVal; + } + + SDRM_BN_Copy(ctx->PRIV_KEY, BN_d); + SDRM_EC_COPY(ctx->PUBLIC_KEY, kP); + + free(pbBuf); + free(kP); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_ECDSA_SIG_GEN + * @brief generate signature + * + * @param ctx [in]ecc context + * @param sig [out]generated signature + * @param hash [in]hashed message + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_NULL_POINTER if any argument is a null pointer + */ +int SDRM_CTX_ECDSA_SIG_GEN(SDRM_ECC_CTX *ctx, cc_u8 *sig, cc_u8 *hash, unsigned int hashLen) +{ + int i, res = -1; + cc_u32 Seed[20]; + SDRM_BIG_NUM *BN_Tmp1, *BN_Tmp2, *BN_Tmp3; + SDRM_BIG_NUM *BN_k, *BN_r, *BN_s, *BN_hash; + SDRM_EC_POINT *kP; + + cc_u8 *pbBuf = NULL; + + if ((ctx== NULL) || (sig == NULL) || (hash == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 7); + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_Tmp1 = SDRM_BN_Alloc( pbBuf, SDRM_ECC_BN_BUFSIZE); + BN_Tmp2 = SDRM_BN_Alloc((cc_u8*)BN_Tmp1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_Tmp3 = SDRM_BN_Alloc((cc_u8*)BN_Tmp2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_k = SDRM_BN_Alloc((cc_u8*)BN_Tmp3 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_r = SDRM_BN_Alloc((cc_u8*)BN_k + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_s = SDRM_BN_Alloc((cc_u8*)BN_r + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_hash = SDRM_BN_Alloc((cc_u8*)BN_s + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + kP = SDRM_ECC_Init(); + if (kP == NULL) + { + free(pbBuf); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + + while(1) + { + while(1) + { + // 1. [1, r-1] »çÀÌÀÇ ³­¼ö k ¼±Åà + SDRM_BN_Sub(BN_Tmp1, ctx->ECC_n, BN_One); + do { + SDRM_RNG_X931((cc_u8 *)Seed, ctx->uDimension, (cc_u8*)BN_k->pData); + BN_k->Length = ctx->uDimension / 32; + } + while((SDRM_BN_Cmp(BN_k, BN_One) < 0) || (SDRM_BN_Cmp(BN_k, BN_Tmp1) > 0)); + + // 2. kP = (x1, y1), r = x1 mod n(&ctx.ECC_n) °è»ê. r = 0 À̸é k ´Ù½Ã ¼±Åà + SDRM_EC_SET_ZERO(kP); + res = SDRM_CTX_EC_kP(ctx, kP, ctx->ECC_G, BN_k); + if (res != CRYPTO_SUCCESS) + { + free(pbBuf); + free(kP); + + return res; + } + + //SDRM_PrintBN("kP->x", kP->x); + SDRM_BN_ModRed(BN_r, kP->x, ctx->ECC_n); + if (BN_r->Length > 0) // r = 0 À̸é k ´Ù½Ã ¼±Åà + { + break; + } + } + + // 3. k^{-1} mod n °è»ê. + SDRM_BN_ModInv(BN_Tmp1, BN_k, ctx->ECC_n); + + //SDRM_PrintBN("BN_k", BN_k); + //SDRM_PrintBN("ctx->ECC_n", ctx->ECC_n); + //SDRM_PrintBN("BN_Tmp1 = k^{-1} mod n", BN_Tmp1); + + // 4. s = k^{-1}(hash + dr) mod n °è»ê (d = private key). s = 0 À̸é 1¹øÀ¸·Î. + // BN_Tmp2 = dr + SDRM_OS2BN(hash, hashLen, BN_hash); + + SDRM_BN_ModMul(BN_Tmp2, ctx->PRIV_KEY, BN_r, ctx->ECC_n); + SDRM_BN_ModAdd(BN_Tmp3, BN_hash, BN_Tmp2, ctx->ECC_n); + SDRM_BN_ModMul(BN_s, BN_Tmp1, BN_Tmp3, ctx->ECC_n); + if (BN_s->Length > 0) + { + break; + } + } + +// (r, s) ¼­¸íÀ¸·Î Ãâ·Â. + //SDRM_PrintBN("BN_r", BN_r); + //SDRM_PrintBN("BN_s", BN_s); + + SDRM_BN2OS(BN_r, ctx->uDimension / 8, sig); + SDRM_BN2OS(BN_s, ctx->uDimension / 8, sig + ctx->uDimension / 8); + + free(kP); + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_CTX_ECDSA_SIG_VERIFY + * @brief verify ecdsa signature + * + * @param ctx [in]ecc context + * @param sig [out]generated signature + * @param signLen [out]byte-length of signature + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * + * @return CRYPTO_VALID_SIGN if given signature is valid + * \n CRYPTO_INVALID_SIGN if given signature is invalid + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + * \n CRYPTO_INVALID_ARGUMENT if any argument is out of range + * \n CRYPTO_INFINITY_INPUT if given argument represents an infinity value + */ +int SDRM_CTX_ECDSA_SIG_VERIFY(SDRM_ECC_CTX *ctx, cc_u8 *sig, int signLen, cc_u8 *hash, int hashLen) +{ + int res; + SDRM_BIG_NUM *BN_tmp, *BN_u1, *BN_u2, *BN_w, *BN_hash, *pBN_r, *pBN_s; + SDRM_EC_POINT *EC_temp1, *EC_temp2; + + cc_u8 *pbBuf = (cc_u8*)malloc(SDRM_ECC_ALLOC_SIZE * 7); + + if (!pbBuf) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_tmp = SDRM_BN_Alloc( pbBuf, SDRM_ECC_BN_BUFSIZE); + BN_u1 = SDRM_BN_Alloc((cc_u8*)BN_tmp + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_u2 = SDRM_BN_Alloc((cc_u8*)BN_u1 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_w = SDRM_BN_Alloc((cc_u8*)BN_u2 + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + BN_hash = SDRM_BN_Alloc((cc_u8*)BN_w + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + pBN_r = SDRM_BN_Alloc((cc_u8*)BN_hash+ SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + pBN_s = SDRM_BN_Alloc((cc_u8*)pBN_r + SDRM_ECC_ALLOC_SIZE, SDRM_ECC_BN_BUFSIZE); + + EC_temp1 = SDRM_ECC_Init(); + if (EC_temp1 == NULL) + { + free(pbBuf); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + EC_temp2 = SDRM_ECC_Init(); + if (EC_temp2 == NULL) + { + free(pbBuf); + free(EC_temp1); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + if ((cc_u32)signLen != (ctx->uDimension / 4)) + { + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + return CRYPTO_INVALID_ARGUMENT; + } + + SDRM_OS2BN(sig, ctx->uDimension / 8, pBN_r); + SDRM_OS2BN(sig + ctx->uDimension / 8, ctx->uDimension / 8, pBN_s); + //SDRM_PrintBN("BN_r", pBN_r); + //SDRM_PrintBN("BN_s", pBN_s); + + // 1. r°ú sÀÇ ¹üÀ§ Á¶»ç + SDRM_BN_Sub(BN_tmp, ctx->ECC_n, BN_One); + if ((SDRM_BN_Cmp(pBN_r, BN_One) < 0) || (SDRM_BN_Cmp(pBN_r, BN_tmp) > 0)) + { + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return CRYPTO_INVALID_ARGUMENT; + } + + if ((SDRM_BN_Cmp(pBN_s, BN_One) < 0) || (SDRM_BN_Cmp(pBN_s, BN_tmp) > 0)) + { + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return CRYPTO_INVALID_ARGUMENT; + } + + // 2. w = s^(-1) mod n, BN_hash °è»ê + SDRM_OS2BN(hash, hashLen, BN_hash); + res = SDRM_BN_ModInv(BN_w, pBN_s, ctx->ECC_n); +//SDRM_PrintBN("BN_w", BN_w); + + if (res != CRYPTO_SUCCESS) + { + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return res; + } + + // 3. u1 = BN_hash *w mod n, u2 = rw mod n + SDRM_BN_ModMul(BN_u1, BN_hash, BN_w, ctx->ECC_n); + SDRM_BN_ModMul(BN_u2, pBN_r, BN_w, ctx->ECC_n); +//SDRM_PrintBN("BN_u1", BN_u1); +//SDRM_PrintBN("BN_u2", BN_u2); + + // 4. (x0, y0) = u1P + u2Q, V = x0 mod n + res = SDRM_CTX_EC_2kP(ctx, EC_temp1, BN_u1, ctx->ECC_G, BN_u2, ctx->PUBLIC_KEY); + if (res != CRYPTO_SUCCESS) + { + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return res; + } + else if(EC_temp1->IsInfinity == 1) + { + res = CRYPTO_INFINITY_INPUT; + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return res; + } + +// SDRM_PrintBN("EC_temp1->x", EC_temp1->x); +// SDRM_PrintBN("ctx->ECC_n", ctx->ECC_n); + SDRM_BN_ModRed(BN_tmp, EC_temp1->x, ctx->ECC_n); + +// SDRM_PrintBN("BN_tmp", BN_tmp); +// SDRM_PrintBN("pBN_r", pBN_r); + // 5. V = rÀÎ °æ¿ì ¼­¸í ok + res = SDRM_BN_Cmp_sign(BN_tmp, pBN_r); + if (res != 0) + { + res = CRYPTO_INVALID_SIGN; + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return res; + } + + //Success + free(pbBuf); + free(EC_temp1); + free(EC_temp2); + + return CRYPTO_VALID_SIGN; +} + +/* + * @fn SDRM_ECDSA_sign + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [out]generated signature + * @param signLen [out]byte-length of signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_ECDSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdsactx == NULL) || (hash == NULL) || (signature == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (signLen) + { + *signLen = crt->ctx->ecdsactx->uDimension / 4; + } + + return SDRM_CTX_ECDSA_SIG_GEN(crt->ctx->ecdsactx, signature, hash, hashLen); +} + +/* + * @fn SDRM_ECDSA_verify + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [in]signature + * @param signLen [in]byte-length of signature + * @param result [in]result of veryfing signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if the length of signature is invalid + */ +int SDRM_ECDSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result) +{ + int retVal; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdsactx == NULL) || (hash == NULL) || (signature == NULL) || (result == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (signLen != (crt->ctx->ecdsactx->uDimension / 4)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + retVal = SDRM_CTX_ECDSA_SIG_VERIFY(crt->ctx->ecdsactx, signature, signLen, hash, hashLen); + + if (retVal == CRYPTO_VALID_SIGN) + { + *result = CRYPTO_VALID_SIGN; + } + else + { + *result = CRYPTO_INVALID_SIGN; + } + + return retVal; +} + +/* + * @fn SDRM_ECC_Set_CTX + * @brief Set parameters for ECC + * + * @param crt [out]crypto env structure + * @param Dimension [in]dimension + * @param ECC_P_Data [in]represents p + * @param ECC_P_Len [in]byte-length of p + * @param ECC_A_Data [in]represents a + * @param ECC_A_Len [in]byte-length of a + * @param ECC_B_Data [in]represents b + * @param ECC_B_Len [in]byte-length of b + * @param ECC_G_X_Data [in]represents x coordinate of g + * @param ECC_G_X_Len [in]byte-length of x coordinate of g + * @param ECC_G_Y_Data [in]represents y coordinate of g + * @param ECC_G_Y_Len [in]byte-length of y coordinate of g + * @param ECC_R_Data [in]represents r + * @param ECC_R_Len [in]byte-length of r + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if argument is null + */ +int SDRM_ECC_Set_CTX(CryptoCoreContainer *crt, cc_u16 Dimension, + cc_u8* ECC_P_Data, cc_u32 ECC_P_Len, + cc_u8* ECC_A_Data, cc_u32 ECC_A_Len, + cc_u8* ECC_B_Data, cc_u32 ECC_B_Len, + cc_u8* ECC_G_X_Data, cc_u32 ECC_G_X_Len, + cc_u8* ECC_G_Y_Data, cc_u32 ECC_G_Y_Len, + cc_u8* ECC_R_Data, cc_u32 ECC_R_Len) +{ + int retVal; + cc_u8 zero[] = {0x00}; + SDRM_ECC_CTX *ECC_ctx; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if ((ECC_P_Data == NULL) || (ECC_A_Data == NULL) || (ECC_B_Data == NULL) || (ECC_G_X_Data == NULL) || (ECC_G_Y_Data == NULL) || (ECC_R_Data == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ECC_ctx = crt->ctx->ecdhctx; + + ECC_ctx->uDimension = Dimension; + + retVal = SDRM_OS2BN(ECC_P_Data, ECC_P_Len, ECC_ctx->ECC_p); + if (retVal != CRYPTO_SUCCESS) + { + free(ECC_ctx); + return retVal; + } + + retVal = SDRM_OS2BN(ECC_A_Data, ECC_A_Len, ECC_ctx->ECC_a); + if (retVal != CRYPTO_SUCCESS) + { + free(ECC_ctx); + return retVal; + } + + retVal = SDRM_OS2BN(ECC_B_Data, ECC_B_Len, ECC_ctx->ECC_b); + if (retVal != CRYPTO_SUCCESS) + { + free(ECC_ctx); + return retVal; + } + + retVal = SDRM_OS2BN(ECC_R_Data, ECC_R_Len, ECC_ctx->ECC_n); + if (retVal != CRYPTO_SUCCESS) + { + free(ECC_ctx); + return retVal; + } + + ECC_ctx->ECC_G->IsInfinity = 0; + retVal = SDRM_OS2BN(ECC_G_X_Data, ECC_G_X_Len, ECC_ctx->ECC_G->x); + if (retVal != CRYPTO_SUCCESS) + { + free(ECC_ctx); + return retVal; + } + retVal = SDRM_OS2BN(ECC_G_Y_Data, ECC_G_Y_Len, ECC_ctx->ECC_G->y); + if (retVal != CRYPTO_SUCCESS) + { + free(ECC_ctx); + return retVal; + } + + SDRM_OS2BN(zero, 0, ECC_ctx->ECC_G->z); + SDRM_OS2BN(zero, 0, ECC_ctx->ECC_G->z2); + SDRM_OS2BN(zero, 0, ECC_ctx->ECC_G->z3); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_ECC_genKeypair + * @brief Generate Private Key and Generate Key Pair for ECC Signature + * + * @param crt [out]crypto env structure + * @param PrivateKey [in]represents x coordinate of public key + * @param PrivateKeyLen [in]byte-length of x coordinate of public key + * @param PublicKey_X [in]represents x coordinate of public key + * @param PublicKey_XLen [in]byte-length of x coordinate of public key + * @param PublicKey_Y [in]represents y coordinate of public key + * @param PublicKey_YLen [in]byte-length of y coordinate of public key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if argument is null + */ +int SDRM_ECC_genKeypair (CryptoCoreContainer *crt, + cc_u8 *PrivateKey, cc_u32 *PrivateKeyLen, + cc_u8 *PublicKey_X, cc_u32 *PublicKey_XLen, + cc_u8 *PublicKey_Y, cc_u32 *PublicKey_YLen) +{ + int retVal; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + retVal = SDRM_CTX_ECDSA_KEY_GEN(crt->ctx->ecdsactx); + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + if (PrivateKey != NULL) + { + SDRM_I2OSP(crt->ctx->ecdsactx->PRIV_KEY, crt->ctx->ecdsactx->uDimension / 8, PrivateKey); + } + + if (PrivateKeyLen != NULL) + { + *PrivateKeyLen = crt->ctx->ecdsactx->uDimension / 8; + } + + if (PublicKey_X != NULL) + { + SDRM_I2OSP(crt->ctx->ecdsactx->PUBLIC_KEY->x, crt->ctx->ecdsactx->uDimension / 8, PublicKey_X); + } + + if (PublicKey_XLen != NULL) + { + *PublicKey_XLen = crt->ctx->ecdsactx->uDimension / 8; + } + + if (PublicKey_Y != NULL) + { + SDRM_I2OSP(crt->ctx->ecdsactx->PUBLIC_KEY->y, crt->ctx->ecdsactx->uDimension / 8, PublicKey_Y); + } + + if (PublicKey_YLen != NULL) + { + *PublicKey_YLen = crt->ctx->ecdsactx->uDimension / 8; + } + + return CRYPTO_SUCCESS; + +} + +/* + * @fn SDRM_ECC_setKeypair + * @brief Set key data for ECC + * + * @param crt [out]crypto env structure + * @param PRIV_Data [in]represents private key + * @param PRIV_Len [in]byte-length of private key + * @param PUB_X_Data [in]represents x coordinate of public key + * @param PUB_X_Len [in]byte-length of x coordinate of public key + * @param PUB_Y_Data [in]represents y coordinate of public key + * @param PUB_Y_Len [in]byte-length of y coordinate of public key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if argument is null + */ +int SDRM_ECC_setKeypair(CryptoCoreContainer *crt, + cc_u8* PRIV_Data, cc_u32 PRIV_Len, + cc_u8* PUB_X_Data, cc_u32 PUB_X_Len, + cc_u8* PUB_Y_Data, cc_u32 PUB_Y_Len) +{ + int retVal; + cc_u8 zero[] = {0x00}; + SDRM_ECC_CTX *ECC_ctx; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->ecdsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ECC_ctx = crt->ctx->ecdsactx; + + ECC_ctx->PUBLIC_KEY->IsInfinity = 0; + + if (PRIV_Data != NULL) + { + retVal = SDRM_OS2BN(PRIV_Data, PRIV_Len, ECC_ctx->PRIV_KEY); + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + if (PUB_X_Data != NULL && PUB_Y_Data != NULL) + { + retVal = SDRM_OS2BN(PUB_X_Data, PUB_X_Len, ECC_ctx->PUBLIC_KEY->x); + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + retVal = SDRM_OS2BN(PUB_Y_Data, PUB_Y_Len, ECC_ctx->PUBLIC_KEY->y); + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + SDRM_OS2BN(zero, 0, ECC_ctx->PUBLIC_KEY->z); + SDRM_OS2BN(zero, 0, ECC_ctx->PUBLIC_KEY->z2); + SDRM_OS2BN(zero, 0, ECC_ctx->PUBLIC_KEY->z3); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_hmac.c b/ssflib/dep/cryptocore/source/middle/cc_hmac.c new file mode 100755 index 0000000..6051eaf --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_hmac.c @@ -0,0 +1,574 @@ +/** + * \file hmac.c + * @brief funciton for c-mac code generation by SHA1 and MD5 + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/19 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_hmac.h" +#include "cc_sha1.h" +#include "cc_sha2.h" +#include "cc_md5.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +int SDRM_getK0(cc_u8* k0, cc_u8* Key, cc_u32 KeyLen, cc_u32 Algorithm, cc_u32 B); + +/* + * @fn SDRM_HMAC_init + * @brief Parameter setting for mac code generation + * + * @param crt [out]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_HMAC_init(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen) +{ + SDRM_HMACContext *ctx; + cc_u8 *ipad; + cc_u32 i; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->hmacctx == NULL) || (Key == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->hmacctx; + ctx->algorithm = crt->alg; + + switch(ctx->algorithm) + { + case ID_HMD5 : + ctx->B = SDRM_MD5_DATA_SIZE; + break; + + case ID_HSHA1 : + ctx->B = SDRM_SHA1_DATA_SIZE; + break; + + case ID_HSHA224 : + ctx->B = SDRM_SHA224_DATA_SIZE; + break; + + case ID_HSHA256 : + ctx->B = SDRM_SHA256_DATA_SIZE; + break; + +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384 : + ctx->B = SDRM_SHA384_DATA_SIZE; + break; + + case ID_HSHA512 : + ctx->B = SDRM_SHA512_DATA_SIZE; + break; +#endif //_OP64_NOTSUPPORTED + + default : + return CRYPTO_INVALID_ARGUMENT; + } + + ipad = (cc_u8*)malloc(ctx->B); + if (ipad == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + ctx->k0 = (cc_u8*)malloc(ctx->B); + if (ctx->k0 == NULL) + { + free(ipad); + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + //make k0 + SDRM_getK0(ctx->k0, Key, KeyLen, ctx->algorithm, ctx->B); + + //ipad = k0 xor ipad + for (i = 0; i < ctx->B; i++) + { + ipad[i] = ctx->k0[i] ^ 0x36; + } + + if (i != ctx->B) + { + for (; i < ctx->B; i++) + { + ipad[i] = ctx->k0[i] ^ 0x36; + } + } + + ctx->md5_ctx = NULL; + ctx->sha1_ctx = NULL; + ctx->sha224_ctx = NULL; + ctx->sha256_ctx = NULL; +#ifndef _OP64_NOTSUPPORTED + ctx->sha384_ctx = NULL; + ctx->sha512_ctx = NULL; +#endif //_OP64_NOTSUPPORTED + + switch(ctx->algorithm) + { + case ID_HMD5 : + ctx->md5_ctx = (SDRM_MD5Context*)malloc(sizeof(SDRM_MD5Context)); + + if (ctx->md5_ctx == NULL) + { + if (ipad != NULL) + { + free(ipad); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_MD5_Init(ctx->md5_ctx); + SDRM_MD5_Update(ctx->md5_ctx, ipad, ctx->B); + break; + + case ID_HSHA1 : + ctx->sha1_ctx = (SDRM_SHA1Context*)malloc(sizeof(SDRM_SHA1Context)); + + if (ctx->sha1_ctx == NULL) + { + if (ipad != NULL) + { + free(ipad); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_SHA1_Init(ctx->sha1_ctx); + SDRM_SHA1_Update(ctx->sha1_ctx, ipad, ctx->B); + break; + + case ID_HSHA224 : + ctx->sha224_ctx = (SDRM_SHA224Context*)malloc(sizeof(SDRM_SHA224Context)); + + if (ctx->sha224_ctx == NULL) + { + if (ipad != NULL) + { + free(ipad); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_SHA224_Init(ctx->sha224_ctx); + SDRM_SHA224_Update(ctx->sha224_ctx, ipad, ctx->B); + break; + + case ID_HSHA256 : + ctx->sha256_ctx = (SDRM_SHA256Context*)malloc(sizeof(SDRM_SHA256Context)); + + if (ctx->sha256_ctx == NULL) + { + if (ipad != NULL) + { + free(ipad); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_SHA256_Init(ctx->sha256_ctx); + SDRM_SHA256_Update(ctx->sha256_ctx, ipad, ctx->B); + break; + +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384 : + ctx->sha384_ctx = (SDRM_SHA384Context*)malloc(sizeof(SDRM_SHA384Context)); + + if (ctx->sha384_ctx == NULL) + { + if (ipad != NULL) + { + free(ipad); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_SHA384_Init(ctx->sha384_ctx); + SDRM_SHA384_Update(ctx->sha384_ctx, ipad, ctx->B); + break; + + case ID_HSHA512 : + ctx->sha512_ctx = (SDRM_SHA512Context*)malloc(sizeof(SDRM_SHA512Context)); + + if (ctx->sha512_ctx == NULL) + { + if (ipad != NULL) + { + free(ipad); + } + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + SDRM_SHA512_Init(ctx->sha512_ctx); + SDRM_SHA512_Update(ctx->sha512_ctx, ipad, ctx->B); + break; +#endif //_OP64_NOTSUPPORTED + + default : + free(ipad); + return CRYPTO_INVALID_ARGUMENT; + } + + free(ipad); + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_HMAC_update + * @brief process data blocks + * + * @param crt [out]crypto parameter + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_HMAC_update(CryptoCoreContainer *crt, cc_u8 *msg, cc_u32 msgLen) +{ + if (msgLen == 0) + { + return CRYPTO_SUCCESS; + } + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->hmacctx == NULL) || (msg == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + switch(crt->ctx->hmacctx->algorithm) + { + case ID_HMD5 : + SDRM_MD5_Update(crt->ctx->hmacctx->md5_ctx, msg, msgLen); + break; + case ID_HSHA1 : + SDRM_SHA1_Update(crt->ctx->hmacctx->sha1_ctx, msg, msgLen); + break; + case ID_HSHA224 : + SDRM_SHA224_Update(crt->ctx->hmacctx->sha224_ctx, msg, msgLen); + break; + case ID_HSHA256 : + SDRM_SHA256_Update(crt->ctx->hmacctx->sha256_ctx, msg, msgLen); + break; + +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384 : + SDRM_SHA384_Update(crt->ctx->hmacctx->sha384_ctx, msg, msgLen); + break; + case ID_HSHA512 : + SDRM_SHA512_Update(crt->ctx->hmacctx->sha512_ctx, msg, msgLen); + break; +#endif //OP64_NOTSUPPORTED + + default : + return CRYPTO_INVALID_ARGUMENT; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_HMAC_final + * @brief process last data block + * + * @param crt [in]crypto parameter + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if Parameter is NULL + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_HMAC_final(CryptoCoreContainer *crt, cc_u8 *output, cc_u32 *outputLen) +{ + SDRM_HMACContext *ctx; + SDRM_MD5Context MD5ctx; + SDRM_SHA1Context SHA1ctx; + SDRM_SHA224Context SHA224ctx; + SDRM_SHA256Context SHA256ctx; +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context SHA384ctx; + SDRM_SHA512Context SHA512ctx; +#endif //_OP64_NOTSUPPORTED + cc_u8 Step6_Result[64]; + cc_u32 HashLen, i; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->hmacctx == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + ctx = crt->ctx->hmacctx; + + //k0 = k0 xor opad + for (i = 0; i < ctx->B; i++) + { + ctx->k0[i] ^= 0x5c; + } + + if (i != ctx->B) + { + for (; i < ctx->B; i++) + { + ctx->k0[i] ^= 0x5c; + } + } + + //Step6 : get H((k0 xor ipad) | text) & Step 9 : make hash + switch(ctx->algorithm) + { + case ID_HMD5 : + SDRM_MD5_Final(ctx->md5_ctx, Step6_Result); + free(ctx->md5_ctx); + + HashLen = SDRM_MD5_BLOCK_SIZ; + + SDRM_MD5_Init(&MD5ctx); + SDRM_MD5_Update(&MD5ctx, ctx->k0, ctx->B); + SDRM_MD5_Update(&MD5ctx, Step6_Result, HashLen); + SDRM_MD5_Final(&MD5ctx, output); + + break; + + case ID_HSHA1 : + SDRM_SHA1_Final(ctx->sha1_ctx, Step6_Result); + free(ctx->sha1_ctx); + + HashLen = SDRM_SHA1_BLOCK_SIZ; + + SDRM_SHA1_Init(&SHA1ctx); + SDRM_SHA1_Update(&SHA1ctx, ctx->k0, ctx->B); + SDRM_SHA1_Update(&SHA1ctx, Step6_Result, HashLen); + SDRM_SHA1_Final(&SHA1ctx, output); + + break; + + case ID_HSHA224 : + SDRM_SHA224_Final(ctx->sha224_ctx, Step6_Result); + free(ctx->sha224_ctx); + + HashLen = SDRM_SHA224_BLOCK_SIZ; + + SDRM_SHA224_Init(&SHA224ctx); + SDRM_SHA224_Update(&SHA224ctx, ctx->k0, ctx->B); + SDRM_SHA224_Update(&SHA224ctx, Step6_Result, HashLen); + SDRM_SHA224_Final(&SHA224ctx, output); + + break; + + case ID_HSHA256 : + SDRM_SHA256_Final(ctx->sha256_ctx, Step6_Result); + free(ctx->sha256_ctx); + + HashLen = SDRM_SHA256_BLOCK_SIZ; + + SDRM_SHA256_Init(&SHA256ctx); + SDRM_SHA256_Update(&SHA256ctx, ctx->k0, ctx->B); + SDRM_SHA256_Update(&SHA256ctx, Step6_Result, HashLen); + SDRM_SHA256_Final(&SHA256ctx, output); + + break; + +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384 : + SDRM_SHA384_Final(ctx->sha384_ctx, Step6_Result); + free(ctx->sha384_ctx); + + HashLen = SDRM_SHA384_BLOCK_SIZ; + + SDRM_SHA384_Init(&SHA384ctx); + SDRM_SHA384_Update(&SHA384ctx, ctx->k0, ctx->B); + SDRM_SHA384_Update(&SHA384ctx, Step6_Result, HashLen); + SDRM_SHA384_Final(&SHA384ctx, output); + + break; + + case ID_HSHA512 : + SDRM_SHA512_Final(ctx->sha512_ctx, Step6_Result); + free(ctx->sha512_ctx); + + HashLen = SDRM_SHA512_BLOCK_SIZ; + + SDRM_SHA512_Init(&SHA512ctx); + SDRM_SHA512_Update(&SHA512ctx, ctx->k0, ctx->B); + SDRM_SHA512_Update(&SHA512ctx, Step6_Result, HashLen); + SDRM_SHA512_Final(&SHA512ctx, output); + + break; +#endif + + default : + if (ctx->k0) { + free(ctx->k0); + } + return CRYPTO_INVALID_ARGUMENT; + } + + if (outputLen != NULL) + { + *outputLen = HashLen; + } + + if (ctx->k0) + { + free(ctx->k0); + } + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_HMAC_getMAC + * @brief generate h-mac code + * + * @param crt [in]crypto parameter + * @param Key [in]user key + * @param KeyLen [in]byte-length of Key + * @param msg [in]data block + * @param msgLen [in]byte-length of Text + * @param output [out]generated MAC + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_HMAC_getMAC(CryptoCoreContainer *crt, cc_u8 *Key, cc_u32 KeyLen, cc_u8 *msg, cc_u32 msgLen, cc_u8 *output, cc_u32 *outputLen) +{ + int result; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->hmacctx == NULL) || (Key == NULL) || (output == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + result = SDRM_HMAC_init(crt, Key, KeyLen); + if (result != CRYPTO_SUCCESS) + { + return result; + } + + result = SDRM_HMAC_update(crt, msg, msgLen); + if (result != CRYPTO_SUCCESS) + { + return result; + } + + return SDRM_HMAC_final(crt, output, outputLen); +} + +int SDRM_getK0(cc_u8* k0, cc_u8* Key, cc_u32 KeyLen, cc_u32 Algorithm, cc_u32 B) +{ + SDRM_MD5Context MD5ctx; + SDRM_SHA1Context SHA1ctx; + SDRM_SHA224Context SHA224ctx; + SDRM_SHA256Context SHA256ctx; +#ifndef _OP64_NOTSUPPORTED + SDRM_SHA384Context SHA384ctx; + SDRM_SHA512Context SHA512ctx; +#endif //_OP64_NOTSUPPORTED + + int L; + + if (KeyLen == B) + { + //if the length of K = B : set K0 = K + memcpy(k0, Key, B); + } + else if (KeyLen > B) + { + //if the length of K > B : get hask(K) and append (B - L) zeros + + //get hash(K) + + switch(Algorithm) + { + case ID_HMD5 : + SDRM_MD5_Init(&MD5ctx); + SDRM_MD5_Update(&MD5ctx, Key, KeyLen); + SDRM_MD5_Final(&MD5ctx, k0); + + L = SDRM_MD5_BLOCK_SIZ; + + break; + + case ID_HSHA1 : + SDRM_SHA1_Init(&SHA1ctx); + SDRM_SHA1_Update(&SHA1ctx, Key, KeyLen); + SDRM_SHA1_Final(&SHA1ctx, k0); + + L = SDRM_SHA1_BLOCK_SIZ; + + break; + + case ID_HSHA224 : + SDRM_SHA224_Init(&SHA224ctx); + SDRM_SHA224_Update(&SHA224ctx, Key, KeyLen); + SDRM_SHA224_Final(&SHA224ctx, k0); + + L = SDRM_SHA224_BLOCK_SIZ; + + break; + + case ID_HSHA256 : + SDRM_SHA256_Init(&SHA256ctx); + SDRM_SHA256_Update(&SHA256ctx, Key, KeyLen); + SDRM_SHA256_Final(&SHA256ctx, k0); + + L = SDRM_SHA256_BLOCK_SIZ; + + break; + +#ifndef _OP64_NOTSUPPORTED + case ID_HSHA384 : + SDRM_SHA384_Init(&SHA384ctx); + SDRM_SHA384_Update(&SHA384ctx, Key, KeyLen); + SDRM_SHA384_Final(&SHA384ctx, k0); + + L = SDRM_SHA384_BLOCK_SIZ; + + break; + + case ID_HSHA512 : + SDRM_SHA512_Init(&SHA512ctx); + SDRM_SHA512_Update(&SHA512ctx, Key, KeyLen); + SDRM_SHA512_Final(&SHA512ctx, k0); + + L = SDRM_SHA512_BLOCK_SIZ; + + break; +#endif + + default : + return CRYPTO_INVALID_ARGUMENT; + } + + //append zeros + memset(k0 + L, 0x00, B - L); + } + else { + //if the length of K < B : append zerots to the end of K + memcpy(k0, Key, KeyLen); + memset(k0 + KeyLen, 0x00, B - KeyLen); + } + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/middle/cc_rng.c b/ssflib/dep/cryptocore/source/middle/cc_rng.c new file mode 100755 index 0000000..614aa61 --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_rng.c @@ -0,0 +1,69 @@ +/** + * \file rng.c + * @brief Random Number Generator Interface + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon, Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/07 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_ANSI_x931.h" +#include "cc_rng.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_X931_seed + * @brief Seed RNG System + * + * @param crt [in]crypto env structure + * @param seed [in]seed for RNG System + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_X931_seed(CryptoCoreContainer *crt, cc_u8 *seed) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->x931ctx == NULL) || (seed == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + memcpy(crt->ctx->x931ctx->Seed, seed, SDRM_X931_SEED_SIZ); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_X931_get + * @brief generate random number + * + * @param crt [in]crypto env structure + * @param bitLength [in]bit length for generated number + * @param data [out]generated data + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_X931_get(CryptoCoreContainer *crt, cc_u32 bitLength, cc_u8 *data) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->x931ctx == NULL) || (data == NULL)) + { + return CRYPTO_NULL_POINTER; + } + +#ifdef _WIN32_WCE + srand(GetTickCount()); +#else + srand((unsigned int)time(NULL)); +#endif + + return SDRM_RNG_X931(crt->ctx->x931ctx->Seed, bitLength, data); +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/cryptocore/source/middle/cc_rsa.c b/ssflib/dep/cryptocore/source/middle/cc_rsa.c new file mode 100755 index 0000000..43d6f10 --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_rsa.c @@ -0,0 +1,1924 @@ +/** + * \file rsa.c + * @brief implementation of rsa encryption/decryption and signature/verifycation + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/20 + * Note : Modified for support RSA-2048(Jisoon Park, 2007/03/14) + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_rsa.h" +#include "cc_pkcs1_v21.h" +#include "cc_ANSI_x931.h" +#include "cc_bignum.h" + +////////////////////////////////////////////////////////////////////////// +// Functions +////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_RSAContext *SDRM_RSA_InitCrt(cc_u32 KeyByteLen) + * + * @brief generate RSA Context + * + * @return pointer to the generated context + * \n NULL if memory allocation is failed + */ +SDRM_RSAContext *SDRM_RSA_InitCrt(cc_u32 KeyByteLen) +{ + SDRM_RSAContext *ctx; + cc_u32 RSA_KeyByteLen = KeyByteLen; + cc_u8 *pbBuf = (cc_u8*)malloc(sizeof(SDRM_RSAContext) + SDRM_RSA_ALLOC_SIZE * 8); + + if (pbBuf == NULL) + { + return NULL; + } + + ctx = (SDRM_RSAContext*)(void*)pbBuf; + ctx->n = SDRM_BN_Alloc((cc_u8*)ctx + sizeof(SDRM_RSAContext), SDRM_RSA_BN_BUFSIZE); + ctx->e = SDRM_BN_Alloc((cc_u8*)ctx->n + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + ctx->d = SDRM_BN_Alloc((cc_u8*)ctx->e + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + ctx->p = SDRM_BN_Alloc((cc_u8*)ctx->d + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + ctx->q = SDRM_BN_Alloc((cc_u8*)ctx->p + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + ctx->dmodp1 = SDRM_BN_Alloc((cc_u8*)ctx->q + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + ctx->dmodq1 = SDRM_BN_Alloc((cc_u8*)ctx->dmodp1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + ctx->iqmodp = SDRM_BN_Alloc((cc_u8*)ctx->dmodq1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + ctx->crt_operation = (unsigned int)-1; + ctx->k = RSA_KeyByteLen; + + return ctx; +} + +/* + * @fn int SDRM_RSA_setNED(CryptoCoreContainer *crt, cc_u32 PaddingMethod, cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, cc_u8* RSA_D_Data, cc_u32 RSA_D_Len) + * @brief set RSA parameters + * + * @param crt [out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [in]n value + * @param RSA_N_Len [in]byte-length of n + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_D_Data [in]d value + * @param RSA_D_Len [in]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + */ +int SDRM_RSA_setNED(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 RSA_D_Len) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL) || (RSA_N_Data == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + SDRM_OS2BN(RSA_N_Data, RSA_N_Len, crt->ctx->rsactx->n); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->n); + + if (RSA_E_Data != NULL) + { + SDRM_OS2BN(RSA_E_Data, RSA_E_Len, crt->ctx->rsactx->e); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->e); + } + + if (RSA_D_Data != NULL) + { + SDRM_OS2BN(RSA_D_Data, RSA_D_Len, crt->ctx->rsactx->d); + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->d); + } + + crt->ctx->rsactx->pm = PaddingMethod; + crt->ctx->rsactx->crt_operation = 0; + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_setNEDPQ(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + * cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + * cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + * cc_u8* RSA_D_Data, cc_u32 RSA_D_Len, + * cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + * cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + * cc_u8* RSA_DmodP1_Data, cc_u32 RSA_DmodP1_Len, + * cc_u8* RSA_DmodQ1_Data, cc_u32 RSA_DmodQ1_Len, + * cc_u8* RSA_iQmodP_Data, cc_u32 RSA_iQmodP_Len) + * + * @brief set RSA parameters + * + * @param crt [out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [in]n value + * @param RSA_N_Len [in]byte-length of n + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_D_Data [in]d value + * @param RSA_D_Len [in]byte-length of d + * @param RSA_P_Data [in]p value + * @param RSA_P_Len [in]byte-length of p + * @param RSA_Q_Data [in]q value + * @param RSA_Q_Len [in]byte-length of q + * @param RSA_DmodP1_Data [in]d mod (p-1) value + * @param RSA_DmodP1_Len [in]byte-length of d mod (p-1) + * @param RSA_DmodQ1_Data [in]d mod (q-1) value + * @param RSA_DmodQ1_Len [in]byte-length of d mod (q-1) + * @param RSA_iQmodP_Data [in]q^(-1) mod p value + * @param RSA_iQmodP_Len [in]byte-length of q^(-1) mod p + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + */ +int SDRM_RSA_setNEDPQ(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + cc_u8* RSA_DmodP1_Data, cc_u32 RSA_DmodP1_Len, + cc_u8* RSA_DmodQ1_Data, cc_u32 RSA_DmodQ1_Len, + cc_u8* RSA_iQmodP_Data, cc_u32 RSA_iQmodP_Len) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + crt->ctx->rsactx->crt_operation = 0; + if ((RSA_P_Data != NULL) && (RSA_Q_Data != NULL) && (RSA_DmodP1_Data != NULL) && (RSA_DmodQ1_Data != NULL) && (RSA_iQmodP_Data != NULL)) + { + crt->ctx->rsactx->crt_operation = 1; + } + else if (RSA_N_Data == NULL) + { + return CRYPTO_NULL_POINTER; + } + + if (RSA_N_Data != NULL) + { + if( !SDRM_OS2BN(RSA_N_Data, RSA_N_Len, crt->ctx->rsactx->n) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->n); + } + } + + if (RSA_E_Data != NULL) + { + if( !SDRM_OS2BN(RSA_E_Data, RSA_E_Len, crt->ctx->rsactx->e) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->e); + } + } + + if (RSA_D_Data != NULL) + { + if( !SDRM_OS2BN(RSA_D_Data, RSA_D_Len, crt->ctx->rsactx->d) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->d); + } + } + + if (RSA_P_Data != NULL) + { + if( !SDRM_OS2BN(RSA_P_Data, RSA_P_Len, crt->ctx->rsactx->p) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->p); + } + } + + if (RSA_Q_Data != NULL) + { + if( !SDRM_OS2BN(RSA_Q_Data, RSA_Q_Len, crt->ctx->rsactx->q) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->q); + } + } + + if (RSA_DmodP1_Data != NULL) + { + if( !SDRM_OS2BN(RSA_DmodP1_Data, RSA_DmodP1_Len, crt->ctx->rsactx->dmodp1) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->dmodp1); + } + } + + if (RSA_DmodQ1_Data != NULL) + { + if( !SDRM_OS2BN(RSA_DmodQ1_Data, RSA_DmodQ1_Len, crt->ctx->rsactx->dmodq1) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->dmodq1); + } + } + + if (RSA_iQmodP_Data != NULL) + { + if( !SDRM_OS2BN(RSA_iQmodP_Data, RSA_iQmodP_Len, crt->ctx->rsactx->iqmodp) ) { + SDRM_BN_OPTIMIZE_LENGTH(crt->ctx->rsactx->iqmodp); + } + } + + crt->ctx->rsactx->pm = PaddingMethod; + + return CRYPTO_SUCCESS; +} + + +/* + * @fn int SDRM_RSA_GenerateKey(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + * cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + * cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + * cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len) + * @brief generate and set RSA parameters + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [out]n value + * @param RSA_N_Len [out]byte-length of n + * @param RSA_E_Data [out]e value + * @param RSA_E_Len [out]byte-length of e + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateKey(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len) +{ + cc_u32 Seed[4]; + SDRM_BIG_NUM *p, *q, *pi, *e, *temp1, *temp2; + cc_u32 RSA_KeyByteLen = 0; + int i, sp, t1; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + t1 = (RSA_KeyByteLen * 4 - 1) % 32; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 5); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + p = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + q = SDRM_BN_Alloc((cc_u8*)p + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + pi = SDRM_BN_Alloc((cc_u8*)q + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)pi + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + e = crt->ctx->rsactx->e; + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^rand(); + } + + //set security parameter for miller-rabin probabilistic primality test + if (RSA_KeyByteLen >= 256) + { + sp = 3; + } + else if (RSA_KeyByteLen >= 128) + { + sp = 5; + } + else if (RSA_KeyByteLen >= 30) + { + sp = 15; + } + else + { + sp = 30; + } + +GEN_RND: + //Generate p + p->Length = (RSA_KeyByteLen + 7) / 8; + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)p->pData); + p->pData[0] |= 1L; + p->pData[p->Length - 1] &= ~((-1L) << t1); + p->pData[p->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(p, sp) != CRYPTO_ISPRIME); + + //Generate q + q->Length = (RSA_KeyByteLen + 7) / 8; + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)q->pData); + q->pData[0] |= 1L; + q->pData[q->Length - 1] &= ~((-1L) << t1); + q->pData[q->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(q, sp) != CRYPTO_ISPRIME); + +// SDRM_PrintBN("p", p); +// SDRM_PrintBN("q", q); + + //temp1 = (p - 1), temp2 = (q - 1) + SDRM_BN_Sub(temp1, p, BN_One); + SDRM_BN_Sub(temp2, q, BN_One); + + //evaluate n and pi + //n = p * q, pi = (p - 1) * (q - 1) + SDRM_BN_Mul(crt->ctx->rsactx->n, p, q); + SDRM_BN_Mul(pi, temp1, temp2); + + //generate e + e->Length = (RSA_KeyByteLen + 3) / 4; + do { + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 8 - 8, (cc_u8*)e->pData); + e->pData[0] |= 0x01; + } + while(SDRM_BN_CheckRelativelyPrime(e, pi) != CRYPTO_ISPRIME); + } + while (SDRM_BN_Cmp(e, pi) >= 0); + + if (SDRM_BN_ModInv(crt->ctx->rsactx->d, e, pi) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + + crt->ctx->rsactx->pm = PaddingMethod; + + if (RSA_N_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->n, RSA_KeyByteLen, RSA_N_Data); + } + + if (RSA_N_Len != NULL) + { + *RSA_N_Len = RSA_KeyByteLen; + } + + if (RSA_E_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->e, RSA_KeyByteLen, RSA_E_Data); + } + + if (RSA_E_Len != NULL) + { + *RSA_E_Len = RSA_KeyByteLen; + } + + if (RSA_D_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->d, RSA_KeyByteLen, RSA_D_Data); + } + + if (RSA_D_Len != NULL) + { + *RSA_D_Len = RSA_KeyByteLen; + } + + free(pbBuf); + + crt->ctx->rsactx->crt_operation = 0; + + return CRYPTO_SUCCESS; +} + +int SDRM_RSA_GenerateKeyforCRT(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + cc_u8* RSA_DP_Data, cc_u32 *RSA_DP_Len, + cc_u8* RSA_DQ_Data, cc_u32 *RSA_DQ_Len, + cc_u8* RSA_QP_Data, cc_u32 *RSA_QP_Len) +{ + cc_u32 Seed[4]; + SDRM_BIG_NUM *p, *q, *h, *e, *p1, *q1; + cc_u32 RSA_KeyByteLen = 0; + int i, sp, t1; + cc_u8 *pbBuf = NULL; + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL)) { + return CRYPTO_NULL_POINTER; + } + RSA_KeyByteLen = crt->ctx->rsactx->k; + t1 = (RSA_KeyByteLen * 4 - 1) % 32; + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 5); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + p = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + q = SDRM_BN_Alloc((cc_u8*)p + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + h = SDRM_BN_Alloc((cc_u8*)q + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + p1 = SDRM_BN_Alloc((cc_u8*)h + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + q1 = SDRM_BN_Alloc((cc_u8*)p1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + e = crt->ctx->rsactx->e; + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + if (RSA_KeyByteLen >= 256) + { + sp = 3; + } + else if (RSA_KeyByteLen >= 128) + { + sp = 5; + } + else if (RSA_KeyByteLen >= 30) + { + sp = 15; + } + else + { + sp = 30; + } +GEN_RND: + p->Length = (RSA_KeyByteLen + 7) / 8; + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)p->pData); + p->pData[0] |= 1L; + p->pData[p->Length - 1] &= ~((-1L) << t1); + p->pData[p->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(p, sp) != CRYPTO_ISPRIME); + q->Length = (RSA_KeyByteLen + 7) / 8; + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)q->pData); + q->pData[0] |= 1L; + q->pData[q->Length - 1] &= ~((-1L) << t1); + q->pData[q->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(q, sp) != CRYPTO_ISPRIME); + SDRM_BN_Sub(p1, p, BN_One); + SDRM_BN_Sub(q1, q, BN_One); + SDRM_BN_Mul(h, p1, q1); + SDRM_OS2BN(RSA_E_Data, RSA_E_Len, e); + if ((SDRM_BN_CheckRelativelyPrime(e, h) != CRYPTO_ISPRIME) || (SDRM_BN_Cmp(e, h) >= 0)) + { + goto GEN_RND; + } + SDRM_BN_Mul(crt->ctx->rsactx->n, p, q); + if (SDRM_BN_ModInv(crt->ctx->rsactx->d, e, h) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + if (SDRM_BN_ModRed(crt->ctx->rsactx->dmodp1, crt->ctx->rsactx->d, p1) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + if (SDRM_BN_ModRed(crt->ctx->rsactx->dmodq1, crt->ctx->rsactx->d, q1) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + if (SDRM_BN_ModInv(crt->ctx->rsactx->iqmodp, q, p) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + crt->ctx->rsactx->pm = PaddingMethod; + if (RSA_N_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->n, RSA_KeyByteLen, RSA_N_Data); + } + if (RSA_N_Len != NULL) + { + *RSA_N_Len = RSA_KeyByteLen; + } + if (RSA_D_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->d, RSA_KeyByteLen, RSA_D_Data); + } + if (RSA_D_Len != NULL) + { + *RSA_D_Len = RSA_KeyByteLen; + } + if (RSA_P_Data != NULL) + { + SDRM_I2OSP(p, RSA_KeyByteLen/2, RSA_P_Data); + } + if (RSA_P_Len != NULL) + { + *RSA_P_Len = RSA_KeyByteLen/2; + } + if (RSA_Q_Data != NULL) + { + SDRM_I2OSP(q, RSA_KeyByteLen/2, RSA_Q_Data); + } + if (RSA_Q_Len != NULL) + { + *RSA_Q_Len = RSA_KeyByteLen/2; + } + if (RSA_DP_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->dmodp1, RSA_KeyByteLen/2, RSA_DP_Data); + } + if (RSA_DP_Len != NULL) + { + *RSA_DP_Len = RSA_KeyByteLen/2; + } + if (RSA_DQ_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->dmodq1, RSA_KeyByteLen/2, RSA_DQ_Data); + } + if (RSA_DQ_Len != NULL) + { + *RSA_DQ_Len = RSA_KeyByteLen/2; + } + if (RSA_QP_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->iqmodp, RSA_KeyByteLen/2, RSA_QP_Data); + } + if (RSA_QP_Len != NULL) + { + *RSA_QP_Len = RSA_KeyByteLen/2; + } + free(pbBuf); + crt->ctx->rsactx->crt_operation = 0; + return CRYPTO_SUCCESS; +} +/* + * @fn int SDRM_RSA_GenerateND(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + * cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + * cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + * cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len) + * @brief generate and set RSA parameters with specfied e + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_N_Data [out]n value + * @param RSA_N_Len [out]byte-length of n + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateND(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len) +{ + cc_u32 Seed[4]; + SDRM_BIG_NUM *p, *q, *pi, *e, *temp1, *temp2; + cc_u32 RSA_KeyByteLen = 0; + int i, sp, t1; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL)) { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + t1 = (RSA_KeyByteLen * 4 - 1) % 32; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 5); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + p = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + q = SDRM_BN_Alloc((cc_u8*)p + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + pi = SDRM_BN_Alloc((cc_u8*)q + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)pi + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + e = crt->ctx->rsactx->e; + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + + //set security parameter for miller-rabin probabilistic primality test + if (RSA_KeyByteLen >= 256) + { + sp = 3; + } + else if (RSA_KeyByteLen >= 128) + { + sp = 5; + } + else if (RSA_KeyByteLen >= 30) + { + sp = 15; + } + else + { + sp = 30; + } + +GEN_RND: + //Generate p + p->Length = (RSA_KeyByteLen + 7) / 8; + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)p->pData); + p->pData[0] |= 1L; + p->pData[p->Length - 1] &= ~((-1L) << t1); + p->pData[p->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(p, sp) != CRYPTO_ISPRIME); + + //Generate q + q->Length = (RSA_KeyByteLen + 7) / 8; + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)q->pData); + q->pData[0] |= 1L; + q->pData[q->Length - 1] &= ~((-1L) << t1); + q->pData[q->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(q, sp) != CRYPTO_ISPRIME); + + //temp1 = (p - 1), temp2 = (q - 1) + SDRM_BN_Sub(temp1, p, BN_One); + SDRM_BN_Sub(temp2, q, BN_One); + + //evaluate n and pi + //n = p * q, pi = (p - 1) * (q - 1) + SDRM_BN_Mul(crt->ctx->rsactx->n, p, q); + SDRM_BN_Mul(pi, temp1, temp2); + + //check N for e + SDRM_OS2BN(RSA_E_Data, RSA_E_Len, e); + if ((SDRM_BN_CheckRelativelyPrime(e, pi) != CRYPTO_ISPRIME) || (SDRM_BN_Cmp(e, pi) >= 0)) + { + goto GEN_RND; + } + + if (SDRM_BN_ModInv(crt->ctx->rsactx->d, e, pi) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + + crt->ctx->rsactx->pm = PaddingMethod; + + if (RSA_N_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->n, RSA_KeyByteLen, RSA_N_Data); + } + + if (RSA_N_Len != NULL) + { + *RSA_N_Len = RSA_KeyByteLen; + } + + if (RSA_D_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->d, RSA_KeyByteLen, RSA_D_Data); + } + + if (RSA_D_Len != NULL) + { + *RSA_D_Len = RSA_KeyByteLen; + } + + free(pbBuf); + + crt->ctx->rsactx->crt_operation = 0; + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_GenerateDwithPQE(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + * cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + * cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + * cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + * cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + * cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len) + * @brief generate D with specfied p, q, d mod (p-1), d mod (q-1) and e + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_E_Data [in]e value + * @param RSA_E_Len [in]byte-length of e + * @param RSA_P_Data [in]n value + * @param RSA_P_Len [in]byte-length of n + * @param RSA_Q_Data [in]d value + * @param RSA_Q_Len [in]byte-length of d + * @param RSA_D_P_Data [in]d mod (p-1) value + * @param RSA_D_P_Len [in]byte-length of d mod (p-1) + * @param RSA_D_Q_Data [in]d mod (q-1) value + * @param RSA_D_Q_Len [in]byte-length of d mod (q-1) + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_GenerateDwithPQE(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_E_Data, cc_u32 RSA_E_Len, + cc_u8* RSA_P_Data, cc_u32 RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 RSA_Q_Len, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len) +{ + SDRM_BIG_NUM *p, *q, *pi, *e, *temp1, *temp2; + cc_u32 RSA_KeyByteLen = 0; + int sp; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 5); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + p = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + q = SDRM_BN_Alloc((cc_u8*)p + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + pi = SDRM_BN_Alloc((cc_u8*)q + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)pi + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + e = crt->ctx->rsactx->e; + + //set security parameter for miller-rabin probabilistic primality test + if (RSA_KeyByteLen >= 256) + { + sp = 3; + } + else if (RSA_KeyByteLen >= 128) + { + sp = 5; + } + else if (RSA_KeyByteLen >= 30) + { + sp = 15; + } + else + { + sp = 30; + } + + SDRM_OS2BN((cc_u8*)RSA_P_Data, RSA_P_Len, p); + if (SDRM_BN_MILLER_RABIN(p, sp) != CRYPTO_ISPRIME) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + SDRM_OS2BN((cc_u8*)RSA_Q_Data, RSA_Q_Len, q); + if (SDRM_BN_MILLER_RABIN(q, sp) != CRYPTO_ISPRIME) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + //temp1 = (p - 1), temp2 = (q - 1) + SDRM_BN_Sub(temp1, p, BN_One); + SDRM_BN_Sub(temp2, q, BN_One); + + //evaluate n and pi + //n = p * q, pi = (p - 1) * (q - 1) + SDRM_BN_Mul(crt->ctx->rsactx->n, p, q); + SDRM_BN_Mul(pi, temp1, temp2); + + //check N for e + SDRM_OS2BN(RSA_E_Data, RSA_E_Len, e); + if ((SDRM_BN_CheckRelativelyPrime(e, pi) != CRYPTO_ISPRIME) || (SDRM_BN_Cmp(e, pi) >= 0)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if (SDRM_BN_ModInv(crt->ctx->rsactx->d, e, pi) != CRYPTO_SUCCESS) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + crt->ctx->rsactx->pm = PaddingMethod; + + if (RSA_N_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->n, RSA_KeyByteLen, RSA_N_Data); + } + + if (RSA_N_Len != NULL) + { + *RSA_N_Len = RSA_KeyByteLen; + } + + if (RSA_D_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->d, RSA_KeyByteLen, RSA_D_Data); + } + + if (RSA_D_Len != NULL) + { + *RSA_D_Len = RSA_KeyByteLen; + } + + free(pbBuf); + + crt->ctx->rsactx->crt_operation = 0; + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_GenerateKeyForCRT(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + * cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + * cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + * cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + * cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + * cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + * cc_u8* RSA_DmodP1_Data, cc_u32 *RSA_DmodP1_Len, + * cc_u8* RSA_DmodQ1_Data, cc_u32 *RSA_DmodQ1_Len, + * cc_u8* RSA_iQmodP_Data, cc_u32 *RSA_iQmodP_Len) + * @brief generate and set RSA parameters for CRT + * + * @param crt [in/out]rsa context + * @param PaddingMethod [in]padding method + * @param RSA_N_Data [out]n value + * @param RSA_N_Len [out]byte-length of n + * @param RSA_E_Data [out]e value + * @param RSA_E_Len [out]byte-length of e + * @param RSA_D_Data [out]d value + * @param RSA_D_Len [out]byte-length of d + * @param RSA_P_Len [out]byte-length of p + * @param RSA_Q_Data [out]q value + * @param RSA_Q_Len [out]byte-length of q + * @param RSA_DmodP1_Data [out]d mod (p-1) value + * @param RSA_DmodP1_Len [out]byte-length of d mod (p-1) + * @param RSA_DmodQ1_Data [out]d mod (q-1) value + * @param RSA_DmodQ1_Len [out]byte-length of d mod (q-1) + * @param RSA_iQmodP_Data [out]q^(-1) mod p value + * @param RSA_iQmodP_Len [out]byte-length of q^(-1) mod p + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ + + +int SDRM_RSA_GenNEDPQ(CryptoCoreContainer *crt, cc_u32 PaddingMethod, + cc_u8* RSA_N_Data, cc_u32 *RSA_N_Len, + cc_u8* RSA_E_Data, cc_u32 *RSA_E_Len, + cc_u8* RSA_D_Data, cc_u32 *RSA_D_Len, + cc_u8* RSA_P_Data, cc_u32 *RSA_P_Len, + cc_u8* RSA_Q_Data, cc_u32 *RSA_Q_Len, + cc_u8* RSA_DmodP1_Data, cc_u32 *RSA_DmodP1_Len, + cc_u8* RSA_DmodQ1_Data, cc_u32 *RSA_DmodQ1_Len, + cc_u8* RSA_iQmodP_Data, cc_u32 *RSA_iQmodP_Len) +{ + cc_u32 Seed[4]; + SDRM_BIG_NUM *p, *q, *pi, *e, *temp1, *temp2; + cc_u32 RSA_KeyByteLen = 0; + int i, sp, t1; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + t1 = (RSA_KeyByteLen * 4 - 1) % 32; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 3); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + pi = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)pi + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + e = crt->ctx->rsactx->e; + p = crt->ctx->rsactx->p; + q = crt->ctx->rsactx->q; + + for (i = 0; i < 4; i++) + { + Seed[i] = (rand() << 16) ^ rand(); + } + + //set security parameter for miller-rabin probabilistic primality test + if (RSA_KeyByteLen >= 256) + { + sp = 3; + } + else if (RSA_KeyByteLen >= 128) + { + sp = 5; + } + else if (RSA_KeyByteLen >= 30) + { + sp = 15; + } + else + { + sp = 30; + } + +GEN_RND: + + //Generate p + p->Length = (RSA_KeyByteLen + 7) / 8; + + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)p->pData); + p->pData[0] |= 1L; + p->pData[p->Length - 1] &= ~((-1L) << t1); + p->pData[p->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(p, sp) != CRYPTO_ISPRIME); + + //Generate q + q->Length = (RSA_KeyByteLen + 7) / 8; + + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 4, (cc_u8*)q->pData); + q->pData[0] |= 1L; + q->pData[q->Length - 1] &= ~((-1L) << t1); + q->pData[q->Length - 1] |= (1L << t1); + } + while(SDRM_BN_MILLER_RABIN(q, sp) != CRYPTO_ISPRIME); + +// SDRM_PrintBN("p", p); +// SDRM_PrintBN("q", q); + + + //temp1 = (p - 1), temp2 = (q - 1) + SDRM_BN_Sub(temp1, p, BN_One); + SDRM_BN_Sub(temp2, q, BN_One); + + //evaluate n and pi + //n = p * q, pi = (p - 1) * (q - 1) + SDRM_BN_Mul(crt->ctx->rsactx->n, p, q); + SDRM_BN_Mul(pi, temp1, temp2); + + //generate e + e->Length = (RSA_KeyByteLen + 3) / 4; + do { + do { + SDRM_RNG_X931((cc_u8 *)Seed, RSA_KeyByteLen * 8 - 8, (cc_u8*)e->pData); + e->pData[0] |= 0x01; + } + while(SDRM_BN_CheckRelativelyPrime(e, pi) != CRYPTO_ISPRIME); + } + while (SDRM_BN_Cmp(e, pi) >= 0); + + if (SDRM_BN_ModInv(crt->ctx->rsactx->d, e, pi) != CRYPTO_SUCCESS) + { + goto GEN_RND; + } + + //calc dmodp1 = d mod (p - 1) + SDRM_BN_ModRed(crt->ctx->rsactx->dmodp1, crt->ctx->rsactx->d, temp1); + + //calc dmodq1 = d mod (q - 1) + SDRM_BN_ModRed(crt->ctx->rsactx->dmodq1, crt->ctx->rsactx->d, temp2); + + //calc iqmodp = inv_q mod p + SDRM_BN_ModInv(crt->ctx->rsactx->iqmodp, q, p); + + crt->ctx->rsactx->pm = PaddingMethod; + + if (RSA_N_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->n, RSA_KeyByteLen, RSA_N_Data); + } + + if (RSA_N_Len != NULL) + { + *RSA_N_Len = RSA_KeyByteLen; + } + + if (RSA_E_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->e, RSA_KeyByteLen, RSA_E_Data); + } + + if (RSA_E_Len != NULL) + { + *RSA_E_Len = RSA_KeyByteLen; + } + + if (RSA_D_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->d, RSA_KeyByteLen, RSA_D_Data); + } + + if (RSA_D_Len != NULL) + { + *RSA_D_Len = RSA_KeyByteLen; + } + + if (RSA_P_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->p, RSA_KeyByteLen / 2, RSA_P_Data); + } + + if (RSA_P_Len != NULL) + { + *RSA_P_Len = RSA_KeyByteLen / 2; + } + + if (RSA_Q_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->q, RSA_KeyByteLen / 2, RSA_Q_Data); + } + + if (RSA_Q_Len != NULL) + { + *RSA_Q_Len = RSA_KeyByteLen / 2; + } + + if (RSA_DmodP1_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->dmodp1, RSA_KeyByteLen / 2, RSA_DmodP1_Data); + } + + if (RSA_DmodP1_Len != NULL) + { + *RSA_DmodP1_Len = RSA_KeyByteLen / 2; + } + + if (RSA_DmodQ1_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->dmodq1, RSA_KeyByteLen / 2, RSA_DmodQ1_Data); + } + + if (RSA_DmodQ1_Len != NULL) + { + *RSA_DmodQ1_Len = RSA_KeyByteLen / 2; + } + + if (RSA_iQmodP_Data != NULL) + { + SDRM_I2OSP(crt->ctx->rsactx->iqmodp, RSA_KeyByteLen / 2, RSA_iQmodP_Data); + } + + if (RSA_iQmodP_Len != NULL) + { + *RSA_iQmodP_Len = RSA_KeyByteLen / 2; + } + + free(pbBuf); + + crt->ctx->rsactx->crt_operation = 1; + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_encrypt(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) + * @brief RSA Encryption + * + * @param crt [in]rsa context + * @param in [in]message to encrypt + * @param inLen [in]byte-length of in + * @param out [out]encrypted message + * @param outLen [out]byte-length of out + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_encrypt(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) +{ + SDRM_BIG_NUM *BN_pMsg, *BN_Cipher; + int retVal = CRYPTO_ERROR; + cc_u32 RSA_KeyByteLen = 0; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL) || (in == NULL) || (out == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + if (inLen > RSA_KeyByteLen) + { + return CRYPTO_MSG_TOO_LONG; + } + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_pMsg = SDRM_BN_Alloc((cc_u8*)pbBuf + RSA_KeyByteLen, SDRM_RSA_BN_BUFSIZE); + BN_Cipher = SDRM_BN_Alloc((cc_u8*)BN_pMsg + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + //Padding the message + switch(SDRM_LOW_HALF(crt->ctx->rsactx->pm)) + { + case ID_RSAES_PKCS15 : + retVal = SDRM_Enpad_Rsaes_pkcs15(pbBuf, in, inLen, RSA_KeyByteLen); + break; + case ID_RSAES_OAEP : + retVal = SDRM_Enpad_Rsaes_oaep(pbBuf, in, inLen, RSA_KeyByteLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_NO_PADDING : + if( inLen != RSA_KeyByteLen) // add by guoxing.xu 20140919 + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + memset(pbBuf, 0x00, RSA_KeyByteLen - inLen); + memcpy(pbBuf + RSA_KeyByteLen - inLen, in, inLen); + retVal= CRYPTO_SUCCESS;// add by guoxing.xu 20140919 + break; + default : + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + +// SDRM_PrintBN("ENPADDED Text : ", BN_pMsg); + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + SDRM_OS2BN(pbBuf, RSA_KeyByteLen, BN_pMsg); + + //RSA Encryption by modular exponent +#ifndef _OP64_NOTSUPPORTED + retVal = SDRM_BN_ModExp2(BN_Cipher, BN_pMsg, crt->ctx->rsactx->e, crt->ctx->rsactx->n); +#else + retVal = SDRM_BN_ModExp(BN_Cipher, BN_pMsg, crt->ctx->rsactx->e, crt->ctx->rsactx->n); +#endif //_OP64_NOTSUPPORTED + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + SDRM_I2OSP(BN_Cipher, RSA_KeyByteLen, out); + + if (outLen != NULL) + { + *outLen = RSA_KeyByteLen; + } + + memset(pbBuf, 0x00, SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_decrypt(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) + * @brief RSA Decryption + * + * @param crt [in]rsa context + * @param in [in]message to decrypt + * @param inLen [in]byte-length of in + * @param out [out]decrypted message + * @param outLen [out]byte-length of out + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_decrypt(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) +{ + SDRM_BIG_NUM *BN_dMsg, *BN_Src; + int retVal; + cc_u32 plainLen; + cc_u32 RSA_KeyByteLen = 0; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL) || (in == NULL) || (out == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + if (inLen > RSA_KeyByteLen) + { + return CRYPTO_MSG_TOO_LONG; + } + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_dMsg = SDRM_BN_Alloc((cc_u8*)pbBuf + RSA_KeyByteLen, SDRM_RSA_BN_BUFSIZE); + BN_Src = SDRM_BN_Alloc((cc_u8*)BN_dMsg + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + SDRM_OS2BN(in, inLen, BN_Src); + + //RSA Decryption by modular exponent +#ifndef _OP64_NOTSUPPORTED + retVal = SDRM_BN_ModExp2(BN_dMsg, BN_Src, crt->ctx->rsactx->d, crt->ctx->rsactx->n); +#else + retVal = SDRM_BN_ModExp(BN_dMsg, BN_Src, crt->ctx->rsactx->d, crt->ctx->rsactx->n); +#endif //_OP64_NOTSUPPORTED + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + SDRM_I2OSP(BN_dMsg, RSA_KeyByteLen, pbBuf); + + //Remove Padding from message + switch(SDRM_LOW_HALF(crt->ctx->rsactx->pm)) + { + case ID_RSAES_PKCS15 : + retVal = SDRM_Depad_Rsaes_pkcs15(out, &plainLen, pbBuf, RSA_KeyByteLen, RSA_KeyByteLen); + break; + case ID_RSAES_OAEP : + retVal = SDRM_Depad_Rsaes_oaep(out, &plainLen, pbBuf, RSA_KeyByteLen, RSA_KeyByteLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_NO_PADDING : + memcpy(out, pbBuf, RSA_KeyByteLen); + plainLen = RSA_KeyByteLen; + retVal = CRYPTO_SUCCESS; + break; + default : + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + if (outLen != NULL) + { + *outLen = plainLen; + } + + memset(pbBuf, 0x00, SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_decryptByCRT(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) + * @brief RSA Decryption using CRT + * + * @param crt [in]rsa context + * @param in [in]message to decrypt + * @param inLen [in]byte-length of in + * @param out [out]decrypted message + * @param outLen [out]byte-length of out + * + * @return CRYPTO_SUCCESS if no error is occured + * \n CRYPTO_NULL_POINTER if an argument is a null pointer + * \n CRYPTO_MEMORY_ALLOC_FAIL if memory allocation is failed + */ +int SDRM_RSA_decryptByCRT(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) +{ + SDRM_BIG_NUM *BN_dMsg, *BN_Src; + int retVal; + cc_u32 plainLen; + cc_u32 RSA_KeyByteLen = 0; + SDRM_BIG_NUM *pi, *temp1, *temp2, *m1, *m2, *h; + cc_u8 *pbBuf = NULL; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL) || (in == NULL) || (out == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (crt->ctx->rsactx->crt_operation != 1) + { + return CRYPTO_INVALID_ARGUMENT; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + if (inLen > RSA_KeyByteLen) + { + return CRYPTO_MSG_TOO_LONG; + } + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 8 + RSA_KeyByteLen); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_dMsg = SDRM_BN_Alloc((cc_u8*)pbBuf + RSA_KeyByteLen, SDRM_RSA_BN_BUFSIZE); + BN_Src = SDRM_BN_Alloc((cc_u8*)BN_dMsg + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + pi = SDRM_BN_Alloc((cc_u8*)BN_Src + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp1 = SDRM_BN_Alloc((cc_u8*)pi + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + temp2 = SDRM_BN_Alloc((cc_u8*)temp1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + m1 = SDRM_BN_Alloc((cc_u8*)temp2 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + m2 = SDRM_BN_Alloc((cc_u8*)m1 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + h = SDRM_BN_Alloc((cc_u8*)m2 + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + SDRM_OS2BN(in, inLen, BN_Src); + + //RSA Decryption by CRT + /* + dp = d mod (p - 1) + dq = d mod (q - 1) + qInv = (1/q) mod p where p > q + => + m1 = c^dp mod p + m2 = c^dq mod q + h = qInv(m1 - m2) mod p if (m1 >= m2) or h = qInv(m1 + p - m2) mod p if (m1 < m2) + m = m2 + hq + */ + + // Prepare variables + // 1. dP = d mod (p - 1) + // dP is already set when SDRM_RSA_setNEDPQ + + // 2. dQ = d mod (q - 1) + // dQ is already set when SDRM_RSA_setNEDPQ + + // 3. qInv = (1/q) mod p where p > q + // qInv is already set when SDRM_RSA_setNEDPQ + + // Computation + // 4. m1 = c^dP mod p + if(SDRM_BN_ModExp2(m1, BN_Src, crt->ctx->rsactx->dmodp1, crt->ctx->rsactx->p)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + // 5. m2 = c^dQ mod q + if(SDRM_BN_ModExp2(m2, BN_Src, crt->ctx->rsactx->dmodq1, crt->ctx->rsactx->q)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + // 6. h = qInv(m1 - m2) mod p if (m1 >= m2) or h = qInv(m1 + p - m2) mod p if (m1 < m2) + if(SDRM_BN_Cmp(m1, m2) < 0) + { + if(SDRM_BN_Add(m1, m1, crt->ctx->rsactx->p)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + } + + if(SDRM_BN_Sub(m1, m1, m2)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if(SDRM_BN_ModMul(h, crt->ctx->rsactx->iqmodp, m1, crt->ctx->rsactx->p)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + // 7. m = m2 + hq + if(SDRM_BN_Mul(h, h, crt->ctx->rsactx->q)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if(SDRM_BN_Add(BN_dMsg, m2, h)) + { + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + +// SDRM_PrintBN("OAEP Text : ", BN_dMsg); + + SDRM_I2OSP(BN_dMsg, RSA_KeyByteLen, pbBuf); + + //Remove Padding from message + switch (SDRM_LOW_HALF(crt->ctx->rsactx->pm)) + { + case ID_RSAES_PKCS15: + retVal = SDRM_Depad_Rsaes_pkcs15(out, &plainLen, pbBuf, RSA_KeyByteLen, RSA_KeyByteLen); + break; + case ID_RSAES_OAEP: + retVal = SDRM_Depad_Rsaes_oaep(out, &plainLen, pbBuf, RSA_KeyByteLen, RSA_KeyByteLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_NO_PADDING: + memcpy(out, pbBuf, RSA_KeyByteLen); + plainLen = RSA_KeyByteLen; + retVal = CRYPTO_SUCCESS; + break; + default: + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + if (outLen != NULL) + { + *outLen = plainLen; + } + + memset(pbBuf, 0x00, SDRM_RSA_ALLOC_SIZE * 8 + RSA_KeyByteLen); + free(pbBuf); + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_RSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [out]generated signature + * @param signLen [out]byte-length of signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + */ +int SDRM_RSA_sign(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 *signLen) +{ + SDRM_BIG_NUM *BN_pMsg, *BN_Sign; + int retVal; + cc_u32 RSA_KeyByteLen = 0; + cc_u8 *pbBuf = NULL; + cc_u32 nBits; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL) || (hash == NULL) || (signature == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + if (hashLen > RSA_KeyByteLen) + { + return CRYPTO_MSG_TOO_LONG; + } + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_pMsg = SDRM_BN_Alloc((cc_u8*)pbBuf + RSA_KeyByteLen, SDRM_RSA_BN_BUFSIZE); + BN_Sign = SDRM_BN_Alloc((cc_u8*)BN_pMsg + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + //Msg Padding + switch(SDRM_LOW_HALF(crt->ctx->rsactx->pm)) + { + case ID_RSASSA_PKCS15 : + retVal = SDRM_Enpad_Rsassa_pkcs15(pbBuf, RSA_KeyByteLen, hash, hashLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_RSASSA_PSS : + SDRM_BN_GETBITLEN(crt->ctx->rsactx->n, nBits); + retVal = SDRM_Enpad_Rsassa_pss(pbBuf, nBits, hash, hashLen, RSA_KeyByteLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_NO_PADDING : + memset(pbBuf, 0x00, RSA_KeyByteLen - hashLen); + //memcpy(pbBuf + hashLen, hash, RSA_KeyByteLen); + memcpy(pbBuf + RSA_KeyByteLen - hashLen, hash, hashLen);// fixed by guoxing.xu 20140919 + retVal = CRYPTO_SUCCESS; + break; + default : + free(pbBuf); + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + +// SDRM_PrintBN("ENPADDED Msg : ", BN_pMsg); + + SDRM_OS2BN(pbBuf, RSA_KeyByteLen, BN_pMsg); + + //RSA Signature by modular exponent +#ifndef _OP64_NOTSUPPORTED + retVal = SDRM_BN_ModExp2(BN_Sign, BN_pMsg, crt->ctx->rsactx->d, crt->ctx->rsactx->n); +#else + retVal = SDRM_BN_ModExp(BN_Sign, BN_pMsg, crt->ctx->rsactx->d, crt->ctx->rsactx->n); +#endif //_OP64_NOTSUPPORTED + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + SDRM_I2OSP(BN_Sign, RSA_KeyByteLen, signature); + + if (signLen != NULL) + { + *signLen = RSA_KeyByteLen; + } + + memset(pbBuf, 0x00, SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + free(pbBuf); + + return retVal; +} + +/* + * @fn int SDRM_RSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result) + * @brief generate signature for given value + * + * @param crt [in]crypto env structure + * @param hash [in]hash value + * @param hashLen [in]byte-length of hash + * @param signature [in]signature + * @param signLen [in]byte-length of signature + * @param result [in]result of verifying signature + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if the length of signature is invalid + */ +int SDRM_RSA_verify(CryptoCoreContainer *crt, cc_u8 *hash, cc_u32 hashLen, cc_u8 *signature, cc_u32 signLen, int *result) +{ + SDRM_BIG_NUM *BN_dMsg, *BN_Sign; + int retVal; + cc_u32 RSA_KeyByteLen = 0; + cc_u8 *pbBuf = NULL; + cc_u32 nBits; + cc_u32 i; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rsactx == NULL) || (hash == NULL) || (signature == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + RSA_KeyByteLen = crt->ctx->rsactx->k; + if (hashLen > RSA_KeyByteLen) + { + return CRYPTO_MSG_TOO_LONG; + } + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_dMsg = SDRM_BN_Alloc((cc_u8*)pbBuf + RSA_KeyByteLen, SDRM_RSA_BN_BUFSIZE); + BN_Sign = SDRM_BN_Alloc((cc_u8*)BN_dMsg + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + SDRM_OS2BN(signature, signLen, BN_Sign); +// SDRM_PrintBN("Generated Sign : ", BN_Sign); + + //RSA Verification by modular exponent +#ifndef _OP64_NOTSUPPORTED + retVal = SDRM_BN_ModExp2(BN_dMsg, BN_Sign, crt->ctx->rsactx->e, crt->ctx->rsactx->n); +#else + retVal = SDRM_BN_ModExp(BN_dMsg, BN_Sign, crt->ctx->rsactx->e, crt->ctx->rsactx->n); +#endif //_OP64_NOTSUPPORTED + + if (retVal != CRYPTO_SUCCESS) + { + free(pbBuf); + return retVal; + } + + SDRM_I2OSP(BN_dMsg, RSA_KeyByteLen, pbBuf); + + //Msg Depadding + switch(SDRM_LOW_HALF(crt->ctx->rsactx->pm)) + { + case ID_RSASSA_PKCS15 : + *result = SDRM_Depad_Rsassa_pkcs15(pbBuf, RSA_KeyByteLen, hash, hashLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_RSASSA_PSS : + SDRM_BN_GETBITLEN(crt->ctx->rsactx->n, nBits); + *result = SDRM_Depad_Rsassa_pss(pbBuf, nBits, hash, hashLen, RSA_KeyByteLen, SDRM_HIGH_HALF(crt->ctx->rsactx->pm)); + break; + case ID_NO_PADDING : + for (i = 0; i < (RSA_KeyByteLen - hashLen); i++) + { + if (pbBuf[i] != 0) + { + *result = CRYPTO_INVALID_SIGN; + } + } + + if ((i == (RSA_KeyByteLen - hashLen)) && (memcmp(pbBuf + i, hash, hashLen) == 0)) + { + *result = CRYPTO_VALID_SIGN; + } + else + { + *result = CRYPTO_INVALID_SIGN; + } + + default : + break; + } + + memset(pbBuf, 0x00, SDRM_RSA_ALLOC_SIZE * 2 + RSA_KeyByteLen); + SDRM_BN_FREE(pbBuf); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ +int SDRM_Extended_GCD(SDRM_BIG_NUM* BN_v, SDRM_BIG_NUM* BN_a, SDRM_BIG_NUM* BN_b, SDRM_BIG_NUM* BN_x, SDRM_BIG_NUM* BN_y) +{ + SDRM_BIG_NUM* BN_g; + SDRM_BIG_NUM* BN_u; + SDRM_BIG_NUM* BN_A; + SDRM_BIG_NUM* BN_B; + SDRM_BIG_NUM* BN_C; + SDRM_BIG_NUM* BN_D; + SDRM_BIG_NUM* BN_tmp; + SDRM_BIG_NUM* BN_xx; + SDRM_BIG_NUM* BN_yy; + cc_u8* pbBuf = NULL; + cc_u32 RSA_KeyByteLen = 128; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 9); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_g = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + BN_u = SDRM_BN_Alloc((cc_u8*)BN_g + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_A = SDRM_BN_Alloc((cc_u8*)BN_u + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_B = SDRM_BN_Alloc((cc_u8*)BN_A + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_C = SDRM_BN_Alloc((cc_u8*)BN_B + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_D = SDRM_BN_Alloc((cc_u8*)BN_C + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_tmp = SDRM_BN_Alloc((cc_u8*)BN_D + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_xx = SDRM_BN_Alloc((cc_u8*)BN_tmp + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_yy = SDRM_BN_Alloc((cc_u8*)BN_xx + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + SDRM_BN_Copy(BN_g, BN_One); + SDRM_BN_Copy(BN_xx, BN_x); + SDRM_BN_Copy(BN_yy, BN_y); + + while(!SDRM_BN_IS_ODD(BN_xx) && !SDRM_BN_IS_ODD(BN_yy)) + { + SDRM_BN_SHR(BN_xx, BN_xx, 1); + SDRM_BN_SHR(BN_yy, BN_yy, 1); + SDRM_BN_SHL(BN_g, BN_g, 1); + } + + SDRM_BN_Copy(BN_u, BN_xx); + SDRM_BN_Copy(BN_v, BN_yy); + + SDRM_BN_Copy(BN_A, BN_One); + SDRM_BN_Copy(BN_B, BN_Zero); + SDRM_BN_Copy(BN_C, BN_Zero); + SDRM_BN_Copy(BN_D, BN_One); + + while(1) + { + while(!SDRM_BN_IS_ODD(BN_u)) + { + SDRM_BN_SHR(BN_u, BN_u, 1); + if (!SDRM_BN_IS_ODD(BN_A) && !SDRM_BN_IS_ODD(BN_B)) + { + SDRM_BN_SHR(BN_A, BN_A, 1); + SDRM_BN_SHR(BN_B, BN_B, 1); + } + else + { + SDRM_BN_Add(BN_A, BN_A, BN_yy); + SDRM_BN_SHR(BN_A, BN_A, 1); + + SDRM_BN_Sub(BN_tmp, BN_B, BN_xx); + SDRM_BN_SHR(BN_B, BN_tmp, 1); + } + } + + while(!SDRM_BN_IS_ODD(BN_v)) + { + SDRM_BN_SHR(BN_v, BN_v, 1); + if (!SDRM_BN_IS_ODD(BN_C) && !SDRM_BN_IS_ODD(BN_D)) + { + SDRM_BN_SHR(BN_C, BN_C, 1); + SDRM_BN_SHR(BN_D, BN_D, 1); + } + else + { + SDRM_BN_Add(BN_C, BN_C, BN_yy); + SDRM_BN_SHR(BN_C, BN_C, 1); + + SDRM_BN_Sub(BN_tmp, BN_D, BN_xx); + SDRM_BN_SHR(BN_D, BN_tmp, 1); + } + } + + if (SDRM_BN_Cmp(BN_u, BN_v) >= 0) + { + SDRM_BN_Sub(BN_tmp, BN_u, BN_v); + SDRM_BN_Copy(BN_u, BN_tmp); + + SDRM_BN_Sub(BN_tmp, BN_A, BN_C); + SDRM_BN_Copy(BN_A, BN_tmp); + + SDRM_BN_Sub(BN_tmp, BN_B, BN_D); + SDRM_BN_Copy(BN_B, BN_tmp); + } + else + { + SDRM_BN_Sub(BN_tmp, BN_v, BN_u); + SDRM_BN_Copy(BN_v, BN_tmp); + + SDRM_BN_Sub(BN_tmp, BN_C, BN_A); + SDRM_BN_Copy(BN_C, BN_tmp); + + SDRM_BN_Sub(BN_tmp, BN_D, BN_B); + SDRM_BN_Copy(BN_D, BN_tmp); + } + + if (SDRM_BN_Cmp(BN_u, BN_Zero) == 0) + { + SDRM_BN_Copy(BN_a, BN_C); + SDRM_BN_Copy(BN_b, BN_D); + SDRM_BN_Mul(BN_tmp, BN_g, BN_v); + SDRM_BN_Copy(BN_v, BN_tmp); + + break; + } + } + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + + +int SDRM_CheckRSAKey(SDRM_BIG_NUM* BN_n, SDRM_BIG_NUM* BN_e, SDRM_BIG_NUM* BN_d) +{ + SDRM_BIG_NUM* BN_m; + SDRM_BIG_NUM* BN_c; + SDRM_BIG_NUM* BN_m1; + cc_u8* pbBuf = NULL; + cc_u32 RSA_KeyByteLen = 128; + + int retVal; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 3); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_m = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + BN_c = SDRM_BN_Alloc((cc_u8*)BN_m + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_m1 = SDRM_BN_Alloc((cc_u8*)BN_c + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + SDRM_BN_Rand(BN_m, 1020); + + SDRM_BN_ModExp(BN_c, BN_m, BN_e, BN_n); + SDRM_BN_ModExp(BN_m1, BN_c, BN_d, BN_n); + + if (SDRM_BN_Cmp(BN_m, BN_m1) == 0) + { + retVal = CRYPTO_SUCCESS; + } + else + { + retVal = CRYPTO_ERROR; + } + + free(pbBuf); + + return retVal; +} + +int SDRM_RSA_ConvertCRT2PrivateExp(cc_u8 *p320byteCRTParam, cc_u8 *PrivateExp) +{ + SDRM_BIG_NUM* BN_g; + SDRM_BIG_NUM* BN_v; + SDRM_BIG_NUM* BN_diff; + SDRM_BIG_NUM* BN_k; + SDRM_BIG_NUM* BN_r; + SDRM_BIG_NUM* BN_l; + SDRM_BIG_NUM* BN_u; + SDRM_BIG_NUM* BN_n; + SDRM_BIG_NUM* BN_e; + SDRM_BIG_NUM* BN_d; + SDRM_BIG_NUM* BN_p; + SDRM_BIG_NUM* BN_q; + SDRM_BIG_NUM* BN_dp; + SDRM_BIG_NUM* BN_dq; + + cc_u8* pbBuf = NULL; + cc_u32 RSA_KeyByteLen = 128; + + pbBuf = (cc_u8*)malloc(SDRM_RSA_ALLOC_SIZE * 14); + if (pbBuf == NULL) + { + return CRYPTO_MEMORY_ALLOC_FAIL; + } + + BN_g = SDRM_BN_Alloc((cc_u8*)pbBuf, SDRM_RSA_BN_BUFSIZE); + BN_v = SDRM_BN_Alloc((cc_u8*)BN_g + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_diff = SDRM_BN_Alloc((cc_u8*)BN_v + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_k = SDRM_BN_Alloc((cc_u8*)BN_diff + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_r = SDRM_BN_Alloc((cc_u8*)BN_k + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_l = SDRM_BN_Alloc((cc_u8*)BN_r + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_u = SDRM_BN_Alloc((cc_u8*)BN_l + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_n = SDRM_BN_Alloc((cc_u8*)BN_u + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_e = SDRM_BN_Alloc((cc_u8*)BN_n + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_d = SDRM_BN_Alloc((cc_u8*)BN_e + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_p = SDRM_BN_Alloc((cc_u8*)BN_d + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_q = SDRM_BN_Alloc((cc_u8*)BN_p + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_dp = SDRM_BN_Alloc((cc_u8*)BN_q + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + BN_dq = SDRM_BN_Alloc((cc_u8*)BN_dp + SDRM_RSA_ALLOC_SIZE, SDRM_RSA_BN_BUFSIZE); + + SDRM_OS2BN(p320byteCRTParam, 64, BN_p); + SDRM_OS2BN(p320byteCRTParam + 64, 64, BN_q); + SDRM_OS2BN(p320byteCRTParam + 128, 64, BN_dp); + SDRM_OS2BN(p320byteCRTParam + 192, 64, BN_dq); + + SDRM_BN_Mul(BN_n, BN_p, BN_q); + + if (SDRM_BN_Cmp(BN_dp, BN_dq) < 0) + { + SDRM_BIG_NUM* tmp; + tmp = BN_p; + BN_p = BN_q; + BN_q = tmp; + + tmp = BN_dp; + BN_dp = BN_dq; + BN_dq = tmp; + } + + SDRM_BN_Sub(BN_p, BN_p, BN_One); + SDRM_BN_Sub(BN_q, BN_q, BN_One); + + SDRM_Extended_GCD(BN_g, BN_u, BN_v, BN_p, BN_q); + SDRM_BN_Sub(BN_diff, BN_dp, BN_dq); + SDRM_BN_Div(BN_k, NULL, BN_diff, BN_g); + + SDRM_BN_Mul(BN_r, BN_k, BN_u); + SDRM_BN_Mul(BN_k, BN_r, BN_p); + SDRM_BN_Sub(BN_d, BN_dp, BN_k); + + SDRM_BN_Mul(BN_k, BN_p, BN_q); + SDRM_BN_Div(BN_l, NULL, BN_k, BN_g); + + SDRM_BN_ModRed(BN_r, BN_d, BN_l); + + if ((SDRM_BN_Cmp(BN_r, BN_Zero) != 0) && SDRM_IS_BN_NEGATIVE(BN_r)) + { + SDRM_BN_Add(BN_d, BN_l, BN_r); + } + else + { + SDRM_BN_Copy(BN_d, BN_r); + } + + SDRM_BN_ModInv(BN_e, BN_d, BN_l); + SDRM_BN_ModInv(BN_d, BN_e, BN_k); + + if ((SDRM_BN_Cmp(BN_d, BN_Zero) != 0) && !SDRM_IS_BN_NEGATIVE(BN_d)) + { + SDRM_BN_ModRed(BN_r, BN_d, BN_p); + SDRM_PrintBN("n", BN_n); + SDRM_PrintBN("e", BN_e); + SDRM_PrintBN("d", BN_d); + + if (SDRM_BN_Cmp(BN_r, BN_dp) == 0) + { + if (SDRM_CheckRSAKey(BN_n, BN_e, BN_d) == CRYPTO_SUCCESS) + { + SDRM_BN2OS(BN_d, 128, PrivateExp); + } + } + } + + free(pbBuf); + + return CRYPTO_SUCCESS; +} + + diff --git a/ssflib/dep/cryptocore/source/middle/cc_symmetric.c b/ssflib/dep/cryptocore/source/middle/cc_symmetric.c new file mode 100755 index 0000000..b70f441 --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_symmetric.c @@ -0,0 +1,1703 @@ +/** + * \file symmetric.c + * @brief API for symmetric encryption + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon, Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/11/07 + */ + +//////////////////////////////////////////////////////////////////////////// +// Include Header Files +//////////////////////////////////////////////////////////////////////////// +#include "cc_symmetric.h" +#include "cc_moo.h" +#include "cc_rc4.h" +#include "cc_snow2.h" +#include +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_getEncRoundKey + * @brief get scheduled key for encryption + * + * @param Algorithm [in]cipher algorithm + * @param UserKey [in]user key + * @param RoundKey [out]round key + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_getEncRoundKey(int Algorithm, cc_u8* UserKey, cc_u8* RoundKey) +{ + if ((UserKey == NULL) || (RoundKey == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + switch (Algorithm) + { + case ID_AES128 : + SDRM_rijndaelKeySetupEnc((cc_u32*)(void*)RoundKey, UserKey, 128); + return CRYPTO_SUCCESS; + case ID_AES192 : + SDRM_rijndaelKeySetupEnc((cc_u32*)(void*)RoundKey, UserKey, 192); + return CRYPTO_SUCCESS; + case ID_AES256 : + SDRM_rijndaelKeySetupEnc((cc_u32*)(void*)RoundKey, UserKey, 256); + return CRYPTO_SUCCESS; + case ID_DES : + SDRM_DES_KeySched(RoundKey, UserKey, 0, 1); + return CRYPTO_SUCCESS; + case ID_TDES_EDE2 : + SDRM_TDES_KeySched(RoundKey, UserKey, 16, 1); + return CRYPTO_SUCCESS; + case ID_TDES_EDE3 : + SDRM_TDES_KeySched(RoundKey, UserKey, 24, 1); + return CRYPTO_SUCCESS; + default : + break; + } + + return CRYPTO_INVALID_ARGUMENT; +} + +/* + * @fn SDRM_getDecRoundKey + * @brief get scheduled key for decryption + * + * @param Algorithm [in]cipher algorithm + * @param UserKey [in]user key + * @param RoundKey [out]round key + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_getDecRoundKey(int Algorithm, cc_u8* UserKey, cc_u8* RoundKey) +{ + if ((UserKey == NULL) || (RoundKey == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + switch (Algorithm) + { + case ID_AES128 : + SDRM_rijndaelKeySetupDec((cc_u32*)(void*)RoundKey, UserKey, 128); + return CRYPTO_SUCCESS; + case ID_AES192 : + SDRM_rijndaelKeySetupDec((cc_u32*)(void*)RoundKey, UserKey, 192); + return CRYPTO_SUCCESS; + case ID_AES256 : + SDRM_rijndaelKeySetupDec((cc_u32*)(void*)RoundKey, UserKey, 256); + return CRYPTO_SUCCESS; + case ID_DES : + SDRM_DES_KeySched(RoundKey, UserKey, 15, (cc_u32)-1); + return CRYPTO_SUCCESS; + case ID_TDES_EDE2 : + SDRM_TDES_KeySched(RoundKey, UserKey, 16, (cc_u32)-1); + return CRYPTO_SUCCESS; + case ID_TDES_EDE3 : + SDRM_TDES_KeySched(RoundKey, UserKey, 24, (cc_u32)-1); + return CRYPTO_SUCCESS; + default : + break; + } + + return CRYPTO_INVALID_ARGUMENT; +} + +/* + * @fn SDRM_AES_init + * @brief intialize crypt context for aes + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_AES_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->aesctx == NULL) || (key == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (!(((mode >= 1111) && (mode <= 1115)) || ((mode >= 1121) && (mode <= 1125)))) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (!((crt->alg == ID_AES128) && (keysize == 16)) && + !((crt->alg == ID_AES192) && (keysize == 24)) && + !((crt->alg == ID_AES256) && (keysize == 32))) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if ((crt->alg != ID_AES128) && (crt->alg != ID_AES192) && (crt->alg != ID_AES256)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if ((PADDING != 0) && (PADDING != ID_PKCS5) && (PADDING != ID_SSL_PADDING) && (PADDING != ID_ZERO_PADDING) && (PADDING != ID_NO_PADDING)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + crt->ctx->aesctx->moo = mode; + + crt->ctx->aesctx->padding = PADDING; + + if (mode != ID_DEC_ECB && mode != ID_DEC_CBC) + { + SDRM_getEncRoundKey(crt->alg, key, crt->ctx->aesctx->RoundKey); + } + else + { + SDRM_getDecRoundKey(crt->alg, key, crt->ctx->aesctx->RoundKey); + } + + if (IV) + { + memcpy(crt->ctx->aesctx->IV, IV, SDRM_AES_BLOCK_SIZ); + } + else + { + memset(crt->ctx->aesctx->IV, 0x00, SDRM_AES_BLOCK_SIZ); + } + + crt->ctx->aesctx->BlockLen = 0; + + GET_UINT32(crt->ctx->aesctx->CTR_Count, crt->ctx->aesctx->IV + 12, 0); + + return CRYPTO_SUCCESS; + +} + +/* + * @fn SDRM_AES_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param Text [in]message block + * @param TextLen [in]byte-length of Text + * @param output [out]proecessed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_AES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen) +{ + int i, Temp; + int retVal, BlockLen; + cc_u8 *Block; + cc_u32 tempLen = 0; + + if (outputLen != NULL) + { + *outputLen = 0; + } + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->aesctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + Block = crt->ctx->aesctx->Block; + BlockLen = crt->ctx->aesctx->BlockLen; + + if ((TextLen + BlockLen) < SDRM_AES_BLOCK_SIZ) + { + memcpy(Block + BlockLen, Text, TextLen); + crt->ctx->aesctx->BlockLen += TextLen; + return CRYPTO_SUCCESS; + } + + if (BlockLen) + { + memcpy(Block + BlockLen, Text, SDRM_AES_BLOCK_SIZ - BlockLen); + + switch(crt->ctx->aesctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV, crt->ctx->aesctx->CTR_Count++); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(crt->alg, output, Block, crt->ctx->aesctx->RoundKey); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV, crt->ctx->aesctx->CTR_Count++); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + Temp = TextLen - SDRM_AES_BLOCK_SIZ + 1; + for (i = (SDRM_AES_BLOCK_SIZ - BlockLen) & 0x0f; i < Temp; i += SDRM_AES_BLOCK_SIZ) + { + switch(crt->ctx->aesctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV, crt->ctx->aesctx->CTR_Count++); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(crt->alg, output + tempLen, Text + i, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV, crt->ctx->aesctx->CTR_Count++); + tempLen += SDRM_AES_BLOCK_SIZ; + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + crt->ctx->aesctx->BlockLen = (SDRM_AES_BLOCK_SIZ + TextLen - i) & 0x0f; + memcpy(Block, Text + TextLen - crt->ctx->aesctx->BlockLen, crt->ctx->aesctx->BlockLen); + + if (outputLen != 0) + { + *outputLen = tempLen; + } + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_AES_final + * @brief process final block and padding + * + * @param crt [in]crypto env structure + * @param input [in]message block + * @param inputLen [in]byte-length of Text + * @param output [out]processed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_AES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen) +{ + int retVal = CRYPTO_SUCCESS; + cc_u8 *Block, PADDING[16]; + cc_u32 BlockLen; + cc_u8 t; + int i = 0; + + + + if (outputLen != NULL) + { + *outputLen = 0; + } + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->aesctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + Block = crt->ctx->aesctx->Block; + BlockLen = crt->ctx->aesctx->BlockLen; + i = 0; + printf("Block [%d]: %d\n", i, Block[0]); + + if (crt->ctx->aesctx->moo >= ID_DEC_ECB) + { + goto DECRYPTION; + } + +//ENCRYPTION: + if (inputLen != 0) + { + unsigned int temp; + retVal = SDRM_AES_process(crt, input, inputLen, output, &temp); + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + retVal = SDRM_AES_final(crt, NULL, 0, output + temp, outputLen); + + if (outputLen) + { + *outputLen += temp; + } + + return retVal; + } + + if (outputLen != NULL) + { + *outputLen = SDRM_AES_BLOCK_SIZ; + } + + //padding + switch(crt->ctx->aesctx->padding) + { + case 0 : + case ID_PKCS5 : + memset(Block + BlockLen, SDRM_AES_BLOCK_SIZ - BlockLen, SDRM_AES_BLOCK_SIZ - BlockLen); + break; + case ID_SSL_PADDING : + memset(Block + BlockLen, SDRM_AES_BLOCK_SIZ - BlockLen - 1, SDRM_AES_BLOCK_SIZ - BlockLen); + break; + case ID_ZERO_PADDING : + memset(Block + BlockLen, 0x00, SDRM_AES_BLOCK_SIZ - BlockLen); + break; + case ID_NO_PADDING : + if (BlockLen == 0) + { + if (outputLen) + { + *outputLen = 0; + } + return CRYPTO_SUCCESS; + } + break; + default : + { + + return CRYPTO_INVALID_ARGUMENT; + } + } + + //encryption + switch(crt->ctx->aesctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey); + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(crt->alg, output, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(crt->alg, Block, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV, crt->ctx->aesctx->CTR_Count++); + if(crt->ctx->aesctx->padding != ID_NO_PADDING)// add by xugx to support padding + { + BlockLen = SDRM_AES_BLOCK_SIZ; + } + memcpy(output, Block, BlockLen); + if(outputLen != NULL) + { + *outputLen = BlockLen; + } + break; + default : + { + retVal = CRYPTO_INVALID_ARGUMENT; + } + break; + } + + return retVal; + +DECRYPTION: + if (outputLen != NULL) + { + *outputLen = 0; + } + + if ((inputLen == 0) && (crt->ctx->aesctx->padding == ID_NO_PADDING) && (crt->ctx->aesctx->moo != ID_DEC_CTR)) + { + return CRYPTO_SUCCESS; + } + + if (((BlockLen + inputLen) != SDRM_AES_BLOCK_SIZ) && (crt->ctx->aesctx->moo != ID_DEC_CTR)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (inputLen != 0) + { + memcpy(Block + BlockLen, input, inputLen); + } + + switch(crt->ctx->aesctx->moo) + { + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(crt->alg, Block, Block, crt->ctx->aesctx->RoundKey); + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(crt->alg, Block, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(crt->alg, Block, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(crt->alg, Block, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV); + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(crt->alg, Block, Block, crt->ctx->aesctx->RoundKey, crt->ctx->aesctx->IV, crt->ctx->aesctx->CTR_Count++); + break; + default : + { + return CRYPTO_INVALID_ARGUMENT; + } + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + //de-padding + + t = Block[SDRM_AES_BLOCK_SIZ - 1]; + + switch(crt->ctx->aesctx->padding) + { + case 0 : + case ID_PKCS5 : + { i = 0; + //for (; i < 16; i++) + printf("Block [%d]: %d\n", i, Block[i]); + + if ((t > SDRM_AES_BLOCK_SIZ) || (t < 1)) + { + return CRYPTO_INVALID_ARGUMENT; + } + memset(PADDING, t, t); + break; + } + case ID_SSL_PADDING : + ++t; + if ((t > SDRM_AES_BLOCK_SIZ) || (t < 1)) + { + return CRYPTO_INVALID_ARGUMENT; + } + memset(PADDING, t - 1, t); + break; + case ID_ZERO_PADDING : + { + cc_u32 tmpLen; + tmpLen = SDRM_AES_BLOCK_SIZ; + while((tmpLen != 0x00) && (Block[tmpLen - 1] == 0x00)) + { + tmpLen--; + } + + memcpy(output, Block, tmpLen); + + if (outputLen != NULL) + { + *outputLen = tmpLen; + } + } + return CRYPTO_SUCCESS; + case ID_NO_PADDING : + { + cc_u32 tmpLen; + tmpLen = SDRM_AES_BLOCK_SIZ; + + if (crt->ctx->aesctx->moo == ID_DEC_CTR) + { + tmpLen = BlockLen + inputLen; + } + else + { + tmpLen = SDRM_AES_BLOCK_SIZ; + } + + memcpy(output, Block, tmpLen); + + if (outputLen != NULL) + { + *outputLen = tmpLen; + } + } + return CRYPTO_SUCCESS; + default : + if (outputLen != NULL) + { + *outputLen = 0; + + return CRYPTO_INVALID_ARGUMENT; + } + } + + if (memcmp(PADDING, Block + SDRM_AES_BLOCK_SIZ - t, t) != 0) + { + return CRYPTO_INVALID_ARGUMENT; + } + + memcpy(output, Block, SDRM_AES_BLOCK_SIZ -t); + + if (outputLen != NULL) + { + *outputLen = SDRM_AES_BLOCK_SIZ - t; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_RC4_init + * @brief intialize crypt context for RC4 + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method, not needed + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector, not needed + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_RC4_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rc4ctx == NULL) || (key == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (keysize > 32) + { + return CRYPTO_INVALID_ARGUMENT; + } + + SDRM_RC4_Setup(crt->ctx->rc4ctx, key, keysize); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_RC4_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param in [in]message block + * @param inLen [in]byte-length of Text + * @param out [out]processed message + * @param outLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_RC4_process(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->rc4ctx == NULL) || (in == NULL) || (out == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + + SDRM_RC4_PRNG(crt->ctx->rc4ctx, in, inLen, out); + + if (outLen != NULL) + { + *outLen = inLen; + } + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_SNOW2_init + * @brief intialize crypt context for SNOW2 + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method, not needed + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_SNOW2_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->snow2ctx == NULL) || (key == NULL) || (IV == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if ((keysize != 16) && (keysize != 32)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + SDRM_SNOW2_Setup(crt->ctx->snow2ctx, key, keysize, IV); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_SNOW2_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param in [in]message block + * @param inLen [in]byte-length of Text + * @param out [out]processed message + * @param outLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_SNOW2_process(CryptoCoreContainer *crt, cc_u8 *in, cc_u32 inLen, cc_u8 *out, cc_u32 *outLen) +{ + cc_u32 i, j, BlockLen, rpt, loc; + cc_u32 keyStream64[16], keyStream; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->snow2ctx == NULL) || (in == NULL) || (out == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if ((inLen & 0x03) != 0) + { + return CRYPTO_INVALID_ARGUMENT; + } + + BlockLen = inLen / 64; + + if (crt->ctx->snow2ctx->endian == CRYPTO_LITTLE_ENDIAN) + { //little endian machine + for (i = 0; i < BlockLen; i++) + { + SDRM_SNOW2_getKeyStream64(crt->ctx->snow2ctx, keyStream64); + + for (j = 0; j < 16; j++) + { + loc = i * 64 + j * 4; + out[loc ] = (cc_u8)(in[loc ] ^ ((keyStream64[j] >> 24) & 0xff)); + out[loc + 1] = (cc_u8)(in[loc + 1] ^ ((keyStream64[j] >> 16) & 0xff)); + out[loc + 2] = (cc_u8)(in[loc + 2] ^ ((keyStream64[j] >> 8) & 0xff)); + out[loc + 3] = (cc_u8)(in[loc + 3] ^ ((keyStream64[j] ) & 0xff)); + } + } + } + else + { //big endian machine + for (i = 0; i < BlockLen; i++) + { + SDRM_SNOW2_getKeyStream64(crt->ctx->snow2ctx, keyStream64); + + for (j = 0; j < 16; j++) + { + ((cc_u32*)(void*)out)[j] = ((cc_u32*)(void*)in)[j] ^ keyStream64[j]; + } + } + } + + in += BlockLen * 64; + out += BlockLen * 64; + + rpt = (inLen - (BlockLen * 64)) / 4; + + if (crt->ctx->snow2ctx->endian == CRYPTO_LITTLE_ENDIAN) + { //little endian machine + for (i = 0; i < rpt; i++) + { + SDRM_SNOW2_getKeyStream(crt->ctx->snow2ctx, &keyStream); + loc = i * 4; + out[loc ] = (cc_u8)(in[loc ] ^ ((keyStream >> 24) & 0xff)); + out[loc + 1] = (cc_u8)(in[loc + 1] ^ ((keyStream >> 16) & 0xff)); + out[loc + 2] = (cc_u8)(in[loc + 2] ^ ((keyStream >> 8) & 0xff)); + out[loc + 3] = (cc_u8)(in[loc + 3] ^ ((keyStream ) & 0xff)); + } + } + else + { //big endian machine + for (i = 0; i < rpt; i++) + { + SDRM_SNOW2_getKeyStream(crt->ctx->snow2ctx, &keyStream); + ((cc_u32*)(void*)out)[i] = ((cc_u32*)(void*)in)[i] ^ keyStream; + } + } + + if (outLen != NULL) + { + *outLen = inLen; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DES_init + * @brief intialize crypt context for des + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_DES_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->desctx == NULL) || (key == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if ((keysize != 8) || !(((mode >= 1111) && (mode <= 1115)) || ((mode >= 1121) && (mode <= 1125)))) + { + return CRYPTO_INVALID_ARGUMENT; + } + + crt->ctx->desctx->moo = mode; + + if ((PADDING != 0) && (PADDING != ID_PKCS5) && (PADDING != ID_SSL_PADDING) && (PADDING != ID_ZERO_PADDING) && (PADDING != ID_NO_PADDING)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + crt->ctx->desctx->padding = PADDING; + + + if (mode != ID_DEC_ECB && mode != ID_DEC_CBC) + { + SDRM_getEncRoundKey(ID_DES, key, (cc_u8*)(crt->ctx->desctx->RoundKey)); + } + else + { + SDRM_getDecRoundKey(ID_DES, key, (cc_u8*)(crt->ctx->desctx->RoundKey)); + } + + crt->ctx->desctx->BlockLen = 0; + crt->ctx->desctx->CTR_Count = 0; + + memcpy(crt->ctx->desctx->UserKey, key, SDRM_DES_BLOCK_SIZ); + + if (IV) + { + memcpy(crt->ctx->desctx->IV, IV, SDRM_DES_BLOCK_SIZ); + } + else + { + memset(crt->ctx->desctx->IV, 0x00, SDRM_DES_BLOCK_SIZ); + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DES_process + * @brief process message block + * + * @param crt [in]crypto env structure + * @param Text [in]message block + * @param TextLen [in]byte-length of Text + * @param output [out]proecessed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_DES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen) +{ + int i, Temp; + int retVal, BlockLen; + cc_u8 *Block; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->desctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + Block = crt->ctx->desctx->Block; + BlockLen = crt->ctx->desctx->BlockLen; + + *outputLen = 0; + + if ((TextLen + BlockLen) < SDRM_DES_BLOCK_SIZ) + { + memcpy(Block + BlockLen, Text, TextLen); + crt->ctx->desctx->BlockLen += TextLen; + return CRYPTO_SUCCESS; + } + + if (BlockLen) + { + memcpy(Block + BlockLen, Text, SDRM_DES_BLOCK_SIZ - BlockLen); + + switch(crt->ctx->desctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV, crt->ctx->desctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV, crt->ctx->desctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + Temp = TextLen + BlockLen - SDRM_DES_BLOCK_SIZ + 1; + for (i = (SDRM_DES_BLOCK_SIZ - BlockLen) & 0x07; i < Temp; i += SDRM_DES_BLOCK_SIZ) + { + switch(crt->ctx->desctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV, crt->ctx->desctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(ID_DES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV, crt->ctx->desctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + crt->ctx->desctx->BlockLen = (SDRM_DES_BLOCK_SIZ + TextLen - i) & 0x07; + memcpy(Block, Text + TextLen - crt->ctx->desctx->BlockLen, crt->ctx->desctx->BlockLen); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_DES_final + * @brief process final block and padding + * + * @param crt [in]crypto env structure + * @param input [in]message block + * @param inputLen [in]byte-length of Text + * @param output [out]processed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_DES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen) +{ + int retVal = CRYPTO_SUCCESS; + cc_u8 *Block, PADDING[16]; + cc_u32 BlockLen, t; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->desctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + Block = crt->ctx->desctx->Block; + BlockLen = crt->ctx->desctx->BlockLen; + + if (crt->ctx->desctx->moo >= ID_DEC_ECB) + { + goto DECRYPTION; + } + +//ENCRYPTION: + if (inputLen != 0) + { + retVal = SDRM_DES_process(crt, input, inputLen, output, outputLen); + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + retVal = SDRM_DES_final(crt, NULL, 0, output + *outputLen, &t); + *outputLen += t; + + return retVal; + } + + if (outputLen != NULL) + { + *outputLen = SDRM_DES_BLOCK_SIZ; + } + + //padding + switch(crt->ctx->desctx->padding) + { + case 0 : + case ID_PKCS5 : + memset(Block + BlockLen, SDRM_DES_BLOCK_SIZ - BlockLen, SDRM_DES_BLOCK_SIZ - BlockLen); + break; + case ID_SSL_PADDING : + memset(Block + BlockLen, SDRM_DES_BLOCK_SIZ - BlockLen - 1, SDRM_DES_BLOCK_SIZ - BlockLen); + break; + case ID_ZERO_PADDING : + memset(Block + BlockLen, 0x00, SDRM_DES_BLOCK_SIZ - BlockLen); + break; + case ID_NO_PADDING : + if (BlockLen == 0) + { + if (outputLen) + { + *outputLen = 0; + } + return CRYPTO_SUCCESS; + } + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + + //encryption + switch(crt->ctx->desctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey); + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV, crt->ctx->desctx->CTR_Count++); + break; + default : + retVal = CRYPTO_INVALID_ARGUMENT; + break; + } + + return retVal; + +DECRYPTION: + if (outputLen != NULL) + { + *outputLen = 0; + } + + if ((inputLen == 0) && (crt->ctx->desctx->padding == ID_NO_PADDING)) + { + return CRYPTO_SUCCESS; + } + + if ((BlockLen + inputLen) != SDRM_DES_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (inputLen != 0) + { + memcpy(Block + BlockLen, input, inputLen); + } + + switch(crt->ctx->desctx->moo) + { + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey); + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV); + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(ID_DES, output, Block, (cc_u8*)crt->ctx->desctx->RoundKey, crt->ctx->desctx->IV, crt->ctx->desctx->CTR_Count++); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + //de-padding + t = output[SDRM_DES_BLOCK_SIZ - 1]; + + switch(crt->ctx->desctx->padding) + { + case 0 : + case ID_PKCS5 : + if ((t > SDRM_DES_BLOCK_SIZ) || (t < 1)) + { + return CRYPTO_INVALID_ARGUMENT; + } + memset(PADDING, t, t); + break; + case ID_SSL_PADDING : + ++t; + if ((t > SDRM_DES_BLOCK_SIZ) || (t < 1)) + { + return CRYPTO_INVALID_ARGUMENT; + } + memset(PADDING, t - 1, t); + break; + case ID_ZERO_PADDING : + { + cc_u32 tmpLen; + tmpLen = SDRM_DES_BLOCK_SIZ; + while((tmpLen != 0x00) && (output[tmpLen - 1] == 0x00)) + { + tmpLen--; + } + + if (outputLen != NULL) + { + *outputLen = tmpLen; + } + } + return CRYPTO_SUCCESS; + case ID_NO_PADDING : + if (outputLen != NULL) + { + *outputLen = SDRM_DES_BLOCK_SIZ; + } + return CRYPTO_SUCCESS; + default : + if (outputLen != NULL) + { + *outputLen = 0; + } + return CRYPTO_INVALID_ARGUMENT; + } + + if (memcmp(PADDING, output + SDRM_DES_BLOCK_SIZ - t, t) != 0) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (outputLen != NULL) + { + *outputLen = SDRM_DES_BLOCK_SIZ - t; + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_TDES_init + * @brief intialize crypt context for triple des + * + * @param crt [out]crypto env structure + * @param mode [in]encryption|decryption and mode of operation + * @param PADDING [in]padding method + * @param key [in]user key + * @param keysize [in]byte-length of key + * @param IV [in]initial vector + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_TDES_init(CryptoCoreContainer *crt, cc_u32 mode, cc_u32 PADDING, cc_u8 *key, cc_u32 keysize, cc_u8 *IV) +{ + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->tdesctx == NULL) || (key == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + if (((keysize != 16) && (keysize != 24)) || !(((mode >= 1111) && (mode <= 1115)) || ((mode >= 1121) && (mode <= 1125)))) + { + return CRYPTO_INVALID_ARGUMENT; + } + + crt->ctx->tdesctx->moo = mode; + + if ((PADDING != 0) && (PADDING != ID_PKCS5) && (PADDING != ID_SSL_PADDING) && (PADDING != ID_ZERO_PADDING) && (PADDING != ID_NO_PADDING)) + { + return CRYPTO_INVALID_ARGUMENT; + } + + crt->ctx->tdesctx->padding = PADDING; + + if ((mode != ID_DEC_ECB) && (mode != ID_DEC_CBC)) + { + if (keysize == 16) + { + SDRM_getEncRoundKey(ID_TDES_EDE2, key, (cc_u8*)(crt->ctx->tdesctx->RoundKey)); + } + else + { + SDRM_getEncRoundKey(ID_TDES_EDE3, key, (cc_u8*)(crt->ctx->tdesctx->RoundKey)); + } + } + else + { + if (keysize == 16) + { + SDRM_getDecRoundKey(ID_TDES_EDE2, key, (cc_u8*)(crt->ctx->tdesctx->RoundKey)); + } + else + { + SDRM_getDecRoundKey(ID_TDES_EDE3, key, (cc_u8*)(crt->ctx->tdesctx->RoundKey)); + } + } + + crt->ctx->tdesctx->BlockLen = 0; + crt->ctx->tdesctx->CTR_Count = 0; + + memcpy(crt->ctx->tdesctx->UserKey, key, SDRM_DES_BLOCK_SIZ); + + if (IV) + { + memcpy(crt->ctx->tdesctx->IV, IV, SDRM_DES_BLOCK_SIZ); + } + else + { + memset(crt->ctx->tdesctx->IV, 0x00, SDRM_DES_BLOCK_SIZ); + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn int SDRM_TDES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen) + * @brief process message block + * + * @param crt [in]crypto env structure + * @param Text [in]message block + * @param TextLen [in]byte-length of Text + * @param output [out]proecessed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_TDES_process(CryptoCoreContainer *crt, cc_u8 *Text, cc_u32 TextLen, cc_u8 *output, cc_u32 *outputLen) +{ + int i, Temp; + int retVal, BlockLen; + cc_u8 *Block; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->tdesctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + Block = crt->ctx->tdesctx->Block; + BlockLen = crt->ctx->tdesctx->BlockLen; + + *outputLen = 0; + + if ((TextLen + BlockLen) < SDRM_DES_BLOCK_SIZ) + { + memcpy(Block + BlockLen, Text, TextLen); + crt->ctx->tdesctx->BlockLen += TextLen; + return CRYPTO_SUCCESS; + } + + if (BlockLen) + { + memcpy(Block + BlockLen, Text, SDRM_DES_BLOCK_SIZ - BlockLen); + + switch(crt->ctx->tdesctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV, crt->ctx->tdesctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV, crt->ctx->tdesctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + Temp = TextLen + BlockLen - SDRM_DES_BLOCK_SIZ + 1; + for (i = (SDRM_DES_BLOCK_SIZ - BlockLen) & 0x07; i < Temp; i += SDRM_DES_BLOCK_SIZ) + { + switch(crt->ctx->tdesctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV, crt->ctx->tdesctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(ID_TDES, output + *outputLen, Text + i, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV, crt->ctx->tdesctx->CTR_Count++); + *outputLen += SDRM_DES_BLOCK_SIZ; + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + } + + crt->ctx->tdesctx->BlockLen = (SDRM_DES_BLOCK_SIZ + TextLen - i) & 0x07; + memcpy(Block, Text + TextLen - crt->ctx->tdesctx->BlockLen, crt->ctx->tdesctx->BlockLen); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn int SDRM_TDES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen) + * @brief process final block and padding + * + * @param crt [in]crypto env structure + * @param input [in]message block + * @param inputLen [in]byte-length of Text + * @param output [out]processed message + * @param outputLen [out]byte-length of output + * + * @return CRYPTO_SUCCESS if success + * \n CRYPTO_NULL_POINTER if given argument is a null pointer + * \n CRYPTO_INVALID_ARGUMENT if given argument is invalid + */ +int SDRM_TDES_final(CryptoCoreContainer *crt, cc_u8 *input, cc_u32 inputLen, cc_u8 *output, cc_u32 *outputLen) +{ + int retVal = CRYPTO_SUCCESS; + cc_u8 *Block, PADDING[16]; + cc_u32 BlockLen, t; + + if ((crt == NULL) || (crt->ctx == NULL) || (crt->ctx->tdesctx == NULL)) + { + return CRYPTO_NULL_POINTER; + } + + Block = crt->ctx->tdesctx->Block; + BlockLen = crt->ctx->tdesctx->BlockLen; + + + if (crt->ctx->tdesctx->moo >= ID_DEC_ECB) + { + goto DECRYPTION; + } + +//ENCRYPTION: + if (inputLen != 0) + { + retVal = SDRM_TDES_process(crt, input, inputLen, output, outputLen); + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + retVal = SDRM_TDES_final(crt, NULL, 0, output + *outputLen, &t); + *outputLen += t; + + return retVal; + } + + if (outputLen != NULL) + { + *outputLen = SDRM_DES_BLOCK_SIZ; + } + + //padding + switch(crt->ctx->tdesctx->padding) + { + case 0 : + case ID_PKCS5 : + memset(Block + BlockLen, SDRM_DES_BLOCK_SIZ - BlockLen, SDRM_DES_BLOCK_SIZ - BlockLen); + break; + case ID_SSL_PADDING : + memset(Block + BlockLen, SDRM_DES_BLOCK_SIZ - BlockLen - 1, SDRM_DES_BLOCK_SIZ - BlockLen); + break; + case ID_ZERO_PADDING : + memset(Block + BlockLen, 0x00, SDRM_DES_BLOCK_SIZ - BlockLen); + break; + case ID_NO_PADDING : + if (BlockLen == 0) + { + if (outputLen) + { + *outputLen = 0; + } + return CRYPTO_SUCCESS; + } + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + //encryption + switch(crt->ctx->tdesctx->moo) + { + case ID_ENC_ECB : + retVal = SDRM_ECB_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey); + break; + case ID_ENC_CBC : + retVal = SDRM_CBC_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + break; + case ID_ENC_CFB : + retVal = SDRM_CFB_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + break; + case ID_ENC_OFB : + retVal = SDRM_OFB_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + break; + case ID_ENC_CTR : + retVal = SDRM_CTR_Enc(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV, crt->ctx->tdesctx->CTR_Count++); + break; + default : + retVal = CRYPTO_INVALID_ARGUMENT; + break; + } + + return retVal; + +DECRYPTION: + if (outputLen != NULL) + { + *outputLen = 0; + } + + if ((inputLen == 0) && (crt->ctx->tdesctx->padding == ID_NO_PADDING)) + { + return CRYPTO_SUCCESS; + } + + if ((BlockLen + inputLen) != SDRM_DES_BLOCK_SIZ) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (inputLen != 0) + { + memcpy(Block + BlockLen, input, inputLen); + } + + switch(crt->ctx->tdesctx->moo) + { + case ID_DEC_ECB : + retVal = SDRM_ECB_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey); + break; + case ID_DEC_CBC : + retVal = SDRM_CBC_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + break; + case ID_DEC_CFB : + retVal = SDRM_CFB_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + break; + case ID_DEC_OFB : + retVal = SDRM_OFB_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV); + break; + case ID_DEC_CTR : + retVal = SDRM_CTR_Dec(ID_TDES, output, Block, (cc_u8*)crt->ctx->tdesctx->RoundKey, crt->ctx->tdesctx->IV, crt->ctx->tdesctx->CTR_Count++); + break; + default : + return CRYPTO_INVALID_ARGUMENT; + } + + if (retVal != CRYPTO_SUCCESS) + { + return retVal; + } + + //de-padding + t = output[SDRM_DES_BLOCK_SIZ - 1]; + + switch(crt->ctx->tdesctx->padding) + { + case 0 : + case ID_PKCS5 : + if ((t > SDRM_DES_BLOCK_SIZ) || (t < 1)) + { + return CRYPTO_INVALID_ARGUMENT; + } + memset(PADDING, t, t); + break; + case ID_SSL_PADDING : + ++t; + if ((t > SDRM_DES_BLOCK_SIZ) || (t < 1)) + { + return CRYPTO_INVALID_ARGUMENT; + } + memset(PADDING, t - 1, t); + break; + case ID_ZERO_PADDING : + { + cc_u32 tmpLen; + tmpLen = SDRM_TDES_BLOCK_SIZ; + while((tmpLen != 0x00) && (output[tmpLen - 1] == 0x00)) + { + tmpLen--; + } + + if (outputLen != NULL) + { + *outputLen = tmpLen; + } + } + return CRYPTO_SUCCESS; + case ID_NO_PADDING : + if (outputLen != NULL) + { + *outputLen = SDRM_TDES_BLOCK_SIZ; + } + return CRYPTO_SUCCESS; + default : + if (outputLen != NULL) + { + *outputLen = 0; + } + return CRYPTO_INVALID_ARGUMENT; + } + + if (memcmp(PADDING, output + SDRM_TDES_BLOCK_SIZ - t, t) != 0) + { + return CRYPTO_INVALID_ARGUMENT; + } + + if (outputLen != NULL) + { + *outputLen = SDRM_DES_BLOCK_SIZ - t; + } + + return CRYPTO_SUCCESS; + +} + +/***************************** End of File *****************************/ diff --git a/ssflib/dep/cryptocore/source/middle/cc_tdes.c b/ssflib/dep/cryptocore/source/middle/cc_tdes.c new file mode 100755 index 0000000..269a122 --- /dev/null +++ b/ssflib/dep/cryptocore/source/middle/cc_tdes.c @@ -0,0 +1,131 @@ +/** + * \file tdes.c + * @brief high-speed implementation of Triple DES-EDE + * + * - Copyright : Samsung Electronics CO.LTD., + * + * \internal + * Author : Jisoon Park + * Dept : DRM Lab, Digital Media Laboratory + * Creation date : 2006/12/06 + */ + +////////////////////////////////////////////////////////////////////////// +// Include Header Files +////////////////////////////////////////////////////////////////////////// +#include "cc_tdes.h" +#include "cc_des.h" + +//////////////////////////////////////////////////////////////////////////// +// Functions +//////////////////////////////////////////////////////////////////////////// +/* + * @fn SDRM_TDES_KeySched + * @brief Expand the cipher key into the encryption key schedule + * + * @param RoundKey [out]generated round key + * @param UserKey [in]user key, 16 or 24 byte + * @param KeyLen [in]byte-length of UserKey + * @param RKStep [in]operation mode + * + * @return the number of rounds for the given cipher key size + */ +int SDRM_TDES_KeySched(cc_u8 *RoundKey, cc_u8 *UserKey, cc_u32 KeyLen, cc_u32 RKStep) +{ + + if (RKStep == 1) + { + SDRM_DES_KeySched(RoundKey, UserKey, 0, 1); + SDRM_DES_KeySched(RoundKey + 128, UserKey + 8, 15, (cc_u32)-1); + + if (KeyLen == 16) + { //2-key des + memcpy(RoundKey + 256, RoundKey, 128); + } + else + { //3-key des + SDRM_DES_KeySched(RoundKey + 256, UserKey + 16, 0, 1); + } + } + else { + SDRM_DES_KeySched(RoundKey + 256, UserKey, 15, (cc_u32)-1); + SDRM_DES_KeySched(RoundKey + 128, UserKey + 8, 0, 1); + + if (KeyLen == 16) + { //2-key des + memcpy(RoundKey, RoundKey + 256, 128); + } + else + { //3-key des + SDRM_DES_KeySched(RoundKey, UserKey + 16, 15, (cc_u32)-1); + } + } + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_TDES_Encryption + * @brief Triple DES processing for one block + * + * @param RoundKey [in]expanded round key + * @param msg [in]8 byte plaintext + * @param out [out]8 byte ciphertext + * + * @return CRYPTO_SUCCESS if no error is occured + */ +int SDRM_TDES_Encryption(cc_u32 RoundKey[][2], cc_u8 *msg, cc_u8 *out) +{ + cc_u8 buf[8]; + + SDRM_DES_Encryption(RoundKey , msg, buf); + SDRM_DES_Encryption(RoundKey + 16, buf, buf); + SDRM_DES_Encryption(RoundKey + 32, buf, out); + + return CRYPTO_SUCCESS; +} + + +/* + * @fn SDRM_TDES64_Encryption + * @brief one block Triple DES Encryption + * + * @param cipherText [out]encrypted text + * @param plainText [in]plain text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_TDES64_Encryption(cc_u8 *cipherText, cc_u8 *plainText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[48][2]; + + SDRM_TDES_KeySched((cc_u8*)RoundKey, UserKey, 16, 1); + + SDRM_TDES_Encryption(RoundKey, plainText, cipherText); + + return CRYPTO_SUCCESS; +} + +/* + * @fn SDRM_TDES64_Decryption + * @brief one block Triple DES Decryption + * + * @param plainText [out]decrypted text + * @param cipherText [in]cipher text + * @param UserKey [in]user key + * + * @return CRYPTO_SUCCESS if success + */ +int SDRM_TDES64_Decryption(cc_u8 *plainText, cc_u8 *cipherText, cc_u8 *UserKey) +{ + cc_u32 RoundKey[48][2]; + + SDRM_TDES_KeySched((cc_u8*)RoundKey, UserKey, 16, (cc_u32)-1); + + SDRM_TDES_Encryption(RoundKey, cipherText, plainText); + + return CRYPTO_SUCCESS; +} + +/***************************** End of File *****************************/ \ No newline at end of file diff --git a/ssflib/dep/swdss/include/file_op.h b/ssflib/dep/swdss/include/file_op.h new file mode 100755 index 0000000..d878006 --- /dev/null +++ b/ssflib/dep/swdss/include/file_op.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _SECRUITY_FILE_OP_H_ +#define _SECRUITY_FILE_OP_H_ + +#include "ss_types.h" +#include "slog.h" +#include + +#define CURRENT_DIR "." +#define PARENT_DIR ".." + +class file_op { +public: + + /** + * @brief write file + * + * write buffer into file. + * @param[in] filename File full path. + * @param[in] buffer Point to data buffer. + * @param[in] size Size of data buffer. + * @retval 0 if success. + * @retval -1 if fail. + */ + static int write_file(const char* filename, unsigned char* buffer, + unsigned int size); + + /** + * @brief read file + * + * Read file into buffer. + * @param[in] filename File full path. + * @param[in] buffer Point to data buffer. + * @param[in] size Size of data buffer. + * @retval 0 if success. + * @retval -1 if fail. + */ + static int read_file(const char* filename, unsigned char** buffer, + unsigned int& size); + + /** + * @brief remove file + * + * Read file into buffer. + * @param[in] filename File full path. + * @retval 0 if success. + * @retval -1 if fail. + */ + static int remove_file(const char* filename); + + /** + * @brief Validates data file path. + * @param[in] filename File full path. + * @return non-zero value in the case of failure + */ + static int is_valid_filename(const char* filename); + + /** + * + * @brief Creates folder inside of the given folder. + * @param[in] folder Folder path. + * @retval 0 if success. + * @retval -1 if fail. + */ + static int create_folder(const char* folder); + + /** + * @brief Remove folder + * + * Remove folder recursively. + * @param[in] folder Folder path. + * @retval 0 if success. + * @retval -1 if fail. + */ + static int remove_folder(const char* folder); + + /** + * @brief Check if folder exist + * + * Check whether specific folder exist. + * @param[in] folder Folder path. + * @retval ture if exists. + * @retval false if not exist. + */ + + static bool is_folder_exists(const char* folder); + + static bool is_file_exists(const char* file); + + /** + * @brief Get base path + * + * Get base path of specific file. + * @param[in] filename Full file path. + * @return base path + */ + static void get_base_path(const char* filename, char* base_path); + +}; + +#endif + diff --git a/ssflib/dep/swdss/include/secure_file.h b/ssflib/dep/swdss/include/secure_file.h new file mode 100755 index 0000000..a7d4e76 --- /dev/null +++ b/ssflib/dep/swdss/include/secure_file.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _SWD_SECURE_FILE_H_ +#define _SWD_SECURE_FILE_H_ + +#include "ss_temp_store.h" +#include "ss_types.h" + +// this is hash material size, the real hash size is equal to SHA1 size 20 bytes +static const CBT_UINT32 HASH_SIZE = 40; +// header size may be bigger then 16 bytes, but non-less +static const CBT_UINT32 HEADER_SIZE = 16; +// this is key material size, the real key size is equal to AES 128 size 16 bytes +static const CBT_UINT32 KEY_MAT_SIZE = 64; +// encrypted key with size info buffer size +static const CBT_UINT32 RSA_KEY_SIZE = 256; +static const CBT_UINT32 ENCRYPTED_KEY_SIZE = RSA_KEY_SIZE + 4; + +/** + * @brief Secure file structure + * + */ +typedef struct secure_file_content { + secure_file_content() { + m_pFileHeader = NULL; + m_pHashMaterial = NULL; + m_pKeyMaterial = NULL; + m_pEncryptedKey = NULL; + m_pFileContent = NULL; + m_pOutputContent = NULL; + m_bHeaderAllocated = false; + m_bHashAllocated = false; + m_bKeyAllocated = false; + m_bEncryptedKeyAllocated = false; + m_bFileContentAllocated = false; + m_uFileHeaderSize = 0; + m_uHashMaterialSize = 0; + m_uKeyMaterialSize = 0; + m_uEncryptedKeySize = 0; + m_uFileContentSize = 0; + m_pOutputContentSize = 0; + } + + bool m_bHeaderAllocated; + CBT_OCTET* m_pFileHeader; + CBT_UINT32 m_uFileHeaderSize; + + bool m_bHashAllocated; + CBT_OCTET* m_pHashMaterial; + CBT_UINT32 m_uHashMaterialSize; + + bool m_bKeyAllocated; + CBT_OCTET* m_pKeyMaterial; + CBT_UINT32 m_uKeyMaterialSize; + + bool m_bEncryptedKeyAllocated; + CBT_OCTET* m_pEncryptedKey; + CBT_OCTET m_EncryptedKeyBuffer[ENCRYPTED_KEY_SIZE]; + CBT_UINT32 m_uEncryptedKeySize; + + bool m_bFileContentAllocated; + CBT_OCTET* m_pFileContent; + CBT_UINT32 m_uFileContentSize; + + CBT_OCTET* m_pOutputContent; + CBT_UINT32 m_pOutputContentSize; +} secure_file_content; + +/** + * @brief Secure file implementation + * + */ +typedef struct { + CBT_OCTET* rsa_n_data; + CBT_UINT32 rsa_n_len; + CBT_OCTET* rsa_e_data; + CBT_UINT32 rsa_e_len; + CBT_OCTET* rsa_d_data; + CBT_UINT32 rsa_d_len; +} ss_rsa_key; + +/** + * @brief Secure file implementation calss + * + * Implementation class of Interface ss_secure_file, provide all secure storage operations. + * @author ryan + * @date 2013.07 + * @version 1.0 + */ +class secure_file { +public: + + secure_file() : + m_cred(), m_options(0), m_file_content(), m_rsa_key(), + m_use_crypted_key(false), m_cache(NULL), m_write_data(NULL), + m_write_data_size(0), m_is_partial_write(false), m_read_data(NULL), + m_read_data_size(0), m_file_path_ready(false) { + } + ; + ~secure_file(); + + /** + * @brief Ininitialize + * + * Initialize. + * @param[in] buffer Point to data buffer. + * @param[in] buf_size Size of data in bytes. + * @param[in] offset Start address for partial writing. + * @retval 0 if success. + * @retval -1 if fail. + */ + int initialize(const ss_credential_s * cred, const char* data_name, + unsigned int options); + + /** + * @brief Write data into secure storage + * + * Write data into secure storage + * @param[in] buffer Point to data buffer. + * @param[in] buf_size Size of data in bytes. + * @param[in] offset Start address for partial writing. + * @retval 0 if success. + * @retval -1 if fail. + */ + int write(unsigned char* buffer, unsigned int buf_size, unsigned int offset); + + /** + * @brief Read data from secure storage. + * + * Read data from secure storage into provided buffer. + * @param[out] ret_buf Point to data buffer read from secure storage. + * @param[in] read_size Up to "read_size" bytes will be read. + * @param[in] offset Start address for partial reading. + * @return If success, real size in bytes of read data will be retured, if fails, -1 will be returned. + */ + int read(unsigned char** ret_buf, unsigned int* read_size, + unsigned int offset); + + /** + * @brief Write data into secure storage. + * + * Write data from provided buffer into secure storage, + * and encrypt data encryption key with provided RSA public key and attach it to secure storage file. + * @param[in] buffer Point to data buffer. + * @param[in] buf_size Size of data in bytes. + * @param[in] offset Start address for partial writing. + * @param[in] rsa_n_data RSA public exponent. + * @param[in] rsa_n_len RSA public exponent size in bytes. + * @param[in] rsa_e_data RSA public key. + * @param[in] rsa_e_len RSA public key size in bytes. + * @param[in] async Indicate writing data in synchronous/ asynchronous mode,if set to ture, in sysnchronous mode. + * @retval 0 if success. + * @retval -1 if fail. + */ + int write_ex(unsigned char* buffer, unsigned int buf_size, + unsigned int offset, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_e_data, + unsigned long rsa_e_len); + + /** + * @brief Read data from secure storage. + * + * Read data from secure storage into provided buffer, content key will be recovered by provided RSA private key. + * @param[out] ret_buf Point to data buffer read from secure storage. + * @param[in] read_size Up to "read_size" bytes will be read. + * @param[in] offset Start address for partial reading. + * @param[in] rsa_n_data RSA public exponent. + * @param[in] rsa_n_len RSA public exponent size in bytes. + * @param[in] rsa_d_data RSA private key. + * @param[in] rsa_d_len RSA private key size in bytes. + * @return If success, real size in bytes of read data will be retured, if fails, -1 will be returned. + */ + int read_ex(unsigned char** ret_buf, unsigned int* read_size, + unsigned int offset, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_d_data, + unsigned long rsa_d_len); + + /** + * @brief Validate secure storage file structure. + * + * Validate the secure storage file structure. + * @retval 0 if success. + * @retval -1 if fail. + */ + int validate(); + + /** + * @brief Delete fiel from secure storage. + * + * Delete fiel from secure storage. + * @retval 0 if success. + * @retval -1 if fail. + */ + int remove(); + + /** + * @brief Remove all data from secure storage. + * + * Remove all data belongs to the credential from secure storage permanently, this should be used with caution. + * @retval 0 if success. + * @retval -1 if fail. + */ + int clear_storage(); + +private: + + int finalize(); + + uint32_t transform_name_to_id(const char* data_name); + + uint64_t transform_id_to_name(uint64_t uDataFileID); + + int derive_file_path(); + + int gen_key_material(); + + void compute_file_hash(CBT_OCTET* pHash); + + int prepare_data(unsigned char** ret_buf, unsigned int * ret_size, + unsigned char* buffer, unsigned int buf_size, unsigned int offset); + + int prepare_file_content(unsigned char* buffer, unsigned int buf_size); + + int parse_file_content(unsigned char* buffer, unsigned int buf_size); + + int serialize_data(unsigned char** buffer, unsigned int& ret_size); + + int write_temp_store(unsigned char* data, unsigned int size); + + int read_temp_store(unsigned char** buffer, unsigned int& ret_size); + + int write_persistent_store(unsigned char* data, unsigned int size); + + int read_persistent_store(unsigned char** buffer, unsigned int& ret_size); + + int remove_persistent_store(bool is_dir); + + int check_file_content(); + + int decrypt_data(); + +#ifdef _SECOS_SIM_ + void get_data_name(char* data_name, bool is_dir); +#endif + +private: + + // credential + ss_credential_s m_cred; + + // data name + char m_data_name[SS_MAX_DATA_NAME_LEN]; + + // options + unsigned int m_options; + + // full path + char m_full_path[SS_FULL_DATA_NAME_LEN]; + + // file content + secure_file_content m_file_content; + + // rsa key + ss_rsa_key m_rsa_key; + + bool m_use_crypted_key; + + // cache manager + ss_temp_store* m_cache; + + // ready_data for support partial write + unsigned char* m_write_data; + + unsigned int m_write_data_size; + + bool m_is_partial_write; + + unsigned char* m_read_data; + + unsigned int m_read_data_size; + + bool m_file_path_ready; + +}; + +#endif + diff --git a/ssflib/dep/swdss/include/slog.h b/ssflib/dep/swdss/include/slog.h new file mode 100755 index 0000000..b9dc449 --- /dev/null +++ b/ssflib/dep/swdss/include/slog.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _SWD_LOG_H_ +#define _SWD_LOG_H_ + +#define LOG_TAG "SWDSS_LIB" + +#include +#define THE_PRINTF(fmt, ARG...) printf(fmt"\n", ##ARG) +#define SLOGV(FMT, ARG ...) THE_PRINTF("[VBOSE][%s]"FMT, LOG_TAG, ##ARG) +#define SLOGD(FMT, ARG ...) THE_PRINTF("[DEBUG][%s]"FMT, LOG_TAG, ##ARG) +#define SLOGI(FMT, ARG ...) THE_PRINTF("[INFO] [%s]"FMT, LOG_TAG, ##ARG) +#define SLOGW(FMT, ARG ...) THE_PRINTF("[WARN] [%s]"FMT, LOG_TAG, ##ARG) +#define SLOGE(FMT, ARG ...) THE_PRINTF("[ERROR][%s]"FMT, LOG_TAG, ##ARG) +#define SLOGF(FMT, ARG ...) THE_PRINTF("[FATAL][%s]"FMT, LOG_TAG, ##ARG) + +#endif + diff --git a/ssflib/dep/swdss/include/ss_api.h b/ssflib/dep/swdss/include/ss_api.h new file mode 100755 index 0000000..ae69f68 --- /dev/null +++ b/ssflib/dep/swdss/include/ss_api.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _SWDSS_SS_API_H_ +#define _SWDSS_SS_API_H_ + +#include "ss_types.h" +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief init secure storage + * + * set credential members + * @param[in] strategy + * @return ref to ss_ret_val_e enum. + */ +int ss_init(int strategy); // check swdss_ta_service is ready + +/** + * @brief Set credential + * + * set credential members + * @param[in] cred Point to credential to be set. + * @param[in] uuid UUID of credential. + * @param[in] module_name Module name. + * @param[in] major_ver major version info. + * @param[in] minor_ver minor version info. + * @return ref to ss_ret_val_e enum. + */ +int ss_set_credential(ss_credential_s * cred, const char* uuid, + const char* module_name, unsigned long major_ver, unsigned long minor_ver); + +/** + * @brief Store data into Secure Storage. + * + * Store data from provided buffer into Secure Storage. + * @param[in] buffer Point to data buffer. The buffer should be freed by API caller. + * @param[in] data_size Size of data in bytes. + * @param[in] data_name Data name associated with data. + * @param[in] offset Start address for partial writing on an existent data, if offset == 0 and data does not exist,new data entry is created, + * the parameter takes effect only when option SS_OPT_PARTIAL_RW is set + * @param[in] cred Application credential. + * @param[in] options Data access options. + * @return ref to ss_ret_val_e enum. + */ +int ss_write(unsigned char* buffer, unsigned int data_size, unsigned int offset, + const char* data_name, const ss_credential_s * cred, unsigned int options); + +/** + * @brief Read data from secure storage. + * + * Read data from secure storage into provided buffer. + * @param[out] ret_buf Point to data buffer read from secure storage,buffer is allocated inside the API,use ss_free_buffer to free. + * @param[out] data_size size of data read from secure storage, when SS_OPT_PARTIAL_RW is set, this is firstly used as an in parameter to indicate required read size. + * @param[in] base_path Path that data will be stored, if set to NULL, default path will be used. + * @param[in] data_name Data name associated with data. + * @param[in] offset Start address for partial reading, only takes effect when SS_OPT_PARTIAL_RW is set. + * @param[in] cred Application credential. + * @param[in] options Data access options. + * @return ref to ss_ret_val_e enum. + */ +int ss_read(unsigned char** ret_buf, unsigned int* data_size, + unsigned int offset, const char* data_name, const ss_credential_s * cred, + unsigned int options); + +/** + * @brief Write data into secure storage. + * + * Write data from provided buffer into secure storage, + * and encrypt data encryption key with provided RSA public key and attach it to secure storage file. + * @param[in] buffer Point to data buffer.The buffer should be freed by API caller. + * @param[in] data_size Size of data in bytes. + * @param[in] data_name Data name associated with data. + * @param[in] offset Start address for partial writing on an existent data, if offset == 0 and data does not exist,new data entry is created, + * the parameter takes effect only when option SS_OPT_PARTIAL_RW is set + * @param[in] cred Application credential. + * @param[in] options Data access options. + * @param[in] rsa_n_data RSA public exponent. + * @param[in] rsa_n_len RSA public exponent size in bytes. + * @param[in] rsa_e_data RSA public key. + * @param[in] rsa_e_len RSA public key size in bytes. + * @return ref to ss_ret_val_e enum. + */ +int ss_write_ex(unsigned char* buffer, unsigned int data_size, + unsigned int offset, const char* data_name, const ss_credential_s* cred, + unsigned int options, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_e_data, + unsigned long rsa_e_len); + +/** + * @brief Read data from secure storage. + * + * Read data from secure storage into provided buffer, content key will be recovered by provided RSA private key. + * @param[out] ret_buf Point to data buffer read from secure storage,the buffer is allocated inside the API, calo ss_free_buffer to free. + * @param[out] data_size size of data read from secure storage, when SS_OPT_PARTIAL_RW is set, this is firstly used as an in parameter to indicate required read size. + * @param[in] base_path Path that data will be stored, if set to NULL, default path will be used. + * @param[in] data_name Data name associated with data. + * @param[in] offset Start address for partial reading, only takes effect when SS_OPT_PARTIAL_RW is set. + * @param[in] cred Application credential. + * @param[in] options Data access options. + * @param[in] rsa_n_data RSA public exponent. + * @param[in] rsa_n_len RSA public exponent size in bytes. + * @param[in] rsa_d_data RSA private key. + * @param[in] rsa_d_len RSA private key size in bytes. + * @return ref to ss_ret_val_e enum. + */ +int ss_read_ex(unsigned char** ret_buf, unsigned int* data_size, + unsigned int offset, const char* data_name, const ss_credential_s* cred, + unsigned int options, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_d_data, + unsigned long rsa_d_len); + +/** + * @brief Validate secure storage file structure. + * + * Validate the secure storage file structure. + * @param [in] data_name Data name associated with data. + * @param [in] cred Application credential. + * @param [in] options Data access options. + * @return ref to ss_ret_val_e enum. + */ +int ss_validate(const char* data_name, const ss_credential_s* cred, + unsigned int options); + +/** + * @brief Delete fiel from secure storage. + * + * Delete fiel from secure storage. + * @param[in] base_path Path that data will be stored, if set to NULL, default path will be used. + * @param[in] data_name Data name associated with data. + * @param[in] cred Application credential. + * @param[in] options Data access options. + * @return ref to ss_ret_val_e enum. + */ +int ss_delete(const char* data_name, const ss_credential_s* cred, + unsigned int options); + +/** + * @brief Remove all data from secure storage. + * + * Remove all data belongs to the credential from secure storage permanently, this should be used with caution. + * @param[in] base_path Path that data will be stored, if set to NULL, default path will be used. + * @param[in] cred Application credential. + * @param[in] options Data access options. + * @return ref to ss_ret_val_e enum. + */ +int ss_clear_storage(const ss_credential_s* cred, unsigned int options); + +/** + * @brief free buffer allocated by secure storage API. + * + * Free buffer which is allocated by secure storage API ss_read/ss_read_ex + * @param buffer Point to buffer to be freed. + * @return ref to ss_ret_val_e enum. + */ +int ss_free_buffer(unsigned char* buffer); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ssflib/dep/swdss/include/ss_crypto.h b/ssflib/dep/swdss/include/ss_crypto.h new file mode 100755 index 0000000..ff7715d --- /dev/null +++ b/ssflib/dep/swdss/include/ss_crypto.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file crypto.h + * @brief Crypto class header. + * @author ryan woo + * @version 1.0 + * @date 2013.7.23 + * + */ + +#ifndef _SS_TA_CRYPTO_H_ +#define _SS_TA_CRYPTO_H_ + +#include "CC_API.h" +#include "ss_types.h" + +// rand gen + +static const CBT_UINT32 lcg_A = 1103515245; /* Initial value of A */ +static const CBT_UINT32 lcg_C = 12345; /* Initial value of C */ + +void seed_rand(CBT_UINT32 seed); +CBT_UINT32 gen_rand(void); + +void gen_rand_vec(CBT_OCTET* vec, CBT_UINT32 size); + +/** + * @class CCryptoEngine + * @brief Crypto Basic class + * + * Copyright 2011 by Samsung Electronics, Inc., + * + * This software is the confidential and proprietary information + * of Samsung Electronics, Inc. ("Confidential Information"). You + * shall not disclose such Confidential Information and shall use + * it only in accordance with the terms of the license agreement + * you entered into with Samsung. + */ +class CCryptoEngine { +public: + const static int Hash_Size = 20; /** +#include "ss_types.h" + +void byte_to_hex(uint8_t* dest, const uint8_t* src, unsigned long src_len); +void hex_to_byte(uint8_t* dest, const uint8_t* src, unsigned long src_len); + +int is_hex(const char* text, char sep); + +#endif + diff --git a/ssflib/dep/swdss/include/ss_temp_store.h b/ssflib/dep/swdss/include/ss_temp_store.h new file mode 100755 index 0000000..a157a1e --- /dev/null +++ b/ssflib/dep/swdss/include/ss_temp_store.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _SWD_SS_TMP_STORE_H_ +#define _SWD_SS_TMP_STORE_H_ + +#include +#include "ss_types.h" +#include +#include "ss_types.h" +#include +#include "OsaLinuxUser.h" + +class auto_lock { +public: + + auto_lock() { + pthread_mutex_lock(&m_mutex); + } + + ~auto_lock() { + pthread_mutex_unlock(&m_mutex); + } + +private: + + static pthread_mutex_t m_mutex; +}; + +typedef struct temp_ss_node { + char node_id[SS_NODE_ID_LEN]; + unsigned char* data; + unsigned int data_size; + temp_ss_node* prev; + temp_ss_node* next; +} temp_ss_node; + +class ss_temp_store { +public: + static ss_temp_store* get_instance(); + + int read(char* data_name, unsigned char** data, unsigned int& data_size); + + int write(char* data_name, unsigned char* data, unsigned int data_size); + + int remove(char* data_name); + + int batch_remove(char* dir); + +private: + + temp_ss_node* find_node(char* data_name); + temp_ss_node* del_node(temp_ss_node* node); + + ss_temp_store() { + m_head.prev = NULL; + m_head.next = NULL; + m_head.data = NULL; + m_head.data_size = 0; + } + +private: + + static ss_temp_store* m_instance; + temp_ss_node m_head; +}; + +#endif diff --git a/ssflib/dep/swdss/include/ss_types.h b/ssflib/dep/swdss/include/ss_types.h new file mode 100755 index 0000000..02f1791 --- /dev/null +++ b/ssflib/dep/swdss/include/ss_types.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 _SWD_SS_COMMON_H_ +#define _SWD_SS_COMMON_H_ + +#define SS_MAX_UUID_LEN 64 +#define SS_MAX_MODULE_NAME_LEN 32 +#define SS_MAX_DATA_NAME_LEN 128 +#define SS_MAX_DATA_SIZE 1024*100 + +#define SS_WSM_MEMPOOL_SIZE 3*1024*1024 +#define SS_CACHE_CAPACITY 2*1024*1024 +#define SWD_SS_SVC_START_CMD 0 + +#define SS_FULL_DATA_NAME_LEN 256 +#define SS_NODE_ID_LEN SS_FULL_DATA_NAME_LEN + +typedef enum { + PRE_LOAD = 1, DELAY_WRITE = 2 +} ss_strategy_e; + +/** + * @brief secure storage return value. + * + */ +typedef enum { + SS_RET_SUCCESS = 0, /**< Return value in the case of success */ + SS_RET_FAIL = 1, /**< Return value in the case of failure if no special detailed failure info available*/ + SS_RET_INVALID_PARAM = 2, /**< Return value in the case if function input params are invalid */ + SS_RET_INVALID_CREDENTIAL = 3, /**< Return value in the case if invalid credentials passed */ + SS_RET_INVALID_DATA_NAME = 4, /**< Return value in the case if invalid data name passed */ + SS_RET_CANT_FIND_REQUESTED_DATA = 5, /**< Return value in the case if requested data doesn't exist */ + SS_RET_DUPLICATE_CREDENTIAL = 6, /**< Return value in the case if credentials duplication (used in internal functions only) */ + SS_RET_OFFSET_ERR = 7, /**< Return value in the case if offset value is error*/ + SS_RET_DATA_SIZE_IS_TOO_BIG = 8, /**< Return value in the case if provided data size is too big */ + SS_RET_INVALID_OPTIONS = 9, /**< Return value in the case if invalid attributes passed */ + SS_RET_MALLOC_FAILED = 10, /**< Return value in the case if memory allocation error occur */ + SS_RET_INVALID_FILE = 11, /**< Return value in the case if file is corrupted or has invalid structure */ + SS_RET_INTERNAL_ERROR = 12, /**< Return value in the case if any unexpected internal error occur */ + SS_RET_COMM_ERR = 13, /**< Return value in the case if internal communication error */ + SS_RET_INVALID_RSA_PARAM = 14, /**< Return value in the case if RSA key params are invalid */ +} ss_ret_val_e; + +/** + * @brief Secure storage options. + * + */ +typedef enum { + SS_OPT_DEFAULT = 0, /** +#include +#include +#include +#include + +#include +#include +#include + +#include + +pthread_mutex_t delLock = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t createLock = PTHREAD_MUTEX_INITIALIZER; + +using namespace std; + +int file_op::write_file(const char* filename, unsigned char* buffer, + unsigned int size) { + SLOGI("entering file_op::write_file"); + if (NULL == buffer) { + return SS_RET_INVALID_PARAM; + } + + FILE* file; + + if (is_valid_filename(filename)) { + SLOGD("[%s][%d] NOT valid file : [ %s ]", __FUNCTION__, __LINE__, filename); + return SS_RET_INVALID_PARAM; + } + + // create folder if not exist. + char base_path[255] = {0}; + get_base_path(filename, base_path); + SLOGI("base_path %s.", base_path); + if (!is_folder_exists(base_path)) { + if (0 != create_folder(base_path)) { + return SS_RET_FAIL; + } + } + + /* open file */ + file = fopen(filename, "wb"); + if (NULL == file) { + SLOGD("[%s][%d] fopen(..) == NULL , Can't open [ %s ] file. ", __FUNCTION__, + __LINE__, filename); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + if (size != fwrite(buffer, 1, size, file)) { + SLOGD("[%s][%d]!!!DIFFERENT!!!", __FUNCTION__, __LINE__); + fclose(file); + return SS_RET_FAIL; + } + + fflush(file); + + //sync(fileno(file)); // sync blocked + + fclose(file); + + return SS_RET_SUCCESS; +} + +int file_op::read_file(const char* filename, unsigned char** buffer, + unsigned int& size) { + SLOGI("Entering file_op::read_file..."); + FILE* file; + long fLen; + *buffer = NULL; + size = 0; + + if (is_valid_filename(filename)) { + SLOGD("[%s][%d] NOT valid file : [ %s ]", __FUNCTION__, __LINE__, filename); + return SS_RET_INVALID_PARAM; + } + + /* open file */ + file = fopen(filename, "rb"); + if (NULL == file) { + SLOGD("[%s][%d] fopen(..) == NULL , Can't open [ %s ] file. ", __FUNCTION__, + __LINE__, filename); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + /* computing file size */ + if(fseek(file, 0, SEEK_END) != 0){ + fclose(file); + return SS_RET_FAIL; + } + fLen = ftell(file); + if (fLen > 0) { + size = fLen; + } + if( fseek(file, 0, SEEK_SET) != 0){ + fclose(file); + return SS_RET_FAIL; + } + + /* allocating data buffer with enough size */ + *buffer = new uint8_t[size]; + if (!(*buffer)) { + SLOGD("[%s][%d] Can't malloc pBuffer to 'fread'. ", __FUNCTION__, __LINE__); + fclose(file); + return SS_RET_MALLOC_FAILED; + } + + /* reading data from file */ + if (size != fread(*buffer, size, 1, file)) { + SLOGD("[%s][%d] Read size is not equal to required size %d.", __FUNCTION__, + __LINE__, size); + } + + /* closing file */ + fclose(file); + + SLOGI("[%s][%d] File read successfully", __FUNCTION__, __LINE__); + return SS_RET_SUCCESS; +} + +int file_op::remove_file(const char* filename) { + SLOGI("[%s][%d] Entering file_op::remove_file", __FUNCTION__, __LINE__); + pthread_mutex_lock(&delLock); + bool ret = is_file_exists(filename); + if (ret) { + ret = remove(filename); + if (0 != ret) { + SLOGD("[%s][%d] remove , nRet : %d , file [ %s ] not removed", + __FUNCTION__, __LINE__, ret, filename); + pthread_mutex_unlock(&delLock); + return SS_RET_FAIL; + } + } else { + SLOGD("[%s][%d] access not ok , nRet : %d , There's NO file [ %s ] ", + __FUNCTION__, __LINE__, ret, filename); + pthread_mutex_unlock(&delLock); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + pthread_mutex_unlock(&delLock); + SLOGI("[%s][%d] Succeed to remove file...", __FUNCTION__, __LINE__); + + return SS_RET_SUCCESS; +} + +int file_op::is_valid_filename(const char* filename) { + // path shall not contain any "strange" characters + const char* validated_path = strpbrk(filename, "&;`'\"|*?~<>^()[]{}$\n \r"); + if (validated_path != NULL) { + SLOGD( + "[%s][%d] There are some forbidden charactors in path.(&;`'\"|*?~<>^()[]{}$\n \r) ", + __FUNCTION__, __LINE__); + return SS_RET_INVALID_PARAM; + } + + return SS_RET_SUCCESS; +} + +int file_op::create_folder(const char* folder) { + SLOGI("[%s][%d] START", __FUNCTION__, __LINE__); + + char base_p[256] = {0}; + get_base_path(folder, base_p); + if (!is_folder_exists(base_p)) { + if (0 != create_folder(base_p)) { + SLOGE("Failed to create folder %s.", base_p); + return SS_RET_FAIL; + } + } + + uint32_t result = SS_RET_SUCCESS; + struct stat st; + memset(&st, 0, sizeof(st)); + pthread_mutex_lock(&createLock); + int res = stat(folder, &st); + + if (res == -1) { + res = mkdir(folder, S_IRWXU); + if (0 != res) { + result = SS_RET_FAIL; + SLOGE("Failed to create folder %s.", folder); + } + //sync(); + } else if (!(S_ISDIR(st.st_mode))) { + result = SS_RET_FAIL; + } + pthread_mutex_unlock(&createLock); + + SLOGI("[%s][%d] END", __FUNCTION__, __LINE__); + + return result; +} + +int file_op::remove_folder(const char* folder) { + SLOGI("[%s][%d] START", __FUNCTION__, __LINE__); + + rmdir(folder); + + SLOGI("[%s][%d] END", __FUNCTION__, __LINE__); + return SS_RET_SUCCESS; +} + +bool file_op::is_folder_exists(const char* folder) { + return is_file_exists(folder); +} + +bool file_op::is_file_exists(const char* file) { + struct stat st; + memset(&st, 0, sizeof(st)); + int res = stat(file, &st); + return (res != -1); +} + +void file_op::get_base_path(const char* filename, char* base_path) { + char tmp[256] = {0}; + memcpy(tmp, filename, strlen(filename)); + + for (int i = strlen(filename) - 1; i >= 0; --i) { + tmp[i] = 0; + + if ('/' == filename[i]) { + memcpy(base_path, tmp, strlen(tmp)); + break; + } + } +} + diff --git a/ssflib/dep/swdss/source/secure_file.cpp b/ssflib/dep/swdss/source/secure_file.cpp new file mode 100755 index 0000000..51059b3 --- /dev/null +++ b/ssflib/dep/swdss/source/secure_file.cpp @@ -0,0 +1,1743 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "ss_crypto.h" +#include "secure_file.h" +#include +#include "ss_misc.h" +#include "OsaLinuxUser.h" + +#ifdef _SECOS_SIM_ +#include "file_op.h" +//#define SWD_SS_ROOT "/opt/usr/apps/tz_simulator/data/swdss/" +#define SWD_SS_ROOT "/tmp/tastore2/" + +#endif + +// this is RNG SEED for mask +static const CBT_UINT32 RNG_SEED = 0xa3e59cf2; +// this is RNG SEED for mask +static const CBT_UINT32 RNG_KEY_SEED = 0x3ae19f52; + +// Salts and IDs used i PBKDF2 +static const CBT_UINT32 SALT_SIZE = 20; +//static CBT_UINT32 gUSaltID1 = 0; +static const CBT_OCTET USALT1[SALT_SIZE] = {0xa2, 0x40, 0x51, 0x4f, 0x5d, 0x6c, + 0xc5, 0x4f, 0xb0, 0x3f, 0x53, 0x33, 0xe9, 0x8a, 0xc0, 0xae, 0, 0, 0, 1}; +//static CBT_UINT32 gUSaltID2 = 0; +static const CBT_OCTET USALT2[SALT_SIZE] = {0x0f, 0xb3, 0x9c, 0x0e, 0x65, 0x49, + 0x91, 0x68, 0xa8, 0xe4, 0xd3, 0xa4, 0xdd, 0xe6, 0x3a, 0x0d, 0, 0, 0, 1}; + +//static CBT_UINT32 gCSaltID1 = 0; +static const CBT_OCTET CSALT1[SALT_SIZE] = {0x51, 0xa2, 0x40, 0x5d, 0x6c, 0x4f, + 0xc5, 0xb0, 0x3f, 0x53, 0x4f, 0x33, 0xe9, 0xae, 0x8a, 0xc0, 0, 0, 0, 1}; +//static CBT_UINT32 gCSaltID2 = 0; +static const CBT_OCTET CSALT2[SALT_SIZE] = {0x91, 0xb3, 0x9c, 0xa4, 0x0e, 0x0f, + 0x49, 0x68, 0xa8, 0xe4, 0xd3, 0x0d, 0x65, 0xdd, 0xe6, 0x3a, 0, 0, 0, 1}; + +const unsigned char g_Prekey[] = {0xa1, 0x21, 0x51, 0x71, 0xf1, 0x01, 0xd1, + 0x31, 0x41, 0x01, 0x01, 0x91, 0x91, 0xb1, 0xe1, 0x11}; + +// PBKDF2 iterations count +static const CBT_UINT32 PHASE1_ITER = 200; +static const CBT_UINT32 PHASE2_ITER = 250; + +#ifndef _SECOS_SIM_ +/*! + * \brief Determine file structure index + * \param pFileHeader [in] pointer to file header + * \return Structure index + */ +static CBT_UINT32 FileStructureType(CBT_OCTET* pFileHeader) { + return (pFileHeader[6] ^ pFileHeader[7]) % 6; +} +#endif + +static int PBKDF2(const CBT_OCTET* pKeyMaterial, CBT_UINT32 uKeyMaterialSize, + const CBT_OCTET* pSalt, unsigned long c, CBT_OCTET* pKey, + CryptoAlgorithm alg) { + + CBT_OCTET pU[32] = {0}; + CBT_OCTET pT[32] = {0}; + cc_u32 uTSize = 0; + + memcpy(pU, pSalt, SALT_SIZE); + + // preparing crypto conteiner for HMAC-SHA1 + CryptoCoreContainer *crt = create_CryptoCoreContainer(alg); + + // main cycle + for (unsigned long i = 0; i < c; i++) { + crt->MAC_getMAC(crt, const_cast(pKeyMaterial), uKeyMaterialSize, + pU, CCryptoEngine::Hash_Size, pT, &uTSize); + memcpy(pU, pT, uTSize); + } + + destroy_CryptoCoreContainer(crt); + + memcpy(pKey, pT, CCryptoEngine::Key_Size); + + return 0; +} + +static int MDeriveCommonKey1(const CBT_OCTET* pKeyMaterial, + CBT_UINT32 uKeyMaterialSize, CBT_OCTET* pKey) { + // deriving key + PBKDF2(pKeyMaterial, uKeyMaterialSize, CSALT1, PHASE1_ITER, pKey, ID_HSHA1); + + return 0; +} + +static int MDeriveCommonKey2(const CBT_OCTET* pKeyMaterial, + CBT_UINT32 uKeyMaterialSize, CBT_OCTET* pKey) { + // deriving key + PBKDF2(pKeyMaterial, uKeyMaterialSize, CSALT2, PHASE2_ITER, pKey, ID_HSHA1); + + return 0; +} + +static int MDeriveUniqueKey1(const CBT_OCTET* pKeyMaterial, + CBT_UINT32 uKeyMaterialSize, CBT_OCTET* pKey) { + // deriving key + PBKDF2(pKeyMaterial, uKeyMaterialSize, USALT1, PHASE1_ITER, pKey, ID_HSHA1); + + return 0; +} + +static int MDeriveUniqueKey2(const CBT_OCTET* pKeyMaterial, + CBT_UINT32 uKeyMaterialSize, CBT_OCTET* pKey) { + unsigned long nSize = 0; + CBT_OCTET* pBuffer = (CBT_OCTET*)NULL; + CBT_OCTET key[16] = {0, }; + + if (uKeyMaterialSize > KEY_MAT_SIZE) { + SLOGE("uKeyMaterialSize %d is too big.\n", uKeyMaterialSize); + return SS_RET_INTERNAL_ERROR; + } + + pBuffer = new CBT_OCTET[uKeyMaterialSize + 16]; + if (!pBuffer) { + SLOGE("Alloc memory failed.\n"); + return SS_RET_MALLOC_FAILED; + } + + memset(pBuffer, 0, uKeyMaterialSize + 16); + +#if defined(_SECOS_SIM_) +#define UCI_HW_SECRET_KEY 0 +#define ID_UCI_ENC_ECB 0 +#endif + + int iRet = CCryptoEngine::HWEncrypt(pBuffer, &nSize, (CBT_OCTET*)pKeyMaterial, + uKeyMaterialSize, key, + UCI_HW_SECRET_KEY, + ID_UCI_ENC_ECB); + if (iRet) { + SLOGE("Failed to do HWEncrypt, ret_code %d.\n", iRet); + delete[] pBuffer; + return SS_RET_INTERNAL_ERROR; + } + + memset(pBuffer + CCryptoEngine::Key_Size, 0, 16); //hack + + // deriving key + PBKDF2(pBuffer, nSize, USALT2, PHASE2_ITER, pKey, ID_HSHA1); + + delete[] pBuffer; + + return 0; +} + +static int GenKey(const CBT_OCTET* pKeyMaterial, CBT_OCTET* pKey, + CBT_UINT32 options) { + int iRet = 0; + CBT_OCTET pBufKey[CCryptoEngine::Key_Size]; + + // performing first transformation + if (options & SS_OPT_COMMON) { + iRet = MDeriveCommonKey1(pKeyMaterial, KEY_MAT_SIZE, pBufKey); + } else { + iRet = MDeriveUniqueKey1(pKeyMaterial, KEY_MAT_SIZE, pBufKey); + } + + if (iRet) { + SLOGE("Failed to derive key 1st phase.\n"); + return SS_RET_INTERNAL_ERROR; + } + + // performing second transformation + if (options & SS_OPT_COMMON) { + iRet = MDeriveCommonKey2(pBufKey, CCryptoEngine::Key_Size, pKey); + } else { + iRet = MDeriveUniqueKey2(pBufKey, CCryptoEngine::Key_Size, pKey); + } + + if (iRet) { + SLOGE("Failed to derive key 2nd phase.\n"); + return SS_RET_INTERNAL_ERROR; + } + + return iRet; +} + +int Encrypt(uint8_t* dest, uint8_t* src, unsigned long data_len, + uint8_t* key_material, uint32_t options) { + int iRet = 0; + CBT_OCTET pKey[CCryptoEngine::Key_Size]; + + // generating random key data + CCryptoEngine::Random(key_material, KEY_MAT_SIZE); + + iRet = GenKey(key_material, pKey, options); + if (iRet) { + SLOGE("Failed to do MGenKey.\n"); + return 0; + } + + return CCryptoEngine::Encrypt(dest, src, data_len, pKey, 0); +} + +int EncryptEx(uint8_t* dest, uint8_t* src, unsigned long data_len, + uint8_t* key_material, uint8_t* enc_key, uint32_t options) { + CBT_OCTET pKey[CCryptoEngine::Key_Size]; + + int iRet = 0; + //int i; + int ret; + // generating random key data + CCryptoEngine::Random(key_material, KEY_MAT_SIZE); + + iRet = GenKey(key_material, pKey, options); + if (iRet) { + SLOGE("Failed to do MGenKey.\n"); + return 0; + } + + unsigned int cipherTextLen, t; + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_AES); + + if (crt == NULL) { + return 0; + } + crt->SE_init(crt, ID_ENC_ECB, ID_NO_PADDING, const_cast(g_Prekey), + CCryptoEngine::Key_Size, (cc_u8*)NULL); + crt->SE_process(crt, pKey, CCryptoEngine::Key_Size, enc_key, + static_cast(&cipherTextLen)); + crt->SE_final(crt, (cc_u8*)NULL, 0, (pKey + cipherTextLen), + static_cast(&t)); + cipherTextLen += t; + destroy_CryptoCoreContainer(crt); + + ret = CCryptoEngine::Encrypt(dest, src, data_len, pKey, 0); + + return ret; +} + +int Decrypt(uint8_t* dest, uint8_t* src, unsigned long data_len, + const uint8_t* key_material, uint32_t options) { + int iRet = 0; + CBT_OCTET pKey[CCryptoEngine::Key_Size]; + + if (key_material == 0) { + SLOGE("Key material is NULL.\n"); + return 0; + } + + iRet = GenKey(key_material, pKey, options); + if (iRet) { + SLOGE("Failed to do MGenKey.\n"); + return 0; + } + + return CCryptoEngine::Decrypt(dest, src, data_len, pKey, 0); +} + +int DecryptEx(uint8_t* dest, uint8_t* src, unsigned long data_len, + const uint8_t* enc_key/*, uint32_t keysize, uint8_t* rsa_n_data, uint32_t rsa_n_len, uint8_t* rsa_d_data, uint32_t rsa_d_len*/) { + int ret; + //int i; + //unsigned long uDecryptedKeySize; + uint8_t decryptedKeyBuffer[ENCRYPTED_KEY_SIZE]; + + unsigned int plainTextLen, t; + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_AES); + if (crt == NULL) { + return 0; + } + + crt->SE_init(crt, ID_DEC_ECB, ID_NO_PADDING, const_cast(g_Prekey), + 16, (cc_u8*)NULL); + crt->SE_process(crt, const_cast(enc_key), CCryptoEngine::Key_Size, + decryptedKeyBuffer, static_cast(&plainTextLen)); + crt->SE_final(crt, NULL, 0, (uint8_t*)(decryptedKeyBuffer + plainTextLen), + static_cast(&t)); + destroy_CryptoCoreContainer(crt); + plainTextLen += t; + + ret = CCryptoEngine::Decrypt(dest, src, data_len, decryptedKeyBuffer, 0); + + return ret; +} + +int is_valid_credential(const ss_credential_s& cred) { + // In its canonical form, a UUID consists of 32 hexadecimal digits, displayed in 5 groups separated by hyphens, + // in the form 8-4-4-4-12 for a total of 36 characters(32 digits and 4 '-'). For example: + // 550e8400-e29b-41d4-a716-446655440000 + // Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the version number as well + // as two reserved bits. All other bits are set using a random or pseudorandom data source. + // Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal digits x and hexadecimal + // digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479. + char tmp_uuid[SS_MAX_UUID_LEN + 1] = {0}; + char tmp_mn[SS_MAX_MODULE_NAME_LEN + 1] = {0}; + strncpy(tmp_uuid, cred.uuid, SS_MAX_UUID_LEN); + strncpy(tmp_mn, cred.module_name, SS_MAX_MODULE_NAME_LEN); + + // we have to check only UUID format + // checking size + if (strlen(tmp_uuid) != 36) { + return SS_RET_INVALID_CREDENTIAL; + } + // checking delimiters + if (tmp_uuid[8] != '-' || tmp_uuid[13] != '-' || tmp_uuid[18] != '-' + || tmp_uuid[23] != '-') { + return SS_RET_INVALID_CREDENTIAL; + } + + // checking specific values + //if (tmp_uuid[14] != '4' || (tmp_uuid[19] != '8' && tmp_uuid[19] != '9' && tmp_uuid[19] != 'a' && tmp_uuid[19] != 'b')) + //{ + // return SS_RET_INVALID_CREDENTIAL; + //} + // checking that string contains only hexidecimal values + if (-1 == is_hex(tmp_uuid, '-')) { + return SS_RET_INVALID_CREDENTIAL; + } + + // Module name shall not contain any spaces + for (uint32_t i = 0; i < strlen(tmp_mn); ++i) { + if (isspace(tmp_mn[i])) { + return SS_RET_INVALID_CREDENTIAL; + } + } + + return SS_RET_SUCCESS; +} + +static int is_valid_options(unsigned int options) { + if (((options & SS_OPT_COMMON) && (options & SS_OPT_UNIQUE)) + || ((options & SS_OPT_TEMPORARY) && (options & SS_OPT_PERMANENT))) { + return SS_RET_INVALID_OPTIONS; + } + + return SS_RET_SUCCESS; +} + +static int is_valid_data_name(const char* data_name) { + for (int i = 0; data_name[i] != 0; ++i) { + if ((!isalnum(data_name[i])) && ('-' != data_name[i]) + && ('_' != data_name[i]) && ('.' != data_name[i])) { + return SS_RET_INVALID_DATA_NAME; + } + } + + return SS_RET_SUCCESS; +} + +int cred_options_check(const ss_credential_s* cred, unsigned int options) { + if (SS_RET_SUCCESS != is_valid_credential(*cred)) { + SLOGE("[%s] invalid credential.\n", __FUNCTION__); + return SS_RET_INVALID_CREDENTIAL; + } + + if (SS_RET_SUCCESS != is_valid_options(options)) { + SLOGE("[%s] invalid options.\n", __FUNCTION__); + return SS_RET_INVALID_OPTIONS; + } + + return SS_RET_SUCCESS; +} + +int secure_file::initialize(const ss_credential_s * cred, const char* data_name, + unsigned int options) { + int iRet = cred_options_check(cred, options); + if (SS_RET_SUCCESS != iRet) { + return iRet; + } + + m_cred = *cred; + + m_data_name[0] = '\0'; + if (NULL != data_name) { + int data_name_len = strlen(data_name); + memcpy(m_data_name, data_name, data_name_len); + m_data_name[data_name_len] = '\0'; + } + + m_options = options; + + m_use_crypted_key = false; + + m_cache = ss_temp_store::get_instance(); + if (NULL == m_cache) { + SLOGF("[%s][%d](ERROR) Failed to alloc cache_manager. ", __FUNCTION__, + __LINE__); + return SS_RET_MALLOC_FAILED; + } + + return SS_RET_SUCCESS; +} + +uint32_t secure_file::transform_name_to_id(const char* data_name) { + uint32_t uuidFile = 0; + + for (unsigned int i = 0; i < strlen(data_name); i++) { + uuidFile = uuidFile * 33 + data_name[i]; + } + + return uuidFile; +} + +uint64_t secure_file::transform_id_to_name(uint64_t uDataFileID) { + uint64_t uDataFileName; + CBT_UINT32 uDataFileName1, uDataFileName2; + // the main idea of this function is to transfor initial file id into different number which + // hexidecimal representation will be the real file name. + // first part + seed_rand(uDataFileID & 0xffffffff); + uDataFileName1 = gen_rand(); + uDataFileName1 = (uDataFileName1 << 15) | (uDataFileName1 >> (32 - 15)); + seed_rand(RNG_SEED); + uDataFileName1 ^= gen_rand(); + // second part + seed_rand((uDataFileID >> 32) & 0xffffffff); + uDataFileName2 = gen_rand(); + uDataFileName2 = (uDataFileName2 << 10) | (uDataFileName2 >> (32 - 10)); + seed_rand(RNG_SEED); + uDataFileName2 ^= gen_rand(); + // hexidecimal representation of return value will be the real file name. + uDataFileName = uDataFileName1 | (((uint64_t)uDataFileName2) << 32); + + SLOGI("[%s][%d] uDataFileName : %llu", __FUNCTION__, __LINE__, uDataFileName); + return uDataFileName; +} + +int secure_file::finalize() { + if (m_file_content.m_bHeaderAllocated) { + delete[] m_file_content.m_pFileHeader; + m_file_content.m_pFileHeader = NULL; + m_file_content.m_bHeaderAllocated = false; + } + + if (m_file_content.m_bHashAllocated) { + delete[] m_file_content.m_pHashMaterial; + m_file_content.m_bHashAllocated = NULL; + m_file_content.m_bHashAllocated = false; + } + + if (m_file_content.m_bKeyAllocated) { + delete[] m_file_content.m_pKeyMaterial; + m_file_content.m_pKeyMaterial = NULL; + m_file_content.m_bKeyAllocated = false; + } + + if (m_file_content.m_bFileContentAllocated) { + delete[] m_file_content.m_pFileContent; + m_file_content.m_pFileContent = NULL; + m_file_content.m_bFileContentAllocated = false; + } + + if (m_file_content.m_pOutputContent) { + delete[] m_file_content.m_pOutputContent; + m_file_content.m_pOutputContent = NULL; + } + + if (m_is_partial_write) { + if (NULL != m_write_data) { + OsaFree(m_write_data); + } + } + + if (m_read_data) { + OsaFree(m_read_data); + } + + // finalize shm mgr + + return SS_RET_SUCCESS; +} + +int secure_file::derive_file_path() { +#ifdef _SECOS_SIM_ + if (true == m_file_path_ready) { + return SS_RET_SUCCESS; + } + + memcpy(m_full_path, m_cred.uuid, SS_MAX_UUID_LEN); + strcat(m_full_path, "/"); + strcat(m_full_path, m_data_name); + m_file_path_ready = true; + return SS_RET_SUCCESS; +#else + + //std::string sfolder; + char sUUID_and_Name[SS_MAX_UUID_LEN + SS_MAX_MODULE_NAME_LEN + 2] = {0}; + char sTemp[SS_MAX_UUID_LEN + SS_MAX_MODULE_NAME_LEN + + 2 * CCryptoEngine::Hash_Size + 2] = {0}; + + CBT_OCTET pHash[2 * CCryptoEngine::Hash_Size]; + CBT_OCTET pFolderName[2 * CCryptoEngine::Hash_Size]; + + // combining UUID and Name + char tmp_uuid[SS_MAX_UUID_LEN + 1] = {0}; + char tmp_mn[SS_MAX_MODULE_NAME_LEN + 1] = {0}; + strncpy(tmp_uuid, m_cred.uuid, SS_MAX_UUID_LEN); + strncpy(tmp_mn, m_cred.module_name, SS_MAX_MODULE_NAME_LEN); + + memcpy(sUUID_and_Name, tmp_uuid, strlen(tmp_uuid)); + memcpy(sUUID_and_Name + strlen(tmp_uuid), tmp_mn, strlen(tmp_mn)); + + // compute hash value of sUUID_and_Name + CCryptoEngine::Hash(pHash, + (CBT_OCTET*)sUUID_and_Name, + strlen(sUUID_and_Name)); + + // obtain first part of our string + byte_to_hex(pFolderName, pHash, CCryptoEngine::Hash_Size); + memcpy(sTemp, pFolderName, 2 * CCryptoEngine::Hash_Size); + //sTemp.assign((char*)pFolderName, 2*CCryptoEngine::Hash_Size); + + // concatenate with UUID and Name + //sTemp += sUUID_and_Name; + memcpy(sTemp + 2 * CCryptoEngine::Hash_Size, + sUUID_and_Name, + strlen(sUUID_and_Name)); + + // compute hash of obtained string + CCryptoEngine::Hash(pHash, (CBT_OCTET*)sTemp, strlen(sTemp)); + + // we will use first 4 bytes of hash value + // convert them into hex format + //byte_to_hex(pFolderName, pHash, 4); + + // set folder name + //sfolder.assign((char*)pFolderName, 8); + //sfolder += "/"; + + //m_full_path = sfolder; + memset(m_full_path, 0, SS_FULL_DATA_NAME_LEN); + memcpy(m_full_path, pHash, 4); + + unsigned char dir[9] = {0}; + byte_to_hex(dir, pHash, 4); + SLOGI("Dir is %s.", (char*)dir); + + //m_full_path[8] = '/'; + + if (0 != strlen(m_data_name)) { + // computing file name + uint64_t data_id = transform_id_to_name(transform_name_to_id(m_data_name)); + memcpy(&m_full_path[4], &data_id, sizeof(uint64_t)); + + unsigned char filename[17] = {0}; + byte_to_hex(filename, (unsigned char*)&m_full_path[4], 8); + SLOGI("filename is %s.", (char*)filename); + } + + m_file_path_ready = true; + + return SS_RET_SUCCESS; +#endif +} + +void secure_file::compute_file_hash(CBT_OCTET* pHash) { + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_SHA1); + crt->MD_init(crt); + crt->MD_update(crt, + static_cast((void*)const_cast(m_file_content + .m_pFileContent)), m_file_content.m_uFileContentSize); + crt->MD_update(crt, + static_cast((void*)const_cast(m_file_content + .m_pKeyMaterial)), m_file_content.m_uKeyMaterialSize); + crt->MD_final(crt, (uint8_t*)pHash); + destroy_CryptoCoreContainer(crt); +} + +int secure_file::prepare_file_content(unsigned char* buffer, + unsigned int buf_size) { +#ifdef _SECOS_SIM_ + return 0; +#else + + // first of all we have to encrypt file data + // allocating enough memory for encrypted content + m_file_content.m_pFileContent = new CBT_OCTET[buf_size + 32]; + + // allocating anough memory for key material + m_file_content.m_pKeyMaterial = new CBT_OCTET[KEY_MAT_SIZE]; + m_file_content.m_uKeyMaterialSize = KEY_MAT_SIZE; + if (!m_file_content.m_pKeyMaterial) { + SLOGD("[%s][%d](SS_RET_MALLOC_FAILED) CAN'T Malloc 'm_file_content.m_pKeyMaterial' to conatin pKey", + __FUNCTION__, + __LINE__); + return SS_RET_MALLOC_FAILED; + } + m_file_content.m_bKeyAllocated = true; + + if (!m_file_content.m_pFileContent) { + SLOGD("[%s][%d](SS_RET_MALLOC_FAILED) CAN'T Malloc 'm_file_content.m_pFileContent' used in Encypt(m_FileContent.m_pFileContent, ..)", + __FUNCTION__, + __LINE__); + return SS_RET_MALLOC_FAILED; + } + + m_file_content.m_bFileContentAllocated = true; + + if (m_use_crypted_key) { + int ret; + + long unsigned uEncryptedKeySize; + CBT_OCTET keybuf[CCryptoEngine::Key_Size]; + m_file_content.m_uFileContentSize = EncryptEx(m_file_content.m_pFileContent, + const_cast(buffer), + buf_size, + m_file_content.m_pKeyMaterial, + keybuf, + m_options); + + if (0 == m_file_content.m_uFileContentSize) { + SLOGD("[%s][%d](ERROR) TZ Can't ENcrypt data WITH EncryptedKey mode. // (0 == m_file_content.m_pOutputContentSize)", + __FUNCTION__, + __LINE__); + SLOGF("[%s][%d](ERROR)", __FUNCTION__, __LINE__); + return SS_RET_INTERNAL_ERROR; + } + + ret = CCryptoEngine::RSAEncrypt(m_file_content.m_EncryptedKeyBuffer + 4, + &uEncryptedKeySize, + keybuf, + CCryptoEngine::Key_Size, + m_rsa_key.rsa_n_data, + m_rsa_key.rsa_n_len, + m_rsa_key.rsa_e_data, + m_rsa_key.rsa_e_len); + + // the first 4 bytes of buffer containes encrypted data size + m_file_content.m_EncryptedKeyBuffer[0] = uEncryptedKeySize & 0xff; + m_file_content.m_EncryptedKeyBuffer[1] = (uEncryptedKeySize >> 8) & 0xff; + m_file_content.m_EncryptedKeyBuffer[2] = (uEncryptedKeySize >> 16) & 0xff; + m_file_content.m_EncryptedKeyBuffer[3] = (uEncryptedKeySize >> 24) & 0xff; + + if (CRYPTO_SUCCESS != ret) { + SLOGD("%s RSA Encryption failure %i\n", __FUNCTION__, ret); + return SS_RET_FAIL; + } else { + SLOGD("%s Content key size is = %ld\n", __FUNCTION__, uEncryptedKeySize); + } + + } else { + m_file_content.m_uFileContentSize = Encrypt(m_file_content.m_pFileContent, + const_cast(buffer), + buf_size, + m_file_content.m_pKeyMaterial, + m_options); + + if (0 == m_file_content.m_uFileContentSize) { + SLOGD("[%s][%d](ERROR) TZ Can't ENcrypt data WITHOUT EncryptedKey mode. // (0 == m_file_content.m_pOutputContentSize)", + __FUNCTION__, + __LINE__); + SLOGF("[%s][%d](ERROR)", __FUNCTION__, __LINE__); + return SS_RET_INTERNAL_ERROR; + } + } + + // time to compute hash + // allocating anough memory for hash + m_file_content.m_pHashMaterial = new CBT_OCTET[HASH_SIZE]; + m_file_content.m_uHashMaterialSize = HASH_SIZE; + + if (!m_file_content.m_pHashMaterial) { + return SS_RET_MALLOC_FAILED; + } + + m_file_content.m_bHashAllocated = true; + + // filling it with random data + CCryptoEngine::Random(m_file_content.m_pHashMaterial, HASH_SIZE); + + // computing hash + compute_file_hash(m_file_content.m_pHashMaterial); + + // time to make header + // allocating anough memory for header + m_file_content.m_pFileHeader = new CBT_OCTET[HEADER_SIZE]; + m_file_content.m_uFileHeaderSize = HEADER_SIZE; + if (!m_file_content.m_pFileHeader) { + SLOGD("[%s][%d](SS_RET_MALLOC_FAILED) CAN'T Malloc 'm_file_content.m_pFileHeader' to initialize Header information", + __FUNCTION__, + __LINE__); + return SS_RET_MALLOC_FAILED; + } + + m_file_content.m_bHeaderAllocated = true; + + // filling it with random data + CCryptoEngine::Random(m_file_content.m_pFileHeader, HEADER_SIZE); + + m_file_content.m_pFileHeader[0] = 0xa5; + m_file_content.m_pFileHeader[1] = 0x5a; + m_file_content.m_pFileHeader[2] = 2; + m_file_content.m_pFileHeader[3] = 0; + m_file_content.m_pFileHeader[4] = 1; + + if (m_use_crypted_key) { + m_file_content.m_pFileHeader[5] = 1; //encrypted key attached to file + } else { + m_file_content.m_pFileHeader[5] = 0; + } + + SLOGI("[%s] m_file_content.m_pFileHeader[5] = %i", + __FUNCTION__, + m_file_content.m_pFileHeader[5]); + + return SS_RET_SUCCESS; +#endif +} + +int secure_file::parse_file_content(unsigned char* buffer, + unsigned int buf_size) { +#ifdef _SECOS_SIM_ + return 0; +#else + + // header shall be at least 16 bytes. + if (NULL == buffer) { + SLOGD("[%s][%d](SS_RET_INVALID_FILE)", __FUNCTION__, __LINE__); + return SS_RET_INVALID_FILE; + } + // the first 2 bytes shall have fixed values + if (buffer[0] != 0xa5 || buffer[1] != 0x5a) { + SLOGD("[%s][%d](SS_RET_INVALID_FILE) *pBuffer : %c // %x", + __FUNCTION__, + __LINE__, + *buffer, + *buffer); + SLOGD("[%s][%d](SS_RET_INVALID_FILE) *(pBuffer+1) : %c // %x", + __FUNCTION__, + __LINE__, + *(buffer + 1), + *(buffer + 1)); + return SS_RET_INVALID_FILE; + } + + // the next 4 bytes containes SS version and file structure version + if ((buffer[2] != 2) || (buffer[3] != 0)) { + SLOGD("[%s][%d](SS_RET_INVALID_FILE) *(pBuffer+2) : %c // %x", + __FUNCTION__, + __LINE__, + *(buffer + 2), + *(buffer + 2)); + SLOGD("[%s][%d](SS_RET_INVALID_FILE) *(pBuffer+3) : %c // %x", + __FUNCTION__, + __LINE__, + *(buffer + 3), + *(buffer + 3)); + return SS_RET_INVALID_FILE; + } + + if ((buffer[4] != 1) || ((buffer[5] != 0) && (buffer[5] != 1))) { + SLOGD("[%s][%d](SS_RET_INVALID_FILE) *(pBuffer+4) : %c // %x", + __FUNCTION__, + __LINE__, + *(buffer + 4), + *(buffer + 4)); + SLOGD("[%s][%d](SS_RET_INVALID_FILE) *(pBuffer+5) : %c // %x", + __FUNCTION__, + __LINE__, + *(buffer + 5), + *(buffer + 5)); + return SS_RET_INVALID_FILE; + } + + // temporary pointer to file content + CBT_OCTET* ptr = const_cast(buffer); + + // header, key material and hash sizes are fixed + m_file_content.m_uFileHeaderSize = HEADER_SIZE; + m_file_content.m_uHashMaterialSize = HASH_SIZE; + m_file_content.m_uKeyMaterialSize = KEY_MAT_SIZE; + + if (buffer[5] == 0) { + SLOGI("[%s][%d] File dosn't containe encrypted key material!", + __FUNCTION__, + __LINE__); + m_file_content.m_uEncryptedKeySize = 0; + m_file_content.m_uFileContentSize = buf_size + - (HEADER_SIZE + HASH_SIZE + KEY_MAT_SIZE); + } else if (buffer[5] == 1) { + SLOGI("[%s][%d] File containes encrypted key material!", + __FUNCTION__, + __LINE__); + m_file_content.m_uEncryptedKeySize = ENCRYPTED_KEY_SIZE; + m_file_content.m_uFileContentSize = buf_size + - (HEADER_SIZE + HASH_SIZE + KEY_MAT_SIZE + ENCRYPTED_KEY_SIZE); + } + + SLOGI("[%s][%d] m_file_content.m_uFileContentSize = %i!", + __FUNCTION__, + __LINE__, + m_file_content.m_uFileContentSize); + SLOGI("[%s][%d] m_file_content.m_uEncryptedKeySize = %i!", + __FUNCTION__, + __LINE__, + m_file_content.m_uEncryptedKeySize); + + switch (FileStructureType(ptr)) { + case 0: { + // [header][hash][data][key] + m_file_content.m_pFileHeader = ptr; + ptr += HEADER_SIZE; + m_file_content.m_pHashMaterial = ptr; + ptr += HASH_SIZE; + m_file_content.m_pFileContent = ptr; + ptr += m_file_content.m_uFileContentSize; + m_file_content.m_pKeyMaterial = ptr; + ptr += KEY_MAT_SIZE; + break; + } + case 1: { + // [header][hash][key][data] + m_file_content.m_pFileHeader = ptr; + ptr += HEADER_SIZE; + m_file_content.m_pHashMaterial = ptr; + ptr += HASH_SIZE; + m_file_content.m_pKeyMaterial = ptr; + ptr += KEY_MAT_SIZE; + m_file_content.m_pFileContent = ptr; + ptr += m_file_content.m_uFileContentSize; + break; + } + case 2: { + // [header][data][key][hash] + m_file_content.m_pFileHeader = ptr; + ptr += HEADER_SIZE; + m_file_content.m_pFileContent = ptr; + ptr += m_file_content.m_uFileContentSize; + m_file_content.m_pKeyMaterial = ptr; + ptr += KEY_MAT_SIZE; + m_file_content.m_pHashMaterial = ptr; + ptr += HASH_SIZE; + break; + } + case 3: { + // [header][key][data][hash] + m_file_content.m_pFileHeader = ptr; + ptr += HEADER_SIZE; + m_file_content.m_pKeyMaterial = ptr; + ptr += KEY_MAT_SIZE; + m_file_content.m_pFileContent = ptr; + ptr += m_file_content.m_uFileContentSize; + m_file_content.m_pHashMaterial = ptr; + ptr += HASH_SIZE; + break; + } + case 4: { + // [header][key][hash][data] + m_file_content.m_pFileHeader = ptr; + ptr += HEADER_SIZE; + m_file_content.m_pKeyMaterial = ptr; + ptr += KEY_MAT_SIZE; + m_file_content.m_pHashMaterial = ptr; + ptr += HASH_SIZE; + m_file_content.m_pFileContent = ptr; + ptr += m_file_content.m_uFileContentSize; + break; + } + case 5: { + // [header][data][hash][key] + m_file_content.m_pFileHeader = ptr; + ptr += HEADER_SIZE; + m_file_content.m_pFileContent = ptr; + ptr += m_file_content.m_uFileContentSize; + m_file_content.m_pHashMaterial = ptr; + ptr += HASH_SIZE; + m_file_content.m_pKeyMaterial = ptr; + ptr += KEY_MAT_SIZE; + break; + } + default: { + SLOGD("[%s][%d](SS_RET_FAIL) OUT OF THE FileStructureType : %d", + __FUNCTION__, + __LINE__, + FileStructureType(m_file_content.m_pFileHeader)); + return SS_RET_INVALID_FILE; + } + break; + } + + // alloc meory for output content + m_file_content.m_pOutputContent = + new CBT_OCTET[m_file_content.m_uFileContentSize]; + if (!m_file_content.m_pOutputContent) { + SLOGD("[%s][%d](SS_RET_MALLOC_FAILED) CAN'T Malloc 'm_FileContent.m_pOutputContent' to attach it to SDC. ", + __FUNCTION__, + __LINE__); + return SS_RET_MALLOC_FAILED; + } + + // do we have encrypted key material attached + if (m_use_crypted_key) { + SLOGI("[%s][%d] Using attached content key", __FUNCTION__, __LINE__); + if (m_file_content.m_pFileHeader[5] != 1) { + SLOGD("[%s][%d](SS_RET_FAIL) m_file_content.m_pFileHeader[5] != 1", + __FUNCTION__, + __LINE__); + return SS_RET_FAIL; + } + + m_file_content.m_pEncryptedKey = const_cast(buffer + buf_size + - ENCRYPTED_KEY_SIZE); + // revocer encrypted data size + m_file_content.m_uEncryptedKeySize = + (CBT_UINT32)m_file_content.m_pEncryptedKey[0] + | (CBT_UINT32)m_file_content.m_pEncryptedKey[1] << 8 + | (CBT_UINT32)m_file_content.m_pEncryptedKey[2] << 16 + | (CBT_UINT32)m_file_content.m_pEncryptedKey[3] << 24; + // it shall not be bigger then expected size + if (m_file_content.m_uEncryptedKeySize > ENCRYPTED_KEY_SIZE) { + SLOGF("[%s][%d] (SS_RET_INVALID_FILE) content key size is = %d", + __FUNCTION__, + __LINE__, + m_file_content.m_uEncryptedKeySize); + return SS_RET_INVALID_FILE; + } + + SLOGI("[%s][%d] Content key size is = %d", + __FUNCTION__, + __LINE__, + m_file_content.m_uEncryptedKeySize); + + SLOGI("[%s][%d] Decrypting content key", __FUNCTION__, __LINE__); + } + + return SS_RET_SUCCESS; +#endif +} + +int secure_file::serialize_data(unsigned char** buffer, + unsigned int& ret_size) { +#ifdef _SECOS_SIM_ + *buffer = (unsigned char*)OsaMalloc(m_write_data_size); + if (NULL == buffer) { + //SLOGE("fail to alloc memory for data."); + return SS_RET_MALLOC_FAILED; + } + + memcpy(*buffer, m_write_data, m_write_data_size); + ret_size = m_write_data_size; + return SS_RET_SUCCESS; +#else + + unsigned char* data = NULL; + *buffer = NULL; + ret_size = 0; + + int buf_size = m_file_content.m_uFileHeaderSize; + buf_size += m_file_content.m_uKeyMaterialSize; + buf_size += m_file_content.m_uFileContentSize; + buf_size += m_file_content.m_uHashMaterialSize; + + if (m_file_content.m_pFileHeader[5] == 1) { + buf_size += ENCRYPTED_KEY_SIZE; + } + + data = (unsigned char*)OsaMalloc(buf_size + 1); + if (NULL == data) { + SLOGE("fail to alloc memory for data."); + return SS_RET_MALLOC_FAILED; + } + + unsigned char* ptr = data; + switch (FileStructureType(m_file_content.m_pFileHeader)) { + case 0: { + // [header][hash][data][key] + memcpy(ptr, m_file_content.m_pFileHeader, HEADER_SIZE); + ptr += HEADER_SIZE; + memcpy(ptr, m_file_content.m_pHashMaterial, HASH_SIZE); + ptr += HASH_SIZE; + memcpy(ptr, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize); + ptr += m_file_content.m_uFileContentSize; + memcpy(ptr, m_file_content.m_pKeyMaterial, KEY_MAT_SIZE); + ptr += KEY_MAT_SIZE; + break; + } + case 1: { + // [header][hash][key][data] + memcpy(ptr, m_file_content.m_pFileHeader, HEADER_SIZE); + ptr += HEADER_SIZE; + memcpy(ptr, m_file_content.m_pHashMaterial, HASH_SIZE); + ptr += HASH_SIZE; + memcpy(ptr, m_file_content.m_pKeyMaterial, KEY_MAT_SIZE); + ptr += KEY_MAT_SIZE; + memcpy(ptr, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize); + ptr += m_file_content.m_uFileContentSize; + break; + } + case 2: { + // [header][data][key][hash] + memcpy(ptr, m_file_content.m_pFileHeader, HEADER_SIZE); + ptr += HEADER_SIZE; + memcpy(ptr, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize); + ptr += m_file_content.m_uFileContentSize; + memcpy(ptr, m_file_content.m_pKeyMaterial, KEY_MAT_SIZE); + ptr += KEY_MAT_SIZE; + memcpy(ptr, m_file_content.m_pHashMaterial, HASH_SIZE); + ptr += HASH_SIZE; + break; + } + case 3: { + // [header][key][data][hash] + memcpy(ptr, m_file_content.m_pFileHeader, HEADER_SIZE); + ptr += HEADER_SIZE; + memcpy(ptr, m_file_content.m_pKeyMaterial, KEY_MAT_SIZE); + ptr += KEY_MAT_SIZE; + memcpy(ptr, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize); + ptr += m_file_content.m_uFileContentSize; + memcpy(ptr, m_file_content.m_pHashMaterial, HASH_SIZE); + ptr += HASH_SIZE; + break; + } + case 4: { + // [header][key][hash][data] + memcpy(ptr, m_file_content.m_pFileHeader, HEADER_SIZE); + ptr += HEADER_SIZE; + memcpy(ptr, m_file_content.m_pKeyMaterial, KEY_MAT_SIZE); + ptr += KEY_MAT_SIZE; + memcpy(ptr, m_file_content.m_pHashMaterial, HASH_SIZE); + ptr += HASH_SIZE; + memcpy(ptr, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize); + ptr += m_file_content.m_uFileContentSize; + break; + } + case 5: { + // [header][data][hash][key] + memcpy(ptr, m_file_content.m_pFileHeader, HEADER_SIZE); + ptr += HEADER_SIZE; + memcpy(ptr, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize); + ptr += m_file_content.m_uFileContentSize; + memcpy(ptr, m_file_content.m_pHashMaterial, HASH_SIZE); + ptr += HASH_SIZE; + memcpy(ptr, m_file_content.m_pKeyMaterial, KEY_MAT_SIZE); + ptr += KEY_MAT_SIZE; + break; + } + default: { + SLOGD("[%s][%d](SS_RET_FAIL) OUT OF THE FileStructureType : %d", + __FUNCTION__, + __LINE__, + FileStructureType(m_file_content.m_pFileHeader)); + delete data; + return SS_RET_FAIL; + } + break; + } + + if (m_file_content.m_pFileHeader[5] == 1) { + SLOGI("[%s][%d] Writing encrypted key", __FUNCTION__, __LINE__); + memcpy(ptr, m_file_content.m_EncryptedKeyBuffer, ENCRYPTED_KEY_SIZE); + } + + *buffer = data; + ret_size = buf_size; + + return SS_RET_SUCCESS; +#endif +} + +int secure_file::write_temp_store(unsigned char* data, unsigned int size) { + if (-1 == m_cache->write(m_full_path, data, size)) { + SLOGI("[%s][%d] Writing to cache storage failed.", __FUNCTION__, __LINE__); + delete data; + return SS_RET_FAIL; + } + + delete data; + return SS_RET_SUCCESS; +} + +int secure_file::write_persistent_store(unsigned char* data, + unsigned int size) { +#ifdef _SECOS_SIM_ + char filename[256] = {0}; + get_data_name(filename, false); + int iRet = file_op::write_file(filename, data, size); + OsaFree(data); + return iRet; +#else + shm_manager shm_mgr; + if (-1 == shm_mgr.init()) + { + SLOGE("Failed to init shm manager."); + return SS_RET_COMM_ERR; + } + + swdss_request req; + req.type = REQ_WRITE; + memcpy(req.data_name, m_full_path, SS_FULL_DATA_NAME_LEN); + req.data = data; + req.data_size = size; + + SLOGE("Data size = %d.", size); + + shm_mgr.lock(); + shm_mgr.put_request(&req); + OsaFree(data); + + if (-1 == call_ta_service()) + { + SLOGE("Failed to call ta service."); + return SS_RET_COMM_ERR; + } + + swdss_response rsp; + shm_mgr.get_response(&rsp); + + return rsp.retcode; +#endif +} + +int secure_file::read_temp_store(unsigned char** buffer, + unsigned int& ret_size) { + if (0 != m_cache->read(m_full_path, buffer, ret_size)) { + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + return SS_RET_SUCCESS; +} + +int secure_file::read_persistent_store(unsigned char** buffer, + unsigned int& ret_size) { +#ifdef _SECOS_SIM_ + char filename[256] = {0}; + get_data_name(filename, false); + return file_op::read_file(filename, buffer, ret_size); +#else + + shm_manager shm_mgr; + if (-1 == shm_mgr.init()) + { + SLOGE("Failed to init shm manager."); + return SS_RET_COMM_ERR; + } + + swdss_request req; + req.type = REQ_READ; + memcpy(req.data_name, m_full_path, SS_FULL_DATA_NAME_LEN); + req.data = NULL; + req.data_size = 0; + + shm_mgr.lock(); + shm_mgr.put_request(&req); + + if (-1 == call_ta_service()) + { + SLOGE("Failed to call ta service."); + return SS_RET_COMM_ERR; + } + + swdss_response rsp; + shm_mgr.get_response(&rsp); + + if (SS_RET_SUCCESS != rsp.retcode) + { + return rsp.retcode; + } + + *buffer = rsp.data; + ret_size = rsp.data_size; + + SLOGI("ret_size = %d", ret_size); + + return SS_RET_SUCCESS; + +#endif +} + +int secure_file::remove_persistent_store(bool is_dir) { +#ifdef _SECOS_SIM_ + char filename[256] = {0}; + get_data_name(filename, is_dir); + int iret = SS_RET_SUCCESS; + if (is_dir) { + iret = file_op::remove_folder(filename); + } else { + iret = file_op::remove_file(filename); + } + + return iret; + +#else + + shm_manager shm_mgr; + if (-1 == shm_mgr.init()) + { + SLOGE("Failed to init shm manager."); + return SS_RET_COMM_ERR; + } + + swdss_request req; + req.type = is_dir ? REQ_BATCH_REMOVE: REQ_REMOVE; + memcpy(req.data_name, m_full_path, SS_FULL_DATA_NAME_LEN); + req.data = NULL; + req.data_size = 0; + + shm_mgr.lock(); + shm_mgr.put_request(&req); + + if (-1 == call_ta_service()) + { + SLOGE("Failed to call ta service."); + return SS_RET_COMM_ERR; + } + + swdss_response rsp; + shm_mgr.get_response(&rsp); + + return rsp.retcode; +#endif +} + +int secure_file::check_file_content() { +#ifdef _SECOS_SIM_ + return 0; +#else + + // compute file hash + CBT_OCTET computed_hash[CCryptoEngine::Hash_Size]; + compute_file_hash(computed_hash); + + CBT_OCTET* stored_hash; + stored_hash = m_file_content.m_pHashMaterial; + + if (memcmp(computed_hash, stored_hash, CCryptoEngine::Hash_Size)) { + SLOGD("[%s][%d](SS_RET_INVALID_FILE) Hash is DIFFERENT!!!", + __FUNCTION__, + __LINE__); + return SS_RET_INVALID_FILE; + } + + return SS_RET_SUCCESS; +#endif +} + +int secure_file::decrypt_data() { +#ifdef _SECOS_SIM_ + m_file_content.m_pOutputContentSize = m_read_data_size; + m_file_content.m_pOutputContent = m_read_data; + m_read_data = NULL; + return 0; +#else + + if (m_use_crypted_key) { + int ret; + unsigned long uDecryptedKeySize; + SLOGI("[%s][%d] Decrypting content key", __FUNCTION__, __LINE__); + + ret = CCryptoEngine::RSADecrypt(m_file_content.m_EncryptedKeyBuffer, + &uDecryptedKeySize, + m_file_content.m_pEncryptedKey + 4, + m_file_content.m_uEncryptedKeySize, + m_rsa_key.rsa_n_data, + m_rsa_key.rsa_n_len, + m_rsa_key.rsa_d_data, + m_rsa_key.rsa_d_len); + + if (CRYPTO_SUCCESS != ret) { + SLOGF("[%s][%d](SS_RET_FAIL) RSADecrypt failed!", __FUNCTION__, __LINE__); + return SS_RET_FAIL; + } + + // content key size shall be exactly as expected + if (uDecryptedKeySize != (unsigned long)(CCryptoEngine::Key_Size)) { + SLOGF("[%s][%d](SS_RET_INVALID_FILE) Contexct key size is wrong %lu", + __FUNCTION__, + __LINE__, + uDecryptedKeySize); + return SS_RET_INVALID_FILE; + } + + m_file_content.m_pOutputContentSize = + DecryptEx(m_file_content.m_pOutputContent, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize, + m_file_content.m_EncryptedKeyBuffer); + + if (0 == m_file_content.m_pOutputContentSize) { + SLOGD("[%s][%d](ERROR) TZ Can't DEcrypt data WITH EncryptedKey mode (0 == m_file_content.m_pOutputContentSize)", + __FUNCTION__, + __LINE__); + SLOGF("[%s][%d](ERROR)", __FUNCTION__, __LINE__); + return SS_RET_INTERNAL_ERROR; + } + } else { + m_file_content.m_pOutputContentSize = + Decrypt(m_file_content.m_pOutputContent, + m_file_content.m_pFileContent, + m_file_content.m_uFileContentSize, + m_file_content.m_pKeyMaterial, + m_options); + + if (0 == m_file_content.m_pOutputContentSize) { + SLOGD("[%s][%d](ERROR) TZ Can't DEcrypt data WITHOUT EncryptedKey mode (0 == m_file_content.m_pOutputContentSize)", + __FUNCTION__, + __LINE__); + SLOGF("[%s][%d](ERROR)", __FUNCTION__, __LINE__); + return SS_RET_INTERNAL_ERROR; + } + } + + return SS_RET_SUCCESS; +#endif +} + +secure_file::~secure_file() { + (void)finalize(); +} + +int secure_file::prepare_data(unsigned char** ret_buf, unsigned int * ret_size, + unsigned char* buffer, unsigned int buf_size, unsigned int offset) { + // if partial rw is not enabled. + if (!(m_options & SS_OPT_PARTIAL_RW)) { + *ret_buf = buffer; + *ret_size = buf_size; + return SS_RET_SUCCESS; + } + + //partial write, read data first + m_is_partial_write = true; + unsigned char* data = NULL; + unsigned char* orig_data = NULL; + unsigned int ori_size = 0xffff; + + bool tmp_flag = m_use_crypted_key; + m_use_crypted_key = false; + int iRet = read(&orig_data, &ori_size, 0); + m_use_crypted_key = tmp_flag; + + if (SS_RET_SUCCESS != iRet) { + // data not exist and offset=0, new data entry is created. + if ((SS_RET_CANT_FIND_REQUESTED_DATA == iRet) && (0 == offset)) { + *ret_buf = buffer; + *ret_size = buf_size; + m_is_partial_write = false; + return SS_RET_SUCCESS; + } + + SLOGF("[%s][%d]Read data for partial write failed.", __FUNCTION__, + __LINE__); + return iRet; + } + + if (offset > ori_size) { + SLOGF("[%s][%d]offset(%d) exceed data size(%d).", __FUNCTION__, __LINE__, + offset, ori_size); + OsaFree(orig_data); + return SS_RET_OFFSET_ERR; + } + + unsigned int add_size = + (offset + buf_size) > ori_size ? (offset + buf_size - ori_size) : 0; + data = (unsigned char*)OsaMalloc(ori_size + add_size); + if (NULL == data) { + SLOGF("[%s][%d]Failed to alloc memory for data.", __FUNCTION__, __LINE__); + OsaFree(orig_data); + return SS_RET_MALLOC_FAILED; + } + + unsigned char* dest = data; + memcpy(dest, orig_data, offset); + dest += offset; + memcpy(dest, buffer, buf_size); + dest += buf_size; + + if (0 == add_size) { + memcpy(dest, orig_data + offset + buf_size, ori_size - offset - buf_size); + } + + *ret_buf = data; + *ret_size = ori_size + add_size; + OsaFree(orig_data); + + return SS_RET_SUCCESS; +} + +int secure_file::write(unsigned char* buffer, unsigned int buf_size, + unsigned int offset) { + SLOGE("Entering secure_file::write, buf_size = %d.", buf_size); + + if ((NULL == buffer) || ('\0' == m_data_name[0]) || (0 == buf_size)) { + SLOGE("[%s] input param error.\n", __FUNCTION__); + return SS_RET_INVALID_PARAM; + } + + if (SS_RET_SUCCESS != is_valid_data_name(m_data_name)) { + return SS_RET_INVALID_DATA_NAME; + } + + if (SS_MAX_DATA_SIZE < buf_size) { + return SS_RET_DATA_SIZE_IS_TOO_BIG; + } + + memset(&m_file_content, 0, sizeof(m_file_content)); + + int iRet = prepare_data(&m_write_data, &m_write_data_size, buffer, buf_size, + offset); + if (SS_RET_SUCCESS != iRet) { + SLOGF("[%s][%d]Failed to prepare data.", __FUNCTION__, __LINE__); + return iRet; + } + + SLOGE(" prepare_data data size = %d.", m_write_data_size); + + if (SS_MAX_DATA_SIZE < m_write_data_size) { + SLOGF("[%s][%d]Data size %d is too big.", __FUNCTION__, __LINE__, + m_write_data_size); + return SS_RET_DATA_SIZE_IS_TOO_BIG; + } + + // generating new key material + int ret = 0; + + // preparing file content for writing + ret = prepare_file_content(m_write_data, m_write_data_size); + if (ret) { + return ret; + } + + // drive path + derive_file_path(); + + // serialize data + unsigned char* data = NULL; + unsigned int size = 0; + if (SS_RET_SUCCESS != (ret = serialize_data(&data, size))) { + return ret; + } + + // write to cache + if (m_options & SS_OPT_TEMPORARY) { + return write_temp_store(data, size); + } + + // writing data into file + ret = write_persistent_store(data, size); + + return ret; +} + +int secure_file::read(unsigned char** ret_buf, unsigned int* read_size, + unsigned int offset) { + SLOGI("Entering secure_file::read"); + + if (('\0' == m_data_name[0]) || (NULL == read_size)) { + return SS_RET_INVALID_PARAM; + } + + if ((m_options & SS_OPT_PARTIAL_RW) && (0 == *read_size)) { + SLOGE("Read zero byte data."); + return SS_RET_INVALID_PARAM; + } + + if (SS_RET_SUCCESS != is_valid_data_name(m_data_name)) { + return SS_RET_INVALID_DATA_NAME; + } + + int ret = 0; + + unsigned int required_size = *read_size; + unsigned int off_set = offset; + *read_size = 0; + + // cleaning internal file structure representation + memset(&m_file_content, 0, sizeof(m_file_content)); + + derive_file_path(); + + // read from cache storage + if (m_options & SS_OPT_TEMPORARY) { + if (SS_RET_SUCCESS + != (ret = read_temp_store(&m_read_data, m_read_data_size))) { + SLOGE("[%s][%d](ERROR) Read data from temp store failed.", __FUNCTION__, + __LINE__); + return ret; + } + } else { + ret = read_persistent_store(&m_read_data, m_read_data_size); + if (ret) { + return ret; + } + } + + // Parsing content + ret = parse_file_content(m_read_data, m_read_data_size); + if (ret) { + return ret; + } + + // checking content integrity + ret = check_file_content(); + if (ret) { + return ret; + } + + // decrypting data + ret = decrypt_data(); + if (ret) { + SLOGE("[%s][%d](ERROR) DecryptData() // iRet : %d", __FUNCTION__, __LINE__, + ret); + return ret; + } + + // partial rw not enabled. + if (!(m_options & SS_OPT_PARTIAL_RW)) { + off_set = 0; + required_size = m_file_content.m_pOutputContentSize + 1; + } + + // partial read supported + if (off_set >= m_file_content.m_pOutputContentSize - 1) { + SLOGE("[%s][%d]offset(%d) exceed data size(%d).", __FUNCTION__, __LINE__, + off_set, m_file_content.m_pOutputContentSize); + return SS_RET_OFFSET_ERR; + } + + // copy data + unsigned ret_size = + m_file_content.m_pOutputContentSize >= (off_set + required_size) ? + required_size : (m_file_content.m_pOutputContentSize - off_set); + + *ret_buf = (unsigned char*)OsaMalloc(ret_size); + if (*ret_buf == NULL) { + SLOGE("[%s][%d]Failed to alloc memory.", __FUNCTION__, __LINE__); + return SS_RET_MALLOC_FAILED; + } + + memcpy(*ret_buf, m_file_content.m_pOutputContent + off_set, ret_size); + *read_size = ret_size; + + return SS_RET_SUCCESS; +} + +int secure_file::write_ex(unsigned char* buffer, unsigned int buf_size, + unsigned int offset, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_e_data, + unsigned long rsa_e_len) { + int ret = 0; + + if ((NULL == buffer) || ('\0' == m_data_name[0]) || (0 == buf_size)) { + SLOGE("[%s] input param error.\n", __FUNCTION__); + return SS_RET_INVALID_PARAM; + } + + if (SS_RET_SUCCESS != is_valid_data_name(m_data_name)) { + return SS_RET_INVALID_DATA_NAME; + } + + if (SS_MAX_DATA_SIZE < buf_size) { + return SS_RET_DATA_SIZE_IS_TOO_BIG; + } + + // checking input correctness + if ((NULL == rsa_n_data) || (NULL == rsa_e_data) || (rsa_n_len > RSA_KEY_SIZE) + || (rsa_e_len > RSA_KEY_SIZE) || (rsa_e_len > rsa_n_len)) { + return SS_RET_INVALID_RSA_PARAM; + } + + // initiating special mode + m_use_crypted_key = true; + + // initializing RSA key data + m_rsa_key.rsa_e_data = const_cast(rsa_e_data); + m_rsa_key.rsa_e_len = rsa_e_len; + m_rsa_key.rsa_n_data = const_cast(rsa_n_data); + m_rsa_key.rsa_n_len = rsa_n_len; + m_rsa_key.rsa_d_data = NULL; + m_rsa_key.rsa_d_len = 0; + + // writing data into file + ret = write(buffer, buf_size, offset); + + // removing special mode + m_use_crypted_key = false; + + return ret; +} + +int secure_file::read_ex(unsigned char** ret_buf, unsigned int* read_size, + unsigned int offset, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_d_data, + unsigned long rsa_d_len) { + if (('\0' == m_data_name[0]) || (NULL == read_size)) { + return SS_RET_INVALID_PARAM; + } + + if ((m_options & SS_OPT_PARTIAL_RW) && (0 == *read_size)) { + SLOGE("Read zero byte data."); + return SS_RET_INVALID_PARAM; + } + + if (SS_RET_SUCCESS != is_valid_data_name(m_data_name)) { + return SS_RET_INVALID_DATA_NAME; + } + + int ret = 0; + + // initiating special mode + m_use_crypted_key = true; + + // checking input correctness + if ((NULL == rsa_n_data) || (NULL == rsa_d_data) || (rsa_n_len > RSA_KEY_SIZE) + || (rsa_d_len > RSA_KEY_SIZE) || (rsa_d_len > rsa_n_len)) { + return SS_RET_INVALID_RSA_PARAM; + } + + // initializing RSA key data + m_rsa_key.rsa_d_data = const_cast(rsa_d_data); + m_rsa_key.rsa_d_len = rsa_d_len; + m_rsa_key.rsa_n_data = const_cast(rsa_n_data); + m_rsa_key.rsa_n_len = rsa_n_len; + m_rsa_key.rsa_e_data = NULL; + m_rsa_key.rsa_e_len = 0; + + // writing data into file + ret = read(ret_buf, read_size, offset); + + // removing special mode + m_use_crypted_key = false; + + return ret; +} + +int secure_file::validate() { + if ('\0' == m_data_name[0]) { + return SS_RET_INVALID_PARAM; + } + + if (SS_RET_SUCCESS != is_valid_data_name(m_data_name)) { + return SS_RET_INVALID_DATA_NAME; + } + + int ret = 0; + + // cleaning internal file structure representation + memset(&m_file_content, 0, sizeof(m_file_content)); + + // drive path + derive_file_path(); + + // read from cache storage + if (m_options & SS_OPT_TEMPORARY) { + if (SS_RET_SUCCESS + != (ret = read_temp_store(&m_read_data, m_read_data_size))) { + SLOGD("[%s][%d](ERROR) Read data from temp store failed.", __FUNCTION__, + __LINE__); + return ret; + } + } else { + ret = read_persistent_store(&m_read_data, m_read_data_size); + if (ret) { + return ret; + } + } + + // Parsing content + ret = parse_file_content(m_read_data, m_read_data_size); + if (ret) { + return ret; + } + + // checking content integrity + return check_file_content(); +} + +int secure_file::remove() { + if ('\0' == m_data_name[0]) { + return SS_RET_INVALID_PARAM; + } + + if (SS_RET_SUCCESS != is_valid_data_name(m_data_name)) { + return SS_RET_INVALID_DATA_NAME; + } + + derive_file_path(); + + if (SS_OPT_TEMPORARY & m_options) { + if (SS_RET_SUCCESS != m_cache->remove(m_full_path)) { + SLOGE("Data file not exist, path = [%s].", m_full_path); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + return SS_RET_SUCCESS; + } + + return remove_persistent_store(false); +} + +int secure_file::clear_storage() { + derive_file_path(); + + if (SS_OPT_TEMPORARY & m_options) { + return m_cache->batch_remove(m_full_path); + } + + return remove_persistent_store(true); +} + +#ifdef _SECOS_SIM_ +#define SS_CRED_LEN 36 +void secure_file::get_data_name(char* data_name, bool is_dir) { + uint8_t* ptr = (uint8_t*)data_name; + memcpy(ptr, SWD_SS_ROOT, strlen(SWD_SS_ROOT)); + ptr += strlen(SWD_SS_ROOT); + + // first 4 bytes for directory. + //byte_to_hex(ptr, (uint8_t*)m_full_path, 4); + memcpy(ptr, m_full_path, SS_CRED_LEN); + + if (is_dir) { + return; + } + + // next 8 bytes for filename + memcpy(ptr, m_full_path, strlen(m_full_path)); + //memset(ptr, '/', 1); + //ptr += 1; + //memcpy(ptr,m_full_path+SS_CRED_LEN,) + //byte_to_hex(ptr, (uint8_t*)&m_full_path[4], 8); +} +#endif + diff --git a/ssflib/dep/swdss/source/ss_api.cpp b/ssflib/dep/swdss/source/ss_api.cpp new file mode 100755 index 0000000..d70ad7a --- /dev/null +++ b/ssflib/dep/swdss/source/ss_api.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "ss_api.h" +#include "secure_file.h" +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int ss_init(int strategy) { + return 0; +} + +int ss_set_credential(ss_credential_s * cred, const char* uuid, + const char* module_name, unsigned long major_ver, unsigned long minor_ver) { + if ((NULL == cred) || (NULL == uuid) || (NULL == module_name)) { + SLOGE("[%s] input param error.\n", __FUNCTION__); + return SS_RET_INVALID_PARAM; + } + + int uuid_size = strlen(uuid); + int mn_size = strlen(module_name); + + if (uuid_size > SS_MAX_UUID_LEN || mn_size > SS_MAX_MODULE_NAME_LEN) { + SLOGE("[%s] length of uuid or module name error.\n", __FUNCTION__); + return SS_RET_INVALID_PARAM; + } + + memset(cred->uuid, '\0', SS_MAX_UUID_LEN); + memset(cred->module_name, '\0', SS_MAX_MODULE_NAME_LEN); + strncpy(cred->uuid, uuid, uuid_size); + strncpy(cred->module_name, module_name, mn_size); + + cred->version.major = major_ver; + cred->version.minor = minor_ver; + + return SS_RET_SUCCESS; +} + +int ss_write(unsigned char* buffer, unsigned int data_size, unsigned int offset, + const char* data_name, const ss_credential_s * cred, unsigned int options) { + secure_file sec_file; + int ret = sec_file.initialize(cred, data_name, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.write(buffer, data_size, offset); +} + +int ss_read(unsigned char** ret_buf, unsigned int* data_size, + unsigned int offset, const char* data_name, const ss_credential_s * cred, + unsigned int options) { + secure_file sec_file; + int ret = sec_file.initialize(cred, data_name, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.read(ret_buf, data_size, offset); +} + +int ss_write_ex(unsigned char* buffer, unsigned int data_size, + unsigned int offset, const char* data_name, const ss_credential_s* cred, + unsigned int options, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_e_data, + unsigned long rsa_e_len) { + secure_file sec_file; + int ret = sec_file.initialize(cred, data_name, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.write_ex(buffer, data_size, offset, rsa_n_data, rsa_n_len, + rsa_e_data, rsa_e_len); +} + +int ss_read_ex(unsigned char** ret_buf, unsigned int* data_size, + unsigned int offset, const char* data_name, const ss_credential_s* cred, + unsigned int options, const unsigned char* rsa_n_data, + unsigned long rsa_n_len, const unsigned char* rsa_d_data, + unsigned long rsa_d_len) { + secure_file sec_file; + int ret = sec_file.initialize(cred, data_name, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.read_ex(ret_buf, data_size, offset, rsa_n_data, rsa_n_len, + rsa_d_data, rsa_d_len); +} + +int ss_validate(const char* data_name, const ss_credential_s* cred, + unsigned int options) { + secure_file sec_file; + int ret = sec_file.initialize(cred, data_name, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.validate(); +} + +int ss_delete(const char* data_name, const ss_credential_s* cred, + unsigned int options) { + secure_file sec_file; + int ret = sec_file.initialize(cred, data_name, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.remove(); +} + +int ss_clear_storage(const ss_credential_s* cred, unsigned int options) { + secure_file sec_file; + int ret = sec_file.initialize(cred, NULL, options); + if (SS_RET_SUCCESS != ret) { + return ret; + } + + return sec_file.clear_storage(); +} + +int ss_free_buffer(unsigned char* buffer) { + if (NULL != buffer) { + OsaFree(buffer); + } + + return SS_RET_SUCCESS; +} +#ifdef __cplusplus +} +#endif + diff --git a/ssflib/dep/swdss/source/ss_crypto.cpp b/ssflib/dep/swdss/source/ss_crypto.cpp new file mode 100755 index 0000000..dc1d820 --- /dev/null +++ b/ssflib/dep/swdss/source/ss_crypto.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "ss_crypto.h" + +static CBT_UINT32 lcg_last; /* Storing the last used LCG value */ + +void seed_rand(CBT_UINT32 seed) { + lcg_last = seed; +} + +CBT_UINT32 gen_rand(void) { + return (lcg_last = lcg_last * lcg_A + lcg_C); +} + +void gen_rand_vec(CBT_OCTET* vec, CBT_UINT32 size) { + CBT_UINT32 i; + + seed_rand((CBT_UINT32)time(NULL)); + for (i = 0; i < size; i++) { + vec[i] = (CBT_OCTET)(gen_rand() % 256); + } +} + +/** + * @brief Encrypt provided data + */ +int CCryptoEngine::Encrypt(uint8_t* dest, uint8_t* src, unsigned long data_len, + const uint8_t* key, unsigned long key_type) { + //memcpy(dest,src,data_len); + //return data_len; + unsigned int cipherTextLen, t; + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_AES); + + crt->SE_init(crt, ID_ENC_CTR, ID_PKCS5, const_cast(key), 16, + (cc_u8*)NULL); + crt->SE_process(crt, src, data_len, dest, + static_cast(&cipherTextLen)); + crt->SE_final(crt, (cc_u8*)NULL, 0, (dest + cipherTextLen), + static_cast(&t)); + cipherTextLen += t; + destroy_CryptoCoreContainer(crt); + + return cipherTextLen; +} + +/** + * @brief Decrypt provided data + */ +int CCryptoEngine::Decrypt(uint8_t* dest, uint8_t* src, unsigned long data_len, + const uint8_t* key, unsigned long key_type) { + unsigned int plainTextLen, t; + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_AES); + crt->SE_init(crt, ID_DEC_CTR, ID_PKCS5, const_cast(key), 16, + (cc_u8*)NULL); + crt->SE_process(crt, src, data_len - 16, dest, + static_cast(&plainTextLen)); + crt->SE_final(crt, src + data_len - 16, 16, (uint8_t*)(dest + plainTextLen), + static_cast(&t)); + destroy_CryptoCoreContainer(crt); + plainTextLen += t; + return plainTextLen; +} + +/** + * @brief Compute hash value over provided data + */ +int CCryptoEngine::Hash(uint8_t* dest, const uint8_t* src, + unsigned long data_len) { + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_SHA1); + crt->MD_init(crt); + crt->MD_update(crt, static_cast((void*)const_cast(src)), + data_len); + crt->MD_final(crt, (uint8_t*)dest); + destroy_CryptoCoreContainer(crt); + return 0; +} + +/** + * @brief Generating random number + */ +int CCryptoEngine::Random(uint8_t* dest, unsigned long data_len) { + CryptoCoreContainer *crt = create_CryptoCoreContainer(ID_X931); + crt->PRNG_seed(crt, (cc_u8*)NULL); + crt->PRNG_get(crt, data_len * 8, (uint8_t*)dest); + destroy_CryptoCoreContainer(crt); + return 0; +} + +/** + * @brief Encrypt provided data by using HW based encryption engine + */ +int CCryptoEngine::HWEncrypt(unsigned char* dest, unsigned long* dest_len, + unsigned char* src, unsigned long data_len, const unsigned char* key, + unsigned long key_type, unsigned long mode) { +#if defined(_SECOS_SIM_) + *dest_len = Encrypt(dest, src, data_len, key, key_type); + return SS_RET_SUCCESS; +#else + + UCI_HANDLE uh = UCI_ERROR; + uh = uci_context_alloc(ID_UCI_AES128,(uci_engine_config_e)key_type); + if ((UCI_ERROR == uh) || (UCI_MEM_ALLOR_ERROR == uh)) + { + SLOGE("Failed to alloc uci context handle.\n"); + return SS_RET_FAIL; + } + + int ret = 0; + + switch (mode) + { + case ID_UCI_ENC_CTR: + { + ret = uci_se_init(uh,ID_UCI_ENC_CTR,ID_UCI_NO_PADDING,(unsigned char*)key,16,NULL); + break; + } + case ID_UCI_ENC_ECB: + { + ret = uci_se_init(uh,ID_UCI_ENC_ECB,ID_UCI_PKCS5,(unsigned char*)key,16,NULL); + break; + } + default: + { + SLOGE("Mode %d not supported.",mode); + uci_context_free(uh); + return SS_RET_INVALID_PARAM; + } + } + + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to init context, retcode = %d.\n",ret); + uci_context_free(uh); + return SS_RET_FAIL; + } + + ret = uci_se_process(uh,src,data_len,dest,(unsigned int*)dest_len); + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to encrypt data, retcode = %d.\n",ret); + uci_context_free(uh); + return SS_RET_FAIL; + } + + unsigned int t; + ret = uci_se_final(uh,NULL,0,dest+(*dest_len),&t); + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to call uci_se_final, retcode = %d.\n",ret); + uci_context_free(uh); + return SS_RET_FAIL; + } + + *dest_len += t; + + ret = uci_context_free(uh); + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to free context, retcode = %d.\n",ret); + } + + return SS_RET_SUCCESS; +#endif +} + +/** + * @brief Decrypt provided data + */ +int CCryptoEngine::HWDecrypt(unsigned char* dest, unsigned long* dest_len, + unsigned char* src, unsigned long data_len, const unsigned char* key, + unsigned long key_type, unsigned long mode) { +#if !defined(_SECOS_SIM_) + UCI_HANDLE uh = UCI_ERROR; + uh = uci_context_alloc(ID_UCI_AES128,(uci_engine_config_e)key_type); + if ((UCI_ERROR == uh) || (UCI_MEM_ALLOR_ERROR == uh)) + { + SLOGE("Failed to alloc uci context handle."); + return SS_RET_FAIL; + } + + int ret = 0; + + switch (mode) + { + case ID_UCI_ENC_CTR: + { + ret = uci_se_init(uh,ID_UCI_DEC_CTR,ID_UCI_NO_PADDING,(unsigned char*)key,16,NULL); + break; + } + case ID_UCI_ENC_ECB: + { + ret = uci_se_init(uh,ID_UCI_DEC_ECB,ID_UCI_PKCS5,(unsigned char*)key,16,NULL); + break; + } + default: + { + SLOGE("Mode %d not supported.",mode); + return SS_RET_INVALID_PARAM; + } + } + + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to init context, retcode = %d.",ret); + uci_context_free(uh); + return SS_RET_FAIL; + } + + ret = uci_se_process(uh,src,data_len-16,dest,(unsigned int*)dest_len); + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to decrypt data, retcode = %d.",ret); + uci_context_free(uh); + return SS_RET_FAIL; + } + + unsigned int t; + ret = uci_se_final(uh,src+data_len-16,16,dest+(*dest_len),&t); + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to call uci_se_final, retcode = %d.",ret); + uci_context_free(uh); + return SS_RET_FAIL; + } + + *dest_len += t; + + ret = uci_context_free(uh); + if (UCI_SUCCESS != ret) + { + SLOGE("Failed to free context, retcode = %d.",ret); + } + + return SS_RET_SUCCESS; + +#else + return SS_RET_SUCCESS; +#endif +} + +/** + * @brief Encrypting data by using RSA pub key + */ +int CCryptoEngine::RSAEncrypt(uint8_t* dest, unsigned long* dest_len, + const uint8_t* src, unsigned long src_len, const uint8_t* RSA_N_Data, + unsigned long RSA_N_Len, const uint8_t* RSA_E_Data, + unsigned long RSA_E_Len) { + int ret; + cc_u32 result_size; + CryptoCoreContainer* ccContainerRSA; + ccContainerRSA = create_CryptoCoreContainer(ID_RSA2048); + + /* seting RSA key for AES key encryption */ + ret = ccContainerRSA->RSA_setKeypair(ccContainerRSA, ID_RSAES_PKCS15, + const_cast(RSA_N_Data), RSA_N_Len, + const_cast(RSA_E_Data), RSA_E_Len, (cc_u8*)NULL, 0); + if (CRYPTO_SUCCESS != ret) { + destroy_CryptoCoreContainer(ccContainerRSA); + return ret; + } + + /* encrypting AES key */ + ret = ccContainerRSA->AE_encrypt(ccContainerRSA, const_cast(src), + src_len, dest, &result_size); + *dest_len = result_size; + + destroy_CryptoCoreContainer(ccContainerRSA); + + return ret; +} + +/** + * @brief Encrypting data by using RSA pub key + */ +int CCryptoEngine::RSADecrypt(uint8_t* dest, unsigned long* dest_len, + const uint8_t* src, unsigned long src_len, const uint8_t* RSA_N_Data, + unsigned long RSA_N_Len, const uint8_t* RSA_D_Data, + unsigned long RSA_D_Len) { + int ret; + cc_u32 result_size; + CryptoCoreContainer* ccContainerRSA; + ccContainerRSA = create_CryptoCoreContainer(ID_RSA2048); + + /* seting RSA key for AES key encryption */ + ret = ccContainerRSA->RSA_setKeypair(ccContainerRSA, ID_RSAES_PKCS15, + const_cast(RSA_N_Data), RSA_N_Len, (cc_u8*)NULL, 0, + const_cast(RSA_D_Data), RSA_D_Len); + if (CRYPTO_SUCCESS != ret) { + destroy_CryptoCoreContainer(ccContainerRSA); + return ret; + } + + /* encrypting AES key */ + ret = ccContainerRSA->AE_decrypt(ccContainerRSA, const_cast(src), + src_len, dest, &result_size); + *dest_len = result_size; + + destroy_CryptoCoreContainer(ccContainerRSA); + + return ret; +} + diff --git a/ssflib/dep/swdss/source/ss_misc.cpp b/ssflib/dep/swdss/source/ss_misc.cpp new file mode 100755 index 0000000..78dc64d --- /dev/null +++ b/ssflib/dep/swdss/source/ss_misc.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "ss_misc.h" +#include + +void byte_to_hex(uint8_t* dest, const uint8_t* src, unsigned long src_len) { + char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f'}; + + for (unsigned long j = 0; j < src_len; j++) { + dest[j * 2] = hexval[((src[j] >> 4) & 0xF)]; + dest[(j * 2) + 1] = hexval[(src[j]) & 0x0F]; + } +} + +//3d3ee6d8 +void hex_to_byte(uint8_t* dest, const uint8_t* src, unsigned long src_len) { + char x = 0; + for (unsigned long j = 0; j < src_len; j++) { + if (src[j] >= '0' && src[j] <= '9') { + x = src[j] - '0'; + } + + if (src[j] >= 'a' && src[j] <= 'f') { + x = src[j] - 'a' + 10; + } + + if (0 == j % 2) { + dest[j / 2] = (x << 4) & 0xF0; + } else { + dest[j / 2] |= x; + } + } +} + +int is_hex(const char* text, char sep) { + for (uint32_t i = 0; i < strlen(text); ++i) { + if ((text[i] >= '0' && text[i] <= '9') || (text[i] >= 'a' && text[i] <= 'f') + || (text[i] == sep)) { + continue; + } else { + return -1; + } + } + + return 0; +} + diff --git a/ssflib/dep/swdss/source/ss_temp_store.cpp b/ssflib/dep/swdss/source/ss_temp_store.cpp new file mode 100755 index 0000000..4d19920 --- /dev/null +++ b/ssflib/dep/swdss/source/ss_temp_store.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 "ss_temp_store.h" +#include "slog.h" + +#define SS_NODE_ID_CMP(id1, id2) memcmp(static_cast(id1),static_cast(id2),SS_NODE_ID_LEN) +#define SS_NODE_ID_CPY(dest,src) memcpy(static_cast(dest),static_cast(src),SS_NODE_ID_LEN) + +pthread_mutex_t auto_lock::m_mutex = PTHREAD_MUTEX_INITIALIZER; + +ss_temp_store* ss_temp_store::m_instance = NULL; + +ss_temp_store* ss_temp_store::get_instance() { + if (NULL == m_instance) { + auto_lock lock; + if (NULL == m_instance) { + m_instance = new ss_temp_store; + } + } + + return m_instance; +} + +int ss_temp_store::read(char* data_name, unsigned char** data, + unsigned int& data_size) { + auto_lock lock; + + temp_ss_node* node = find_node(data_name); + + if (NULL == node) { + SLOGE("Data not found."); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + *data = (unsigned char*)OsaMalloc(node->data_size); + if (NULL == *data) { + SLOGE("Failed to malloc data."); + return SS_RET_MALLOC_FAILED; + } + + memcpy(*data, node->data, node->data_size); + data_size = node->data_size; + + SLOGI("Data read size :%d.", data_size); + + return SS_RET_SUCCESS; +} + +int ss_temp_store::write(char* data_name, unsigned char* data, + unsigned int data_size) { + auto_lock lock; + + temp_ss_node* node = find_node(data_name); + if (NULL != node) { + OsaFree(node->data); + node->data = (unsigned char*)OsaMalloc(data_size); + if (NULL == node->data) { + SLOGE("Failed to malloc data."); + return SS_RET_MALLOC_FAILED; + } + + memcpy(node->data, data, data_size); + node->data_size = data_size; + return SS_RET_SUCCESS; + } + + node = new temp_ss_node; + if (NULL == node) { + SLOGE("Failed to malloc memory."); + return SS_RET_MALLOC_FAILED; + } + + SS_NODE_ID_CPY(node->node_id, data_name); + + node->data = (unsigned char*)OsaMalloc(data_size); + if (NULL == node->data) { + SLOGE("Failed to malloc data."); + OsaFree(node); + return SS_RET_MALLOC_FAILED; + } + + memcpy(node->data, data, data_size); + node->data_size = data_size; + + if (NULL == m_head.next) { + m_head.next = node; + node->prev = &m_head; + node->next = NULL; + } else { + node->next = m_head.next; + node->prev = &m_head; + m_head.next->prev = node; + m_head.next = node; + } + + return SS_RET_SUCCESS; +} + +int ss_temp_store::remove(char* data_name) { + auto_lock lock; + + temp_ss_node* node = find_node(data_name); + if (NULL == node) { + SLOGE("Data not found."); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + del_node(node); + + return SS_RET_SUCCESS; +} + +int ss_temp_store::batch_remove(char* dir) { + auto_lock lock; + + if (NULL == m_head.next) { + SLOGI("ss temp storage is empty."); + return SS_RET_CANT_FIND_REQUESTED_DATA; + } + + temp_ss_node* node = m_head.next; + int data_find = 0; + while (NULL != node) { + // is dir the same, dir len is 4 byte. + if (0 == memcmp(node->node_id, dir, 4)) { + node = del_node(node); + data_find = 1; + continue; + } + + node = node->next; + } + + return (data_find ? SS_RET_SUCCESS : SS_RET_CANT_FIND_REQUESTED_DATA); + +} + +temp_ss_node* ss_temp_store::find_node(char* data_name) { + if (NULL == m_head.next) { + SLOGI("ss temp storage is empty."); + return NULL; + } + + temp_ss_node* node = m_head.next; + while (NULL != node) { + if (0 == SS_NODE_ID_CMP(node->node_id, data_name)) { + break; + } + + node = node->next; + } + + return node; +} + +temp_ss_node* ss_temp_store::del_node(temp_ss_node* node) { + if (NULL == node) { + return NULL; + } + + temp_ss_node* ret_node = node->next; + + if (node->data) { + OsaFree(node->data); + } + + node->prev->next = node->next; + if (NULL != node->next) { + node->next->prev = node->prev; + } + + delete node; + + return ret_node; +} + diff --git a/ssflib/dep/time/ssf_time.cpp b/ssflib/dep/time/ssf_time.cpp new file mode 100755 index 0000000..105cdfc --- /dev/null +++ b/ssflib/dep/time/ssf_time.cpp @@ -0,0 +1,209 @@ +/* + * ===================================================================================== + * + * Filename: ssf_time.cpp + * + * Description: SSF time functions + * + * Version: 1.0 + * Created: 30 June 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Cheryl (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include "tee_internal_api.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +bool isSetReqTaSpec = false; +TEE_Time reqTaTime; +TEE_Time reeTaTime; +TEE_Time teeTaTime; + +/*----------------------------------------------------------------------------- + * TEE API Implementation + *-----------------------------------------------------------------------------*/ +/** + * The TEE_GetSystemTime function retrieves the current system time. + * The system time has an arbitrary implementation-defined origin that can + * vary across TA instances. The minimum guarantee is that the system time + * MUST be monotonic for a given TA instance. + * @param time Filled with the number of seconds and milliseconds since + * midnight on January 1, 1970, UTC + */ +void TEE_GetSystemTime(TEE_Time* time) { + uint32_t value; + bool reqSrcTee = true; + TEE_Result result = TEE_GetPropertyAsU32( + (TEE_PropSetHandle)TEE_PROPSET_TEE_IMPLEMENTATION, + "gpd.tee.systemTime.protectionLevel", &value); + LOGD(SSF_LIB, "TEE_GetPropertyAsU32(systemTime.protectionLevel) : %d(ret:%d)", + value, result); + if (result == TEE_SUCCESS) if (value == 1000) /* req ree time*/ + reqSrcTee = false; + + struct timespec tspec; + tspec.tv_sec = 0; + tspec.tv_nsec = 0; + if (reqSrcTee == true) { + clock_gettime(CLOCK_REALTIME, &tspec); + time->seconds = tspec.tv_sec; + time->millis = tspec.tv_nsec / 1000000ULL; + } else TEE_GetREETime(time); +} + +/** + * The TEE_Wait function waits for the specified number of milliseconds or + * waits forever if timeout equals TEE_TIMEOUT_INFINITE (0xFFFFFFFF). + * When this function returns success, the implementation MUST guarantee that + * the difference between two calls to TEE_GetSystemTime before and after + * the call to TEE_Wait is greater than or equal to the requested timeout. + * However, there may be additional implementation-dependent delays due to + * the scheduling of TEE tasks. + * This function is cancellable, i.e. if the current task’s cancelled flag is + * set and the TA has unmasked the effects of cancellation, then this + * function returns earlier than the requested timeout with the return code + * TEE_ERROR_CANCEL. See section 4.10 for more details about cancellations. + * @param timeout The number of milliseconds to wait, or TEE_TIMEOUT_INFINITE + */ +TEE_Result TEE_Wait(uint32_t timeout) { + bool isNeedCancel = false; + uint32_t decreaseTimeoutMillis = 500; + uint32_t remainTimeout = timeout; + while (1) { + if (timeout != TEE_TIMEOUT_INFINITE) { + remainTimeout = remainTimeout - decreaseTimeoutMillis; + if (remainTimeout <= 0) break; + } + usleep(decreaseTimeoutMillis * 1000); + if (TEE_GetCancellationFlag()) isNeedCancel = true; + } + if (isNeedCancel == true) return TEE_ERROR_CANCEL; + return TEE_SUCCESS; +} + +/** + * The _TEE_Time_To_TimeSpec function converts TEE_Time to timespec. + * @param dstTime Pointer to output time in timespec format + * @param srcTime Pointer to input time in TEE_Time format + */ +struct timespec* _TEE_Time_To_TimeSpec(struct timespec* dstTime, + TEE_Time* srcTime) { + dstTime->tv_sec = srcTime->seconds; + dstTime->tv_nsec = srcTime->millis * 1000000ULL; + return dstTime; +} + +#if 0 +/** + * The _TimeSpec_To_TEE_TIME function converts timespec toTEE_Time. + * @param dstTime Pointer to output time in TEE_Time format + * @param srcTime Pointer to input time in timespec format + */ +TEE_Time* _TimeSpec_To_TEE_TIME(TEE_Time* dstTime, struct timespec* srcTime) +{ + dstTime->seconds = srcTime->tv_sec; + dstTime->millis = srcTime->tv_nsec / 1000000ULL; + return dstTime; +} +#endif + +TEE_Time* _TEE_GetAdjDiffTeeTime(TEE_Time* dstTime, TEE_Time* startTime, + TEE_Time* endTime) { + struct timespec startSpec; + struct timespec endSpec; + struct timespec dstSpec; + _TEE_Time_To_TimeSpec(&startSpec, startTime); + _TEE_Time_To_TimeSpec(&endSpec, endTime); + _TEE_Time_To_TimeSpec(&dstSpec, dstTime); + + time_t stTt = startSpec.tv_sec + (startSpec.tv_nsec + 500000000) / 1000000000; + time_t endTt = endSpec.tv_sec + (endSpec.tv_nsec + 500000000) / 1000000000; + time_t dstTt = dstSpec.tv_sec + (dstSpec.tv_nsec + 500000000) / 1000000000; + + dstTt = dstTt + endTt - stTt; + static TEE_Time retTt; + retTt.seconds = dstTt; + retTt.millis = 0; + return &retTt; +} + +/** + * The TEE_GetTAPersistentTime function retrieves the persistent time of the + * Trusted Application, expressed as a number of seconds and milliseconds + * since the arbitrary origin set by calling TEE_SetTAPersistentTime. + * @param time A pointer to the TEE_Time structure to be set to the current + * TA Persistent Time. If an error other than TEE_ERROR_OVERFLOW + * is returned, this structure is filled with zeroes. + */ +TEE_Result TEE_GetTAPersistentTime(TEE_Time* time) { + if (isSetReqTaSpec == false) return TEE_ERROR_TIME_NOT_SET; + + uint32_t value; + bool reqSrcTee = true; + TEE_Result result = TEE_GetPropertyAsU32( + (TEE_PropSetHandle)TEE_PROPSET_TEE_IMPLEMENTATION, + "gpd.tee.systemTime.protectionLevel", &value); + LOGD(SSF_LIB, "TEE_GetPropertyAsU32(systemTime.protectionLevel) : %d(ret:%d)", + value, result); + if (result == TEE_SUCCESS) if (value == 1000) /* req ree time*/ + reqSrcTee = false; + + TEE_Time nowTime; + if (reqSrcTee == true) { + TEE_GetSystemTime(&nowTime); + TEE_Time* retTime = _TEE_GetAdjDiffTeeTime(&reqTaTime, &teeTaTime, + &nowTime); + memcpy(time, retTime, sizeof(TEE_Time)); + } else { + TEE_GetREETime(&nowTime); + TEE_Time* retTime = _TEE_GetAdjDiffTeeTime(&reqTaTime, &reeTaTime, + &nowTime); + memcpy(time, retTime, sizeof(TEE_Time)); + } + return TEE_SUCCESS; +} + +/** + * The TEE_SetTAPersistentTime function sets the persistent time of the + * current Trusted Application. + * Only the persistent time for the current Trusted Application is modified, + * not the persistent time of other Trusted Applications. This will affect all + * instances of the current Trusted Application. The modification is atomic + * and persistent across device reboots. + * @param time Filled with the persistent time of the current TA + */ +TEE_Result TEE_SetTAPersistentTime(TEE_Time* time) { + reqTaTime = *time; + TEE_GetREETime(&reeTaTime); + TEE_GetSystemTime(&teeTaTime); + + isSetReqTaSpec = true; + return TEE_SUCCESS; +} + +/* TODO : NOT IMPLEMENTED */ +/** + * The TEE_GetREETime function retrieves the current REE system time. This + * function retrieves the current time as seen from the point of view of the + * REE, expressed in the number of seconds since midnight on + * January 1, 1970, UTC. + * @param time Filled with the number of seconds and milliseconds since + * midnight on January 1, 1970, UTC + */ +void TEE_GetREETime(TEE_Time* time) { + return; +} diff --git a/ssflib/dep/uci/include/uci_aes_xcbc_mac.h b/ssflib/dep/uci/include/uci_aes_xcbc_mac.h new file mode 100755 index 0000000..47ff5f0 --- /dev/null +++ b/ssflib/dep/uci/include/uci_aes_xcbc_mac.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_cryptocore.h + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2014.3 + **/ +#ifndef _UCI_AES_XCBC_MAC_H +#define _UCI_AES_XCBC_MAC_H +#include "uci_type.h" +#include "CC_API.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAXBLOCKSIZE 32 + +typedef struct { + unsigned char K[3][MAXBLOCKSIZE]; + unsigned char IV[MAXBLOCKSIZE]; + + unsigned char key[MAXBLOCKSIZE]; + unsigned int buflen; + unsigned int blocksize; +} aes_xcbc_state; + +int xcbc_init(aes_xcbc_state *xcbc, unsigned char *key, unsigned int keylen); +int xcbc_process(aes_xcbc_state *xcbc, unsigned char *in, unsigned int inlen); +int xcbc_done(aes_xcbc_state *xcbc, unsigned char *out, unsigned int *outlen); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssflib/dep/uci/include/uci_api.h b/ssflib/dep/uci/include/uci_api.h new file mode 100755 index 0000000..0acb7e4 --- /dev/null +++ b/ssflib/dep/uci/include/uci_api.h @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file UCI_API.h + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.7 + **/ + +/** + * @addtogroup g_uci + * @{ + */ + +#ifndef _UCI_API_H_ +#define _UCI_API_H_ + +#include "uci_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief allocates memory and initializes the cryptographic context structure, and return the crypto handle.. + * + * @param[in] algorithm, algorithm wants to use. + * @config[in] config, config specified which function to call. + * @retval UCI handle if success + * @retval UCI_ERROR if fail + * @retval UCI_MEM_ALLOR_ERROR if allocate memory error. + */ +UCI_HANDLE uci_context_alloc(unsigned int algorithm, + uci_engine_config_e config); + +/** + * @brief free allocated memory. + * + * @param[in] algorithm algorithm wants to use. + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a invalid handle. + */ +int uci_context_free(UCI_HANDLE oh); + +/** + * @brief Digest initialization. + * + * @param[in] oh UCI handle + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is a invalid handle. + */ +int uci_md_init(UCI_HANDLE oh); + +/** + * @brief process a message block + * @param[in] oh UCI operator handle. + * @param[in] msg message. + * @param[in] msglen byte-length of msg. + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a valid handle. + * @retval UCI_ERROR if msg is NULL while msg_len is not 0 + */ +int uci_md_update(UCI_HANDLE oh, unsigned char *msg, unsigned int msg_len); + +/** + * @brief get hashed message + * @param[in] oh UCI operator handle + * @param[out] output hashed message. + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a valid handle. + * @retval UCI_ERROR If operate failed. Such as output is NULL. + */ +int uci_md_final(UCI_HANDLE oh, unsigned char * output); + +/** + * @brief get hashed message from message + * @param[in] oh UCI operator handle + * @param[in] msg message + * @param[in] msglen byte-length of msg + * @param[out] output hashed message. + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a valid handle. + * @retval UCI_ERROR if output is NULL. + */ +int uci_md_get_hash(UCI_HANDLE oh, unsigned char *msg, unsigned int msg_len, + unsigned char * output); + +/** + * @brief Parameter setting for mac code generation + * @param[in] oh uci handle + * @param[in] key user key + * @param[in] key_len byte-length of key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if key is NULL or key_len is not equal to 16. + */ +int uci_mac_init(UCI_HANDLE oh, unsigned char *key, unsigned int key_len); + +/** + * @brief process data blocks + * @param[in] oh uci handle + * @param[in] msg data block + * @param[in] msg_len byte-length of Text + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if msg is NULL. + */ +int uci_mac_update(UCI_HANDLE oh, unsigned char *msg, unsigned int msg_len); + +/** + * @brief process last data block + * @param[in] oh uci handle + * @param[out] output generated MAC + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if output is NULL. + */ +int uci_mac_final(UCI_HANDLE oh, unsigned char *output, + unsigned int *output_len); + +/** + * @brief generate c-mac code + * @param[in] oh UCI handle + * @param[in] key user key + * @param[in] key_len byte-length of Key + * @param[in] msg data block + * @param[in] msg_len byte-length of Text + * @param[out] utput generated MAC + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR Other error. such key is NULL or msg is NULL. + */ +int uci_mac_get_mac(UCI_HANDLE oh, unsigned char *key, unsigned int key_len, + unsigned char * msg, unsigned int msg_len, unsigned char * output, + unsigned int * output_len); + +/** + * @brief initialize crypt context for symmetric cryptography + * @param[in] oh UCI handle + * @param[in] mode encryption|decryption and mode of operation + * @param[in] padding padding method + * @param[in] key user key + * @param[in] key_len byte-length of key + * @param[in] iv initial vector + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_INVALID_ARGUMENT if one or moer parameter is ininvalid. + * @retval UCI_ERROR if key is null. iv is null is invalid. + */ +int uci_se_init(UCI_HANDLE oh, unsigned int mode, unsigned padding, + unsigned char *key, unsigned int key_len, unsigned char * iv); + +/** + * @brief process message block + * @param[in] oh UCI handle + * @param[in] input message block + * @param[in] input_len byte-length of Text + * @param[out] output proecessed message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if output is NULL while input is not NULL. + */ +int uci_se_process(UCI_HANDLE oh, unsigned char * input, unsigned int input_len, + unsigned char * output, unsigned int *output_len); + +/*** + * @brief process final block and padding + * @param[in] oh UCI handle + * @param[in] input message block + * @param[in] input_len byte-length of Text + * @param[in] output processed message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if output is NULL while input is not NULL.. + */ +int uci_se_final(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char * output, unsigned int *output_len); + +/** + * @brief Encrypt one block + * @param[in] oh UCI handle + * @param[in] cipher_tex encrypted text + * @param[in] plain_text plain text + * @param[in] user_key user key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR cipher_text,plain_text or user_key is NULL. + */ +int uci_se_encrypt_oneblock(UCI_HANDLE oh, unsigned char *cipher_text, + unsigned char * plain_text, unsigned char *user_key); + +/** + * @brief Decrypt one block + * @param[in] oh UCI handle + * @param[in] cipher_text encrypted text + * @param[out] plain_text plain text + * @param[in] user_key user key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR cipher_text,plain_text or user_key is NULL. + */ +int uci_se_decrypt_oneblock(UCI_HANDLE oh, unsigned char * plain_text, + unsigned char *cipher_text, unsigned char* user_key); + +/** + * @brief initialize crypt context for symmetric cryptography in whitebox aes + * @param[in] oh UCI handle + * @param[in] flag if flag is 1 means table was encrypted, and key is used to decrypt table. else key is set NULL. + * @param[in] key key used to decrypt table + * @param[in] table_filepath the file path where table stored. + * @param[in] pencoder1 encoder instance + * @param[in] pencoder2 encoder instance + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR such as if flag is 1 while key is NULL. and table_filepath is NULL will also return UCI_ERROR. + */ +int uci_wbse_init(UCI_HANDLE oh, int flag, unsigned char *key, + char * table_filepath, void*pencoder1, void *pencoder2); + +/** + * @brief Encrypt message with whitebox aes + * @param[in] oh UCI handle + * @param[in] input text need to encrypt or decrypt + * @param[in] input_len input textlen + * @param[out] output processed output data. + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR such as input , output is NULL. + */ +int uci_wbse_final(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char * output, unsigned int output_len); + +/** + * @brief generate DH or DSA param + * @param[in] oh UCI handle + * @param[out] param parameter structure + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_INVALID_ARGUMENT if param is NULL. + * @retval UCI_ERROR other error occured. + */ +int uci_ae_gen_param(UCI_HANDLE oh, uci_param_s *param, unsigned int size); + +/** + * @brief generate key pair + * @param[in] oh UCI handle + * @param[in] keymaterial key pair structure + * @param[in] param parameter structure + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR If keymaterial is ininvalid. except whiteboxRSA, param should not be NULL. + */ +int uci_ae_gen_keypair(UCI_HANDLE oh, uci_key_s* keymaterial, + uci_param_s* param); + +/** + * @brief generate key pair + * @param[in] oh UCI handle + * @param[in] keymaterial key pair structure + * @param[in] param parameter structure + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is ininvalid handle. + * @retval UCI_ERROR if keymaterial is not invalid. param is not invalid(except whitebox rsa). + + */ +int uci_ae_set_keypair(UCI_HANDLE oh, uci_key_s* keymaterial, + uci_param_s *param); + +/** + * @brief RSA Encryption + * @param[in] oh UCI handle + * @param[in] input message to encrypt + * @param[in] input_len byte-length of input + * @param[out] output encrypted message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is ininvalid handle. + * @retval UCI_MSG_TOO_LONG the input_len is too long. The correct usage is that input_len shorter than key length. + * @retval UCI_ERROR input or output is NULL.. + */ +int uci_ae_encrypt(UCI_HANDLE oh, unsigned char * input, unsigned int input_len, + unsigned char * output, unsigned int* output_len); + +/** + * @brief RSA Decryption + * @param[in]oh UCI handle + * @param[in]input message to decrypt + * @param[in]input_len byte-length of input + * @param[out]output decrypted message + * @param[out]output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_MSG_TOO_LONG the input_len is too long. The correct usage is that input_len shorter than key length. + * @retval UCI_ERROR input or output is NULL. + */ +int uci_ae_decrypt(UCI_HANDLE oh, unsigned char * input, unsigned int input_len, + unsigned char * output, unsigned int* output_len); + +/** + * @brief RSA Decryption using CRT + * @param[in]oh UCI handle + * @param[in]input message to decrypt + * @param[in]input_len byte-length of input + * @param[out]output decrypted message + * @param[out]output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_MSG_TOO_LONG the input_len is too long. The correct usage is that input_len shorter than key length. + * @retvla UCI_ERROR input or output is NULL. + */ +int uci_ae_decryptbycrt(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int* output_len); + +/** + * @brief whitebox rsa encryption + * @param[in]oh UCI handle + * @param[in]input message to decrypt + * @param[in]input_len byte-length of input + * @param[out]output decrypted message + * @param[out]output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retvla UCI_ERROR other error occured.if input, output, output_len is NULL. + */ +int uci_wbae_encrypt(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int* output_len); + +/** + * @brief whitebox rsa decryption + * @param[in] oh UCI handle + * @param[in] input message to decrypt + * @param[in] input_len byte-length of input + * @param[out] output decrypted message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR other error occured. if input, output, output_len is NULL. + */ +int uci_wbae_decrypt(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int* output_len); + +/** + * @brief generate signature for given value + * @param[in]oh UCI handle + * @param[in]hash hash value + * @param[in]hash_len byte-length of hash + * @param[out]signature generated signature + * @param[out]sign_len byte-length of signature + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_MSG_TOO_LONG the input_len is too long. The correct usage is that input_len shorter than key length. + * @retval UCI_ERROR if hash or signature is NULL. + */ +int uci_ds_sign(UCI_HANDLE oh, unsigned char * hash, unsigned int hash_len, + unsigned char * signature, unsigned int* sign_len); + +/** + * @brief generate signature for given value + * @param[in] oh UCI handle + * @param[in] hash hash value to signature. + * @param[in] hash_len byte-length of hash + * @param[in] signature result of signatured value. + * @param[in] sign_len byte-length of signature + * @param[out] result result of verifying signature + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_MSG_TOO_LONG the input_len is too long. The correct usage is that input_len shorter than key length. + * @retval UCI_ERROR If hash or signature is NULL. + */ +int uci_ds_verify(UCI_HANDLE oh, unsigned char * hash, unsigned int hash_len, + unsigned char * signature, unsigned int sign_len, int * result); + +/** + * @brief generate xk and its xv + * @param[in] oh UCI handle + * @param[out] pch_xk Generated Random Number + * @param[out] pch_xv DH 1st phase value + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if pch_xk or pch_xv is NULL; and the length of pch_xv should be more than 40 bytes. The length of pch_xk should be more than 20 bytes. + */ +int uci_dh_gen_phasekey(UCI_HANDLE oh, unsigned char*pch_xk, + unsigned char*pch_xv, uci_param_s * param); + +/** + * @brief genenrate auth key with Xk and Yv + * @param[in] oh UCI handle + * @param[in] pch_xk Generated Random Number + * @param[in] pch_yv DH 1st phase value + * @param[out] pch_kauth authentication key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR if pch_xk, pch_xv and pch_kauth should be not NULL. and the length of pch_kauth should be longer than 20. + */ +int uci_dh_gen_authkey(UCI_HANDLE oh, unsigned char*pch_xk, + unsigned char*pch_xv, unsigned char *pch_kauth); + +/** + * @brief Seed RNG System + * @param[in] oh UCI handle + * @param[in] seed seed for RNG System + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR other error occured.If seed is NULL. and user should ensure length of seed should be at least 16 bytes, because cryptocore module need seed is 16 bytes. + */ +int uci_prng_seed(UCI_HANDLE oh, unsigned char * seed); + +/** + * @brief generate random number + * @param[in] oh UCI handle + * @param[in] bit_length bit length for generated number + * @param[out] data generated data + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is invalid handle. + * @retval UCI_ERROR other error occured.if data is NULL. + */ +int uci_prng_get(UCI_HANDLE oh, unsigned int bit_len, unsigned char *data); + +int uci_dup_handle(UCI_HANDLE srcoh, UCI_HANDLE destoh); +int uci_authcrypt_init(UCI_HANDLE oh, unsigned int mode, unsigned char *nonce, + unsigned int nonce_len, unsigned int tag_len, unsigned int aad_len, + unsigned int payload_len, unsigned char *key, unsigned int key_len); +int uci_authcrypt_update_aad(UCI_HANDLE oh, unsigned char *aad, + unsigned int aad_len); +int uci_authcrypt_update(UCI_HANDLE oh, unsigned char *src, + unsigned int src_len, unsigned char *dest, unsigned int *dest_len); +int uci_authcrypt_encryptfinal(UCI_HANDLE oh, unsigned char *src, + unsigned int src_len, unsigned char *dest, unsigned int *dest_len, + unsigned char *tag, unsigned int *tag_len); + +int uci_authcrypt_decryptfinal(UCI_HANDLE oh, unsigned char *src, + unsigned int src_len, unsigned char *dest, unsigned int *dest_len, + unsigned char *tag, unsigned int tag_len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +/** @}*/ + +#endif + diff --git a/ssflib/dep/uci/include/uci_cryptocore.h b/ssflib/dep/uci/include/uci_cryptocore.h new file mode 100755 index 0000000..ab40685 --- /dev/null +++ b/ssflib/dep/uci/include/uci_cryptocore.h @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_cryptocore.h + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.7 + **/ +#ifndef _UCI_CRYPTOCORE_H +#define _UCI_CRYPTOCORE_H +#include "uci_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief allocates memory and initializes the cryptographic context structure, and return the crypto handle.. + * + * @param[in] algorithm, algorithm wants to use. + * @retval UCI handle if success + * @retval UCI_ERROR if fail + */ +UCI_HANDLE cryptocore_context_alloc(unsigned int algorithm); +/** + * @brief free allocated memory. + * + * @param[in] algorithm algorithm wants to use. + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a valid handle. + */ +int cryptocore_context_free(UCI_HANDLE oh); + +/** + * @brief Digest initialization. + * + * @param[in] oh UCI handle + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a valid handle. + */ +int cryptocore_md_init(UCI_HANDLE oh); + +/** + * @brief process a message block + * @param[in] oh UCI operator handle. + * @param[in] msg message. + * @param[in] msglen byte-length of msg. + * @UCI_SUCCESS If no error occurred. + * @UCI_INVALID_HANDLE If oh is not a valid handle. + */ +int cryptocore_md_update(UCI_HANDLE oh, unsigned char *msg, + unsigned int msg_len); + +/** + * @brief get hashed message + * @param[in] oh UCI operator handle + * @param[out] output hashed message. + * @ retval UCI_SUCCESS If no error occurred. + * @ retval UCI_INVALID_HANDLE If oh is not a valid handle. + */ + +int cryptocore_md_final(UCI_HANDLE oh, unsigned char * output); + +/** + * @brief get hashed message from message + * @param[in] oh UCI operator handle + * @param[in] msg message + * @param[in] msglen byte-length of msg + * @param[out] output hashed message. + * @ retval UCI_SUCCESS If no error occurred. + * @ retval UCI_INVALID_HANDLE If oh is not a valid handle. + */ + +int cryptocore_md_get_hash(UCI_HANDLE oh, unsigned char *msg, + unsigned int msg_len, unsigned char * output); + +/** + * @brief Parameter setting for mac code generation + * @param[in] oh uci handle + * @param[in] key user key + * @param[in] key_len byte-length of key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_MEMORY_ALLOC_FAIL if memory allocation is failed. + */ + +int cryptocore_mac_init(UCI_HANDLE oh, unsigned char *key, + unsigned int key_len); + +/** + * @brief process data blocks + * @param[in] oh uci handle + * @param[in] msg data block + * @param[in] msg_len byte-length of Text + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR if other error occured. + */ + +int cryptocore_mac_update(UCI_HANDLE oh, unsigned char *msg, + unsigned int msg_len); + +/** + * @brief process last data block + * @param[in] oh uci handle + * @param[out] output generated MAC + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_mac_final(UCI_HANDLE oh, unsigned char *output, + unsigned int *output_len); + +/** + * @brief generate c-mac code + * @param[in] oh UCI handle + * @param[in] key user key + * @param[in] key_len byte-length of Key + * @param[in] msg data block + * @param[in] msg_len byte-length of Text + * @param[out] utput generated MAC + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_mac_getmac(UCI_HANDLE oh, unsigned char *key, + unsigned int key_len, unsigned char * msg, unsigned int msg_len, + unsigned char * output, unsigned int * output_len); + +/** + * @brief initialize crypt context for symmetric cryptography + * @param[in] oh UCI handle + * @param[in] mode encryption|decryption and mode of operation + * @param[in] padding padding method + * @param[in] key user key + * @param[in] key_len byte-length of key + * @param[in] iv initial vector + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_se_init(UCI_HANDLE oh, unsigned int mode, unsigned padding, + unsigned char *key, unsigned int key_len, unsigned char * iv); +/** + * @brief process message block + * @param[in] oh UCI handle + * @param[in] input message block + * @param[in] input_len byte-length of Text + * @param[out] output proecessed message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_se_process(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int *output_len); + +/** + * @brief process final block and padding + * @param[in] oh UCI handle + * @param[in] input message block + * @param[in] input_len byte-length of Text + * @param[in] output processed message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_se_final(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char * output, unsigned int *output_len); + +/** + * @brief Encrypt one block + * @param[in] oh UCI handle + * @param[in] cipher_tex encrypted text + * @param[in] plain_text plain text + * @param[in] user_key user key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_se_encrypt_oneblock(UCI_HANDLE oh, unsigned char *cipher_text, + unsigned char * plain_text, unsigned char *user_key); + +/** + * @brief Decrypt one block + * @param[in] oh UCI handle + * @param[in] cipher_text encrypted text + * @param[out] plain_text plain text + * @param[in] user_key user key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_se_decrypt_oneblock(UCI_HANDLE oh, unsigned char * plain_text, + unsigned char *cipher_text, unsigned char* user_key); + +/** + * @brief generate DH or DSA param + * @param[in] oh UCI handle + * @param[out] param parameter structure + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_INVALID_ARGUMENT if param is NULL. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_ae_gen_param(UCI_HANDLE oh, uci_param_s *param, + unsigned int size); + +/** + * @brief generate key pair + * @param[in] oh UCI handle + * @param[in] keymaterial key pair structure + * @param[in] param parameter structure + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_ae_gen_keypair(UCI_HANDLE oh, uci_key_s* keymaterial, + uci_param_s* param); + +/** + * @brief generate key pair + * @param[in] oh UCI handle + * @param[in] keymaterial key pair structure + * @param[in] param parameter structure + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_ae_set_keypair(UCI_HANDLE oh, uci_key_s* keymaterial, + uci_param_s* param); + +/** + * @brief RSA Encryption + * @param[in] oh UCI handle + * @param[in] input message to encrypt + * @param[in] input_len byte-length of input + * @param[out] output encrypted message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int cryptocore_ae_encrypt(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int* output_len); + +/** + * @brief RSA Decryption + * @param[in]oh UCI handle + * @param[in]input message to decrypt + * @param[in]input_len byte-length of input + * @param[out]output decrypted message + * @param[out]output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_ae_decrypt(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int* output_len); + +/** + * @brief RSA Decryption using CRT + * @param[in]oh UCI handle + * @param[in]input message to decrypt + * @param[in]input_len byte-length of input + * @param[out]output decrypted message + * @param[out]output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retvla UCI_ERROR other error occured. + */ +int cryptocore_ae_decryptbycrt(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int* output_len); + +/** + * @brief generate signature for given value + * @param[in]oh UCI handle + * @param[in]hash hash value + * @param[in]hash_len byte-length of hash + * @param[out]signature generated signature + * @param[out]sign_len byte-length of signature + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_ds_sign(UCI_HANDLE oh, unsigned char * hash, + unsigned int hash_len, unsigned char * signature, unsigned int* sign_len); + +/** + * @brief generate signature for given value + * @param[in] oh UCI handle + * @param[in] hash hash value to signature. + * @param[in] hash_len byte-length of hash + * @param[in] signature result of signatured value. + * @param[in] sign_len byte-length of signature + * @param[out] result result of verifying signature + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_ds_verify(UCI_HANDLE oh, unsigned char * hash, + unsigned int hash_len, unsigned char * signature, unsigned int sign_len, + int * result); + +/** + * @brief generate xk and its xv + * @param[in] oh UCI handle + * @param[out] pch_xk Generated Random Number + * @param[out] pch_xv DH 1st phase value + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_dh_gen_dh1stphasekey(UCI_HANDLE oh, unsigned char*pch_xk, + unsigned char*pch_xv, uci_param_s * param); + +/** + * @brief genenrate auth key with Xk and Yv + * @param[in] oh UCI handle + * @param[in] pch_xk Generated Random Number + * @param[in] pch_yv DH 1st phase value + * @param[out] pch_kauth authentication key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_dh_gen_dhkey(UCI_HANDLE oh, unsigned char*pch_xk, + unsigned char*pch_xv, unsigned char *pch_kauth); + +/** + * @brief Seed RNG System + * @param[in] oh UCI handle + * @param[in] seed seed for RNG System + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_prng_seed(UCI_HANDLE oh, unsigned char * seed); + +/** + * @brief generate random number + * @param[in] oh UCI handle + * @param[in] bit_length bit length for generated number + * @param[out] data generated data + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int cryptocore_prng_get(UCI_HANDLE oh, unsigned int bit_len, + unsigned char *data); +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssflib/dep/uci/include/uci_hwcrypto.h b/ssflib/dep/uci/include/uci_hwcrypto.h new file mode 100755 index 0000000..02a7710 --- /dev/null +++ b/ssflib/dep/uci/include/uci_hwcrypto.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_hwcrypto.h + * @brief hwcrypto codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.7 + **/ +#ifndef _UCI_HWCRYPTO_H +#define _UCI_HWCRYPTO_H +#include "uci_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief allocates memory and initializes the cryptographic context structure, and return the crypto handle.. + * + * @param[in] algorithm, algorithm wants to use. + * @retval UCI handle if success + * @retval UCI_ERROR if fail + */ +UCI_HANDLE hwcrypto_context_alloc(unsigned int algorithm, + uci_engine_config_e config); + +/** + * @brief free allocated memory. + * + * @param[in] algorithm algorithm wants to use. + * @retval UCI_SUCCESS If no error occurred. + * @retval UCI_INVALID_HANDLE If oh is not a valid handle. + */ +int hwcrypto_context_free(UCI_HANDLE oh); +/** + * @brief initialize crypt context for symmetric cryptography + * @param[in] oh UCI handle + * @param[in] mode encryption|decryption and mode of operation + * @param[in] padding padding method + * @param[in] key user key + * @param[in] key_len byte-length of key + * @param[in] iv initial vector + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int hwcrypto_se_init(UCI_HANDLE oh, unsigned int mode, unsigned int padding, + unsigned char *key, unsigned int key_len, unsigned char * iv); +/** + * @brief process message block + * @param[in] oh UCI handle + * @param[in] input message block + * @param[in] input_len byte-length of Text + * @param[out] output proecessed message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +int hwcrypto_se_process(UCI_HANDLE oh, unsigned char * input, + unsigned int input_len, unsigned char * output, unsigned int *output_len); + +/*** + * @brief process final block and padding + * @param[in] oh UCI handle + * @param[in] input message block + * @param[in] input_len byte-length of Text + * @param[in] output processed message + * @param[out] output_len byte-length of output + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ +int hwcrypto_se_final(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char * output, unsigned int *output_len); + +/** + * @brief Encrypt one block + * @param[in] oh UCI handle + * @param[in] cipher_tex encrypted text + * @param[in] plain_text plain text + * @param[in] user_key user key + * @retval UCI_SUCCESS if no error is occured. + * @retval UCI_INVALID_HANDLE if oh is valid handle. + * @retval UCI_ERROR other error occured. + */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/ssflib/dep/uci/include/uci_internal.h b/ssflib/dep/uci/include/uci_internal.h new file mode 100755 index 0000000..c1bb305 --- /dev/null +++ b/ssflib/dep/uci/include/uci_internal.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_internal.h + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.7 + **/ +#ifndef _UCI_INTERNAL_H +#define _UCI_INTERNAL_H + +#include "uci_type.h" +#include + +typedef struct uci_context { + unsigned int alg; + unsigned int config; + unsigned int flag; //(hwcrypt)if flag equal to 1, means encrypt. else flag equal to 0, means decrypt. flag == ID_UCI_ENC_CTS (ID_UCI_DEC_CTS) + int handle; + void* imp; +} uci_context_s; + +#endif + diff --git a/ssflib/dep/uci/include/uci_type.h b/ssflib/dep/uci/include/uci_type.h new file mode 100755 index 0000000..f3c8843 --- /dev/null +++ b/ssflib/dep/uci/include/uci_type.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_type.h + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.7 + **/ +#ifndef _UCI_TYPE_H +#define _UCI_TYPE_H + +#include "OsaLinuxUser.h" + +/** + * @addtogroup g_uci + * @{ + */ + +/** + * @brief UCI handle. + * + */ +typedef int UCI_HANDLE; +/** + * @brief UCI return error type. + * + */ + +#define UCI_SUCCESS 0 /**< no error is occured */ +#define UCI_ERROR -3000 /**< error is occured */ +#define UCI_MEM_ALLOR_ERROR -3001 /**< malloc is failed */ +#define UCI_INVALID_ARGUMENT -3003 /**< argument is not correct */ +#define UCI_MSG_TOO_LONG -3004 /**< length of input message is too long */ +#define UCI_INVALID_HANDLE -3005 /**< hand is not valid */ +#define UCI_VALID_SIGN UCI_SUCCESS /**< valid sign */ +#define UCI_INVALID_SIGN -3011 /**< invalid sign */ + +#define SDRM_SHIFT_HALF 16 /**< common value at both of 32-bit and 64-bit machine */ +#define SDRM_HIGH_HALF(A) ((A) >> SDRM_SHIFT_HALF) +#define SDRM_LOW_HALF(A) ((A) & ((1 << SDRM_SHIFT_HALF) - 1)) + +//////////////////////////////////////////////////////////////////////////// +// Algorithm Identifier (To be update) +//////////////////////////////////////////////////////////////////////////// +enum UCICryptoAlgorithm { + /*! \brief RNG Module */ + ID_UCI_X931 = 1011, + + /*! \brief Hash Algorithms */ + ID_UCI_MD5 = 1021, + ID_UCI_SHA1 = 1022, + ID_UCI_SHA160 = 1022, + ID_UCI_SHA256 = 1023, +#ifndef _OP64_NOTSUPPORTED + ID_UCI_SHA384 = 1024, + ID_UCI_SHA512 = 1025, +#endif //_OP64_NOTSUPPORTED + ID_UCI_SHA224 = 1026, + + /*! \brief MAC Algorithms */ + ID_UCI_CMAC = 1031, + ID_UCI_HMD5 = 1032, + ID_UCI_HSHA1 = 1033, + ID_UCI_HSHA160 = 1033, + ID_UCI_HSHA256 = 1034, +#ifndef _OP64_NOTSUPPORTED + ID_UCI_HSHA384 = 1035, + ID_UCI_HSHA512 = 1036, +#endif //_OP64_NOTSUPPORTED + ID_UCI_HSHA224 = 1037, + ID_UCI_XCBCMAC = 1038, + /*! \brief Symmetric Encryption Algorithms */ + ID_UCI_AES = 1041, + ID_UCI_AES128 = 1041, + ID_UCI_AES192 = 1047, + ID_UCI_AES256 = 1048, + ID_UCI_DES = 1042, + ID_UCI_TDES = 1043, + ID_UCI_TDES_EDE2 = 1043, + ID_UCI_TDES_EDE3 = 1044, + ID_UCI_RC4 = 1045, + ID_UCI_SNOW2 = 1046, + + /*! \brief Asymmetric Encryption Algorithms */ + ID_UCI_RSA = 1051, + ID_UCI_RSA512 = 1057, + ID_UCI_RSA1024 = 1054, + ID_UCI_RSA2048 = 1055, + ID_UCI_RSA3072 = 1056, + ID_UCI_ELGAMAL = 1052, + ID_UCI_ECELGAMAL = 1053, + + /*! \brief Signature Algorithms */ + ID_UCI_DSA = 1061, + ID_UCI_ECDSA = 1062, + + /*! \brief Key Exchange Algorithms */ + ID_UCI_DH = 1071, + ID_UCI_ECDH = 1072, + /*! \brief WhitBox Algorithms */ + ID_UCI_WBENC_AES = 1081, + ID_UCI_WBDEC_AES = 1082, + ID_UCI_WBRSA512 = 1083, + ID_UCI_WBRSA1024 = 1084, + ID_UCI_WBRSA2048 = 1085, + + /*! \brief Encryption/Decryption Mode of Operations */ + ID_UCI_ENC_ECB = 1111, + ID_UCI_ENC_CBC = 1112, + ID_UCI_ENC_CFB = 1113, + ID_UCI_ENC_OFB = 1114, + ID_UCI_ENC_CTR = 1115, + ID_UCI_ENC_CTS = 1116, + + ID_UCI_DEC_ECB = 1121, + ID_UCI_DEC_CBC = 1122, + ID_UCI_DEC_CFB = 1123, + ID_UCI_DEC_OFB = 1124, + ID_UCI_DEC_CTR = 1125, + ID_UCI_DEC_CTS = 1126, + + /*! \brief Symmetric Encryption/Decryption Padding Methods */ + ID_UCI_PKCS5 = 1201, + ID_UCI_SSL_PADDING = 1202, + ID_UCI_ZERO_PADDING = 1203, + ID_UCI_NO_PADDING = 1204, + + /*! \brief Asymmetric Encryption/Decryption Padding Methods */ + ID_UCI_RSAES_PKCS15 = 1131, + + ID_UCI_RSAES_OAEP = 1132, + ID_UCI_RSAES_OAEP_MD5 = ID_UCI_RSAES_OAEP + (ID_UCI_MD5 << SDRM_SHIFT_HALF), + ID_UCI_RSAES_OAEP_SHA1 = ID_UCI_RSAES_OAEP + (ID_UCI_SHA1 << SDRM_SHIFT_HALF), + ID_UCI_RSAES_OAEP_SHA160 = ID_UCI_RSAES_OAEP + + (ID_UCI_SHA160 << SDRM_SHIFT_HALF), + ID_UCI_RSAES_OAEP_SHA224 = ID_UCI_RSAES_OAEP + + (ID_UCI_SHA224 << SDRM_SHIFT_HALF), + ID_UCI_RSAES_OAEP_SHA256 = ID_UCI_RSAES_OAEP + + (ID_UCI_SHA256 << SDRM_SHIFT_HALF), +#ifndef _OP64_NOTSUPPORTED + ID_UCI_RSAES_OAEP_SHA384 = ID_UCI_RSAES_OAEP + + (ID_UCI_SHA384 << SDRM_SHIFT_HALF), + ID_UCI_RSAES_OAEP_SHA512 = ID_UCI_RSAES_OAEP + + (ID_UCI_SHA512 << SDRM_SHIFT_HALF), +#endif + + ID_UCI_RSASSA_PKCS15 = 1133, + ID_UCI_RSASSA_PKCS15_MD5 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_MD5 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PKCS15_SHA1 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_SHA1 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PKCS15_SHA160 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_SHA160 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PKCS15_SHA224 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_SHA224 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PKCS15_SHA256 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_SHA256 << SDRM_SHIFT_HALF), +#ifndef _OP64_NOTSUPPORTED + ID_UCI_RSASSA_PKCS15_SHA384 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_SHA384 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PKCS15_SHA512 = ID_UCI_RSASSA_PKCS15 + + (ID_UCI_SHA512 << SDRM_SHIFT_HALF), +#endif + + ID_UCI_RSASSA_PSS = 1134, + ID_UCI_RSASSA_PSS_MD5 = ID_UCI_RSASSA_PSS + (ID_UCI_MD5 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PSS_SHA1 = ID_UCI_RSASSA_PSS + (ID_UCI_SHA1 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PSS_SHA160 = ID_UCI_RSASSA_PSS + + (ID_UCI_SHA160 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PSS_SHA224 = ID_UCI_RSASSA_PSS + + (ID_UCI_SHA224 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PSS_SHA256 = ID_UCI_RSASSA_PSS + + (ID_UCI_SHA256 << SDRM_SHIFT_HALF), +#ifndef _OP64_NOTSUPPORTED + ID_UCI_RSASSA_PSS_SHA384 = ID_UCI_RSASSA_PSS + + (ID_UCI_SHA384 << SDRM_SHIFT_HALF), + ID_UCI_RSASSA_PSS_SHA512 = ID_UCI_RSASSA_PSS + + (ID_UCI_SHA512 << SDRM_SHIFT_HALF), +#endif + /*!\brief Authenticated Encryption Functions */ + ID_UCI_AE_GCM = 1091, + ID_UCI_AE_CCM = 1092 + +}; + +/** @HW engine key type */ + +typedef enum { + + UCI_USER_KEY = 1, UCI_SECRET_KEY = 2, UCI_MASTER_KEY = 3 +} hw_keytype_e; + +/** @crypto types uci supported */ +typedef enum uci_engine_config { + UCI_SW = 2001, UCI_SW_CRYPTOCORE = 2001, UCI_SW_OPENSSL = 2002, UCI_HW = 2003, //SHOULD NOT USED + UCI_WB = 2004, + + UCI_HW_USER_KEY = UCI_HW + (UCI_USER_KEY << SDRM_SHIFT_HALF), + UCI_HW_SECRET_KEY = UCI_HW + (UCI_SECRET_KEY << SDRM_SHIFT_HALF), + UCI_HW_MASTER_KEY = UCI_HW + (UCI_MASTER_KEY << SDRM_SHIFT_HALF) +} uci_engine_config_e; + +/** + * @brief RSA key strucsture. + * + * Including private key an public key + */ +typedef struct rsa_key { + unsigned char* n; /**< RSA public component of key.*/ + unsigned int n_len; /**< RSA public component size of key.*/ + unsigned char* e; /**< RSA public component of key.*/ + unsigned int e_len; /**< RSA public component size of key.*/ + unsigned char* d; /**< RSA private component key.*/ + unsigned int d_len; /**< RSA private component key size.*/ +} rsa_key_s; + +/** + * @brief dsa key strucsture. + * + * Including private key an public key + */ + +typedef struct dsa_key { + unsigned char* ydata; /**< DSA public of key.*/ + unsigned int ydata_len; /**< DSA size of public key.*/ + unsigned char* xdata; /**< DSA private key.*/ + unsigned int xdata_len; /**< DSA key private size.*/ +} dsa_key_s; + +/** + * @brief ecc key strucsture. + * + * Including private key an public key + */ +typedef struct ecc_key { + unsigned char* privatekey; + unsigned int privatekey_len; + unsigned char* publickey_x; + unsigned int publickey_x_len; + unsigned char* publickey_y; + unsigned int publickey_y_len; +} ecc_key_s; + +/** + * @brief DH key structure + * + * Including key buf and length. + */ +typedef struct dh_key { + unsigned char* privatekey; + unsigned int privatekey_len; + unsigned char* publickey; + unsigned int publickey_len; + +} dh_key_s; +/** + * @brief imp key union. + * + *Including rsa key structure , dsa key structure, ecc key structure. + */ +typedef union uci_impkey { + rsa_key_s rkey; + dsa_key_s dkey; + ecc_key_s ekey; + dh_key_s dhkey; +} uci_impkey_u; + +/** + * @brief UCI key strucsture. + * + * ECC, DSA and RSA algorithm generate key will use this structure. + */ +typedef struct uci_key { + uci_impkey_u imp; + + /*rsa*/ +#define ucik_rsa_n imp.rkey.n +#define ucik_rsa_e imp.rkey.e +#define ucik_rsa_d imp.rkey.d +#define ucik_rsa_n_len imp.rkey.n_len +#define ucik_rsa_e_len imp.rkey.e_len +#define ucik_rsa_d_len imp.rkey.d_len + + /*dsa*/ +#define ucik_dsa_privkey imp.dkey.xdata +#define ucik_dsa_pubkey imp.dkey.ydata +#define ucik_dsa_privk_len imp.dkey.xdata_len +#define ucik_dsa_pubk_len imp.dkey.ydata_len + + /*ecc*/ +#define ucik_ecc_privkey imp.ekey.privatekey +#define ucik_ecc_pubkey_x imp.ekey.publickey_x +#define ucik_ecc_pubkey_y imp.ekey.publickey_y +#define ucik_ecc_privk_len imp.ekey.privatekey_len +#define ucik_ecc_pubkx_len imp.ekey.publickey_x_len +#define ucik_ecc_pubky_len imp.ekey.publickey_y_len + + /*dh*/ +#define ucik_dh_privkey imp.dhkey.privatekey +#define ucik_dh_prikey_len imp.dhkey.privatekey_len +#define ucik_dh_pubkey imp.dhkey.publickey +#define ucik_dh_pubkey_len imp.dhkey.publickey_len + +} uci_key_s; + +typedef enum rsa_kparam_flag { + RSA_GENKEYWITHNON = 1, RSA_GENKEYWITHE, /* *< Dispaly the sturctut is including e */ + RSA_GENKEYWITHPQE, /* *< Dispaly the sturctut is including pqe */ + RSA_KEYFORCRT, /* *< Dispaly the sturctut for crt */ +} rsa_kparam_flag_e; + +/** + *@brief rsa key param structure + * + */ +typedef struct rsa_param { + rsa_kparam_flag_e flag; + int padding; + unsigned char* e; + unsigned int e_len; + unsigned char* p; + unsigned int p_len; + unsigned char* q; + unsigned int q_len; + unsigned char* dmodp1; + unsigned int dmodp1_len; + unsigned char* dmodq1; + unsigned int dmodq1_len; + unsigned char* iqp; + unsigned int iqp_len; +} uci_rsa_param_s; + +/** + *@brief UCI key param + * + */ +typedef struct ecc_param { + unsigned short dimension; + unsigned char* ecc_p_data; + unsigned int ecc_p_len; + unsigned char* ecc_a_data; + unsigned int ecc_a_len; + unsigned char* ecc_b_data; + unsigned int ecc_b_len; + unsigned char* ecc_g_x_data; + unsigned int ecc_g_x_len; + unsigned char* ecc_g_y_data; + unsigned int ecc_g_y_len; + unsigned char* ecc_r_data; + unsigned int ecc_r_len; +} uci_ecc_param_s; + +/** + *@brief dsa key param + * + */ +typedef struct dsa_param { + unsigned int t_size; + unsigned char* dsa_p_data; + unsigned int dsa_p_len; + unsigned char* dsa_q_data; + unsigned int dsa_q_len; + unsigned char* dsa_g_data; + unsigned int dsa_g_len; +} uci_dsa_param_s; + +/** + *@brief DH key param + * + */ +typedef struct dh_param { + unsigned int len; + unsigned char* prime; + unsigned char* generator; +} uci_dh_param_s; + +/** + *@brief uci key param union + * + */ +typedef union uci_param_imp { + uci_ecc_param_s uep; + uci_dsa_param_s udp; + uci_rsa_param_s urp; + uci_dh_param_s udhp; +} uci_param_imp_u; + +/** + *@brief uci key param structure + * + */ +typedef struct uci_param { + uci_param_imp_u uparam; + /*rsa*/ +#define ucip_rsa_flag uparam.urp.flag +#define ucip_rsa_padding uparam.urp.padding +#define ucip_rsa_e uparam.urp.e +#define ucip_rsa_e_len uparam.urp.e_len +#define ucip_rsa_p uparam.urp.p +#define ucip_rsa_p_len uparam.urp.p_len +#define ucip_rsa_q uparam.urp.q +#define ucip_rsa_q_len uparam.urp.q_len +#define ucip_rsa_dmodp1 uparam.urp.dmodp1 +#define ucip_rsa_dmodp1_len uparam.urp.dmodp1_len +#define ucip_rsa_dmodq1 uparam.urp.dmodq1 +#define ucip_rsa_dmodq1_len uparam.urp.dmodq1_len +#define ucip_rsa_iqmodp uparam.urp.iqp +#define ucip_rsa_iqmodp_len uparam.urp.iqp_len + /*dsa*/ +#define ucip_dsa_flag uparam.udp.flag +#define ucip_dsa_tsize uparam.udp.t_size +#define ucip_dsa_p uparam.udp.dsa_p_data +#define ucip_dsa_q uparam.udp.dsa_q_data +#define ucip_dsa_g uparam.udp.dsa_g_data +#define ucip_dsa_p_len uparam.udp.dsa_p_len +#define ucip_dsa_q_len uparam.udp.dsa_q_len +#define ucip_dsa_g_len uparam.udp.dsa_g_len + /*ecc*/ +#define ucip_ecc_dimension uparam.uep.dimension +#define ucip_ecc_p uparam.uep.ecc_p_data +#define ucip_ecc_a uparam.uep.ecc_a_data +#define ucip_ecc_b uparam.uep.ecc_b_data +#define ucip_ecc_gx uparam.uep.ecc_g_x_data +#define ucip_ecc_gy uparam.uep.ecc_g_y_data +#define ucip_ecc_r uparam.uep.ecc_r_data +#define ucip_ecc_p_len uparam.uep.ecc_p_len +#define ucip_ecc_a_len uparam.uep.ecc_a_len +#define ucip_ecc_b_len uparam.uep.ecc_b_len +#define ucip_ecc_gx_len uparam.uep.ecc_g_x_len +#define ucip_ecc_gy_len uparam.uep.ecc_g_y_len +#define ucip_ecc_r_len uparam.uep.ecc_r_len + + /**/ +#define ucip_dh_prime uparam.udhp.prime +#define ucip_dh_generator uparam.udhp.generator +#define ucip_dh_len uparam.udhp.len + +} uci_param_s; +/** @}*/ + +#endif diff --git a/ssflib/dep/uci/source/uci_aes_xcbc_mac.c b/ssflib/dep/uci/source/uci_aes_xcbc_mac.c new file mode 100755 index 0000000..ae3f3b0 --- /dev/null +++ b/ssflib/dep/uci/source/uci_aes_xcbc_mac.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_hwcrypto.cpp + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2014.3 + **/ +/*according to RFC3566*/ +#include "uci_aes_xcbc_mac.h" +#include +#include "cc_aes.h" + +static unsigned char k1[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; +static unsigned char k2[] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}; +static unsigned char k3[] = {0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; + +int xcbc_init(aes_xcbc_state *xcbc, unsigned char *key, unsigned int keylen) { + /* + + (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret + key K, as follows: + K1 = 0x01010101010101010101010101010101 encrypted with Key K + K2 = 0x02020202020202020202020202020202 encrypted with Key K + K3 = 0x03030303030303030303030303030303 encrypted with Key K + + (2) Define E[0](iv) = 0x00000000000000000000000000000000 + + */ + if (keylen != 16) { + return 0; + } + if (xcbc == NULL) { + return 0; + } + memcpy(xcbc->key, key, 16); + SDRM_AES128_Encryption(xcbc->K[0], k1, xcbc->key); + SDRM_AES128_Encryption(xcbc->K[1], k2, xcbc->key); + SDRM_AES128_Encryption(xcbc->K[2], k3, xcbc->key); + memset(xcbc->key, 0, MAXBLOCKSIZE); + memcpy(xcbc->key, xcbc->K[0], 16); + xcbc->blocksize = 16; + xcbc->buflen = 0; + memset(xcbc->IV, 0, MAXBLOCKSIZE); + return 1; +} +int xcbc_process(aes_xcbc_state *xcbc, unsigned char *in, unsigned int inlen) { + /* + + (3) For each block M[i], where i = 1 ... n-1: + XOR M[i] with E[i-1], then encrypt the result with Key K1, + yielding E[i]. + + */ + unsigned int x; + if (xcbc == NULL) { + return 0; + } + if (xcbc->buflen == 0) { + while (inlen > xcbc->blocksize) { + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= in[x]; + } + SDRM_AES128_Encryption(xcbc->IV, xcbc->IV, xcbc->key); + in += xcbc->blocksize; + inlen -= xcbc->blocksize; + } + } + while (inlen) { + if (xcbc->buflen == xcbc->blocksize) { + SDRM_AES128_Encryption(xcbc->IV, xcbc->IV, xcbc->key); + xcbc->buflen = 0; + } + xcbc->IV[xcbc->buflen++] ^= *in++; + --inlen; + } + return 1; +} +int xcbc_done(aes_xcbc_state *xcbc, unsigned char *out, unsigned int *outlen) { + unsigned int x; + if (xcbc == NULL || out == NULL) { + return 0; + } + /* + (4) + a) If the blocksize of M[n] is 128 bits: + XOR M[n] with E[n-1] and Key K2, then encrypt the result with + Key K1, yielding E[n]. + */ + if (xcbc->buflen == xcbc->blocksize) { + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= xcbc->K[1][x]; + } + } else { + /* + (4) + b) If the blocksize of M[n] is less than 128 bits: + + i) Pad M[n] with a single "1" bit, followed by the number of + "0" bits (possibly none) required to increase M[n]'s + blocksize to 128 bits. + + ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result + with Key K1, yielding E[n]. + + */ + xcbc->IV[xcbc->buflen] ^= 0x80; + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= xcbc->K[2][x]; + } + } + SDRM_AES128_Encryption(out, xcbc->IV, xcbc->key); + if (outlen != NULL) { + *outlen = xcbc->blocksize; + } + return 1; + +} + diff --git a/ssflib/dep/uci/source/uci_api.c b/ssflib/dep/uci/source/uci_api.c new file mode 100755 index 0000000..15cb5fc --- /dev/null +++ b/ssflib/dep/uci/source/uci_api.c @@ -0,0 +1,674 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ +/** + * @file uci_api.cpp + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.9.6 + **/ + +#include "uci_api.h" +#include +#include +#include "uci_cryptocore.h" +#include "uci_internal.h" +#include "uci_hwcrypto.h" +//#include "ae.h" +#include "CC_Context.h" +#include "uci_aes_xcbc_mac.h" + +#if 1 +#define TC_PRINT(fmt...) \ + do { printf(fmt);}while(0) +#else +#define TC_PRINT(fmt...)\ + do {;}while(0) +#endif +/*! \brief print out by byte unit */ +#undef PrintBYTE +#define g_bTAdbug 1 +#define TZ_PRINT(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) +#define TZ_ERROR(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) +#define PrintBYTE(msg, Data, DataLen) { \ + int idx; \ + TC_PRINT("%10s =", msg); \ + for(idx=0; idx<(int)DataLen; idx++) { \ + if((idx!=0) && ((idx%16)==0)) TC_PRINT("\n"); \ + if((idx % 4) == 0) TC_PRINT(" 0x"); \ + TC_PRINT("%.2x", Data[idx]); \ + } \ + TC_PRINT("\n"); \ +} + +UCI_HANDLE uci_context_alloc(unsigned int algorithm, uci_engine_config_e config) { + unsigned int conf = SDRM_LOW_HALF(config); + uci_context_s *ctx; + + if (algorithm < ID_UCI_X931 || algorithm > ID_UCI_AE_CCM) { + return UCI_ERROR; + } +#if 0 + if(algorithm == ID_UCI_AE_GCM) + { + ctx = OsaMalloc(sizeof(uci_context_s)); + ctx->imp = OsaMalloc(sizeof(gcm_context)); + ctx->alg = ID_UCI_AE_GCM; + return (int)ctx; + } + if(algorithm == ID_UCI_AE_CCM) + { + ctx = OsaMalloc(sizeof(uci_context_s)); + ctx->imp = OsaMalloc(sizeof(aes_ccm_context)); + ctx->alg = ID_UCI_AE_CCM; + return (int)ctx; + } +#endif + if (algorithm == ID_UCI_XCBCMAC) { + ctx = (uci_context_s*)OsaMalloc(sizeof(uci_context_s)); + ctx->imp = (aes_xcbc_state *)OsaMalloc(sizeof(aes_xcbc_state)); + ctx->alg = ID_UCI_XCBCMAC; + return (int)ctx; + } + if (conf == UCI_SW_CRYPTOCORE) { + return cryptocore_context_alloc(algorithm); + } + if (conf == UCI_HW) { + return hwcrypto_context_alloc(algorithm, config); + } + + return UCI_ERROR; +} + +int uci_context_free(UCI_HANDLE oh) { + uci_context_s *pctx = (uci_context_s*)oh; + unsigned int conf; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + conf = SDRM_LOW_HALF(pctx->config); + if (pctx->alg == ID_UCI_AE_GCM || pctx->alg == ID_UCI_AE_CCM + || pctx->alg == ID_UCI_XCBCMAC) { + OsaFree(pctx->imp); + OsaFree(pctx); + return UCI_SUCCESS; + } + if (conf == UCI_SW_CRYPTOCORE) { + return cryptocore_context_free(oh); + } + if (conf == UCI_HW) { + return hwcrypto_context_free(oh); + } + return UCI_ERROR; +} + +int uci_md_init(UCI_HANDLE oh) { + + return cryptocore_md_init(oh); + +} + +int uci_md_update(UCI_HANDLE oh, unsigned char *msg, unsigned int msg_len) { + return cryptocore_md_update(oh, msg, msg_len); + +} + +int uci_md_final(UCI_HANDLE oh, unsigned char *output) { + return cryptocore_md_final(oh, output); +} + +int uci_md_get_hash(UCI_HANDLE oh, unsigned char *msg, unsigned int msg_len, + unsigned char *output) { + + if (output == NULL) { + return UCI_ERROR; + } + return cryptocore_md_get_hash(oh, msg, msg_len, output); + +} + +int uci_mac_init(UCI_HANDLE oh, unsigned char *key, unsigned int key_len) { + int ret = 0; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx->alg == ID_UCI_XCBCMAC) { + ret = xcbc_init((aes_xcbc_state *)(pctx->imp), key, key_len); + if (ret != 1) { + return UCI_ERROR; + } else { + return UCI_SUCCESS; + } + } + return cryptocore_mac_init(oh, key, key_len); +} + +int uci_mac_update(UCI_HANDLE oh, unsigned char *msg, unsigned int msg_len) { + int ret = 0; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx->alg == ID_UCI_XCBCMAC) { + ret = xcbc_process((aes_xcbc_state*)(pctx->imp), msg, msg_len); + if (ret != 1) { + return UCI_ERROR; + } else { + return UCI_SUCCESS; + } + } + + return cryptocore_mac_update(oh, msg, msg_len); +} + +int uci_mac_final(UCI_HANDLE oh, unsigned char *output, + unsigned int *output_len) { + int ret = 0; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx->alg == ID_UCI_XCBCMAC) { + ret = xcbc_done((aes_xcbc_state*)(pctx->imp), output, output_len); + if (ret != 1) { + return UCI_ERROR; + } else { + return UCI_SUCCESS; + } + } + + return cryptocore_mac_final(oh, output, output_len); +} + +int uci_mac_get_mac(UCI_HANDLE oh, unsigned char *key, unsigned int key_len, + unsigned char *msg, unsigned int msg_len, unsigned char *output, + unsigned int *output_len) { + //int ret = 0; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx->alg == ID_UCI_XCBCMAC) { + if (xcbc_init((aes_xcbc_state *)(pctx->imp), key, key_len) != 1) { + return UCI_ERROR; + } + + if (xcbc_process((aes_xcbc_state*)(pctx->imp), msg, msg_len) != 1) { + return UCI_ERROR; + } + + if (xcbc_done((aes_xcbc_state*)(pctx->imp), output, output_len) != 1) { + return UCI_ERROR; + } + return UCI_SUCCESS; + + } + return cryptocore_mac_getmac(oh, key, key_len, msg, msg_len, output, + output_len); +} + +int uci_se_init(UCI_HANDLE oh, unsigned int mode, unsigned padding, + unsigned char *key, unsigned int key_len, unsigned char *iv) { + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + unsigned conf = SDRM_LOW_HALF(pctx->config); + if (conf == UCI_SW_CRYPTOCORE) { + return cryptocore_se_init(oh, mode, padding, key, key_len, iv); + } + if (conf == UCI_HW) { + return hwcrypto_se_init(oh, mode, padding, key, key_len, iv); + } + return UCI_ERROR; +} + +int uci_se_process(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char *output, unsigned int *output_len) { + + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + unsigned conf = SDRM_LOW_HALF(pctx->config); + if (input != NULL && output == NULL) { + return UCI_ERROR; + } + if (conf == UCI_SW_CRYPTOCORE) { + return cryptocore_se_process(oh, input, input_len, output, output_len); + } + if (conf == UCI_HW) { + return hwcrypto_se_process(oh, input, input_len, output, output_len); + } + return UCI_ERROR; +} + +int uci_se_final(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char *output, unsigned int *output_len) { + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + unsigned conf = SDRM_LOW_HALF(pctx->config); + if (input != NULL && output == NULL) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__); + return UCI_ERROR; + } + if (conf == UCI_SW_CRYPTOCORE) { + return cryptocore_se_final(oh, input, input_len, output, output_len); + } + if (conf == UCI_HW) { + return hwcrypto_se_final(oh, input, input_len, output, output_len); + } + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__); + return UCI_ERROR; +} + +int uci_se_encrypt_oneblock(UCI_HANDLE oh, unsigned char *cipher_text, + unsigned char *plain_text, unsigned char *user_key) { + if (cipher_text == NULL || plain_text == NULL || user_key == NULL) { + return UCI_ERROR; + } + return cryptocore_se_encrypt_oneblock(oh, cipher_text, plain_text, user_key); +} + +int uci_se_decrypt_oneblock(UCI_HANDLE oh, unsigned char *plain_text, + unsigned char *cipher_text, unsigned char *user_key) { + if (cipher_text == NULL || plain_text == NULL || user_key == NULL) { + return UCI_ERROR; + } + return cryptocore_se_decrypt_oneblock(oh, cipher_text, plain_text, user_key); +} + +int uci_wbse_init(UCI_HANDLE oh, int flag, unsigned char *key, + char *table_filepath, void *pencoder1, void *pencoder2) { + return UCI_ERROR; +} + +int uci_wbse_final(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char *output, unsigned int output_len) { + return UCI_ERROR; +} +int uci_ae_gen_param(UCI_HANDLE oh, uci_param_s *param, unsigned int size) { + return cryptocore_ae_gen_param(oh, param, size); +} + +int uci_ae_gen_keypair(UCI_HANDLE oh, uci_key_s *keymaterial, + uci_param_s *param) { + if (keymaterial == NULL) { + return UCI_ERROR; + } + return cryptocore_ae_gen_keypair(oh, keymaterial, param); + +} + +int uci_ae_set_keypair(UCI_HANDLE oh, uci_key_s *keymaterial, + uci_param_s *param) { + if (keymaterial == NULL) { + return UCI_ERROR; + } + return cryptocore_ae_set_keypair(oh, keymaterial, param); +} + +int uci_ae_encrypt(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char *output, unsigned int *output_len) { + return cryptocore_ae_encrypt(oh, input, input_len, output, output_len); +} + +int uci_ae_decrypt(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, + unsigned char *output, unsigned int *output_len) { + return cryptocore_ae_decrypt(oh, input, input_len, output, output_len); +} + +int uci_ae_decryptbycrt(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + return cryptocore_ae_decryptbycrt(oh, input, input_len, output, output_len); +} + +int uci_wbae_encrypt(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + return UCI_ERROR; +} + +int uci_wbae_decrypt(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + return UCI_ERROR; +} + +int uci_ds_sign(UCI_HANDLE oh, unsigned char *hash, unsigned int hash_len, + unsigned char *signature, unsigned int *sign_len) { + + return cryptocore_ds_sign(oh, hash, hash_len, signature, sign_len); +} + +int uci_ds_verify(UCI_HANDLE oh, unsigned char *hash, unsigned int hash_len, + unsigned char *signature, unsigned int sign_len, int *result) { + + return cryptocore_ds_verify(oh, hash, hash_len, signature, sign_len, result); +} + +int uci_dh_gen_phasekey(UCI_HANDLE oh, unsigned char *pch_xk, + unsigned char *pch_xv, uci_param_s *param) { + return cryptocore_dh_gen_dh1stphasekey(oh, pch_xk, pch_xv, param); +} + +int uci_dh_gen_authkey(UCI_HANDLE oh, unsigned char *pch_xk, + unsigned char *pch_xv, unsigned char *pch_kauth) { + return cryptocore_dh_gen_dhkey(oh, pch_xk, pch_xv, pch_kauth); +} + +int uci_prng_seed(UCI_HANDLE oh, unsigned char * seed) { + return cryptocore_prng_seed(oh, seed); +} + +int uci_prng_get(UCI_HANDLE oh, unsigned int bit_len, unsigned char *data) { + return cryptocore_prng_get(oh, bit_len, data); +} + +int uci_authcrypt_init(UCI_HANDLE oh, unsigned int mode, unsigned char *nonce, + unsigned int nonce_len, unsigned int tag_len, unsigned int aad_len, + unsigned int payload_len, unsigned char *key, unsigned int key_len) { +#if 0 + uci_context_s *pctx = (uci_context_s*)oh; + gcm_context *gctx = NULL; + aes_ccm_context *cctx = NULL; + int ret; + if(pctx->alg == ID_UCI_AE_GCM) + { + gctx = (gcm_context *)pctx->imp; + if(gcm_init(gctx, key, key_len) != 0) + { + return UCI_ERROR; + } + if(gcm_starts(gctx, mode, nonce, nonce_len) != 0) + { + return UCI_ERROR; + } + pctx->flag = tag_len; + } + else if(pctx->alg == ID_UCI_AE_CCM) + { + cctx = (aes_ccm_context *)pctx->imp; + ret = aes_ccm_init(cctx, mode, key, key_len, nonce, nonce_len, tag_len, aad_len, payload_len); + if(ret != 0) + { + printf("aes_ccm_init error. ret = %d\n ", ret); + return UCI_ERROR; + } + } + else + { + printf("alg type erro \n"); + return UCI_ERROR; + + } + + return UCI_SUCCESS; +#endif + return UCI_ERROR; +} +int uci_authcrypt_update_aad(UCI_HANDLE oh, unsigned char *aad, + unsigned int aad_len) { +#if 0 + uci_context_s *pctx = (uci_context_s*)oh; + gcm_context *gctx; + aes_ccm_context *cctx; + if(pctx->alg == ID_UCI_AE_GCM) + { + gctx = (gcm_context *)pctx->imp; + if(gcm_update_add(gctx, aad, aad_len) != 0) + { + return UCI_ERROR; + } + } + else if(pctx->alg == ID_UCI_AE_CCM) + { + cctx = (aes_ccm_context *)pctx->imp; + if(aes_ccm_update_aad(cctx,aad,aad_len) != 0) + { + return UCI_ERROR; + } + } + else + { + return UCI_ERROR; + } + + return UCI_SUCCESS; +#endif + return UCI_ERROR; +} +int uci_authcrypt_update(UCI_HANDLE oh, unsigned char *src, + unsigned int src_len, unsigned char *dest, unsigned int *dest_len) { +#if 0 + uci_context_s *pctx = (uci_context_s*)oh; + gcm_context *gctx; + aes_ccm_context *cctx; + + if(pctx->alg == ID_UCI_AE_GCM) + { + gctx = (gcm_context *)pctx->imp; + if(gcm_update(gctx,src_len, src, dest) != 0) + { + return UCI_ERROR; + } + *dest_len = src_len; + } + else if(pctx->alg == ID_UCI_AE_CCM) + { + cctx = (aes_ccm_context*)pctx->imp; + if(aes_ccm_process(cctx,src,src_len,dest,dest_len,NULL,NULL,0) != 0) + { + return UCI_ERROR; + } + } + else + { + return UCI_ERROR; + + } + + return UCI_SUCCESS; +#endif + return UCI_ERROR; +} +int uci_authcrypt_encryptfinal(UCI_HANDLE oh, unsigned char *src, + unsigned int src_len, unsigned char *dest, unsigned int *dest_len, + unsigned char *tag, unsigned int *tag_len) { +#if 0 + uci_context_s *pctx = (uci_context_s*)oh; + gcm_context *gctx = NULL; + aes_ccm_context *cctx = NULL; + + int ret; + if(pctx->alg == ID_UCI_AE_GCM) + { + + gctx = (gcm_context *)pctx->imp; + if(gcm_update(gctx,src_len, src, dest) != 0) + { + return UCI_ERROR; + } + if(dest_len != NULL) + { + *dest_len = src_len; + } + if((ret = gcm_finish(gctx, tag, pctx->flag)) != 0) + { + printf("ERROR %d\n",ret); + return UCI_ERROR; + } + if(tag_len != NULL) + { + *tag_len= pctx->flag; + } + } + else if(pctx->alg == ID_UCI_AE_CCM) + { + cctx = (aes_ccm_context*)pctx->imp; + if(aes_ccm_process(cctx,src,src_len,dest,dest_len,tag,tag_len,1) != 0) + { + return UCI_ERROR; + } + } + else + { + return UCI_ERROR; + + } + return UCI_SUCCESS; +#endif + return UCI_ERROR; +} +int uci_authcrypt_decryptfinal(UCI_HANDLE oh, unsigned char *src, + unsigned int src_len, unsigned char *dest, unsigned int *dest_len, + unsigned char *tag, unsigned int tag_len) { +#if 0 + uci_context_s *pctx = (uci_context_s*)oh; + gcm_context *gctx; + aes_ccm_context *cctx; + + unsigned char tmp[16] = + { 0x0,}; + unsigned int len = 0; + len = tag_len; + if(pctx->alg == ID_UCI_AE_GCM) + { + gctx = (gcm_context *)pctx->imp; + if(gcm_update(gctx,src_len, src, dest) != 0) + { + return UCI_ERROR; + } + *dest_len = src_len; + if(gcm_finish(gctx, tmp, pctx->flag) != 0) + { + printf("gcm_finish error \n"); + return UCI_ERROR; + } + if(memcmp(tmp, tag, tag_len) != 0) + { + PrintBYTE("tmp",tmp,tag_len); + PrintBYTE("tag",tag,tag_len); + printf("tag not right \n"); + return UCI_ERROR; + } + } + else if(pctx->alg == ID_UCI_AE_CCM) + { + cctx = (aes_ccm_context*)pctx->imp; + if(aes_ccm_process(cctx,src,src_len,dest,dest_len,tag,&len,1) != 0) + { + return UCI_ERROR; + } + } + else + { + return UCI_ERROR; + + } + return UCI_SUCCESS; +#endif + return UCI_ERROR; +} + +int uci_dup_handle(UCI_HANDLE srcoh, UCI_HANDLE destoh) { + uci_context_s *srcctx = (uci_context_s *)srcoh; + uci_context_s *destctx = NULL; + destoh = uci_context_alloc(srcctx->alg, (uci_engine_config_e)srcctx->config); + destctx = (uci_context_s *)destoh; + if (destctx == NULL) { + return UCI_ERROR; + } + + switch (srcctx->alg) { +#if 0 + case ID_UCI_AE_GCM: + memcpy(destctx->imp, srcctx->imp, sizeof(gcm_context)); + break; + case ID_UCI_AE_CCM: + memcpy(destctx->imp, srcctx->imp, sizeof(aes_ccm_context)); + break; +#endif + case ID_UCI_X931: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_X931Context)); + break; + case ID_UCI_MD5: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_MD5Context)); + break; + case ID_UCI_SHA1: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_SHA1Context)); + break; + case ID_UCI_SHA224: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_SHA224Context)); + break; + case ID_UCI_SHA256: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_SHA256Context)); + break; +#ifndef _OP64_NOTSUPPORTED + case ID_UCI_SHA384: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_SHA384Context)); + break; + case ID_UCI_SHA512: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_SHA512Context)); + break; +#endif + case ID_UCI_CMAC: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_CMACContext)); + break; + case ID_UCI_XCBCMAC: + memcpy(destctx->imp, srcctx->imp, sizeof(aes_xcbc_state)); + break; + case ID_UCI_HMD5: + case ID_UCI_HSHA1: + case ID_UCI_HSHA256: + case ID_UCI_HSHA224: +#ifndef _OP64_NOTSUPPORTED + case ID_UCI_HSHA384: + case ID_UCI_HSHA512: +#endif //_OP64_NOTSUPPORTED + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_HMACContext)); + break; + case ID_UCI_AES128: + case ID_UCI_AES192: + case ID_UCI_AES256: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_AESContext)); + break; + case ID_UCI_DES: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_DESContext)); + break; + case ID_UCI_TDES: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_TDESContext)); + break; + case ID_UCI_RC4: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_RC4Context)); + break; + case ID_UCI_SNOW2: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_SNOW2Context)); + break; + case ID_UCI_RSA512: + case ID_UCI_RSA: + case ID_UCI_RSA1024: + case ID_UCI_RSA2048: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_RSAContext)); + break; + case ID_UCI_DSA: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_DSAContext)); + break; + case ID_UCI_ECDSA: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_ECDSAContext)); + break; + case ID_UCI_ECDH: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_ECDHContext)); + break; + case ID_UCI_DH: + memcpy(destctx->imp, srcctx->imp, sizeof(SDRM_DHContext)); + break; + } + + return UCI_SUCCESS; +} + diff --git a/ssflib/dep/uci/source/uci_cryptocore.c b/ssflib/dep/uci/source/uci_cryptocore.c new file mode 100755 index 0000000..db15895 --- /dev/null +++ b/ssflib/dep/uci/source/uci_cryptocore.c @@ -0,0 +1,972 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +/** + * @file uci_cryptocore.cpp + * @brief UCI codec. + * @author guoxing.xu + * @version 1.0 + * @date 2013.9.9 + **/ + +#include "uci_cryptocore.h" +#include +#include "uci_internal.h" +#include "uci_aes_xcbc_mac.h" +#define g_bTAdbug 1 +#define TZ_PRINT(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) +#define TZ_ERROR(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) + +UCI_HANDLE cryptocore_context_alloc(unsigned int algorithm) { + UCI_HANDLE fd; + uci_context_s* ctx; + CryptoCoreContainer *crt; + + ctx = (uci_context_s*)OsaMalloc(sizeof(uci_context_s)); + if (ctx == NULL) { + return UCI_MEM_ALLOR_ERROR; + } + fd = (UCI_HANDLE)ctx; + crt = create_CryptoCoreContainer(algorithm); + if (crt == NULL) { + OsaFree(ctx); + return UCI_MEM_ALLOR_ERROR; + } + ctx->imp = (void*)crt; + ctx->config = UCI_SW; + ctx->alg = algorithm; + return fd; + +} + +int cryptocore_context_free(UCI_HANDLE oh) { + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + destroy_CryptoCoreContainer((CryptoCoreContainer*)pctx->imp); + OsaFree(pctx); + pctx = NULL; + + return UCI_SUCCESS; +} + +int cryptocore_md_init(UCI_HANDLE oh) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->MD_init( + (CryptoCoreContainer*)(pctx->imp)); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_md_update(UCI_HANDLE oh, unsigned char *msg, + unsigned int msg_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->MD_update( + ((CryptoCoreContainer*)pctx->imp), msg, msg_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_md_final(UCI_HANDLE oh, unsigned char *output) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->MD_final( + (CryptoCoreContainer*)pctx->imp, output); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_md_get_hash(UCI_HANDLE oh, unsigned char *msg, + unsigned int msg_len, unsigned char * output) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->MD_getHASH( + (CryptoCoreContainer*)pctx->imp, msg, msg_len, output); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_mac_init(UCI_HANDLE oh, unsigned char *key, unsigned int key_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)pctx->imp)->MAC_init( + (CryptoCoreContainer*)(pctx->imp), key, key_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_mac_update(UCI_HANDLE oh, unsigned char *msg, + unsigned int msg_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)pctx->imp)->MAC_update( + (CryptoCoreContainer*)(pctx->imp), msg, msg_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_mac_final(UCI_HANDLE oh, unsigned char *output, + unsigned int *output_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->MAC_final( + (CryptoCoreContainer*)(pctx->imp), output, output_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_mac_getmac(UCI_HANDLE oh, unsigned char *key, + unsigned int key_len, unsigned char *msg, unsigned int msg_len, + unsigned char *output, unsigned int *output_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->MAC_getMAC( + (CryptoCoreContainer*)(pctx->imp), key, key_len, msg, msg_len, output, + output_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_se_init(UCI_HANDLE oh, unsigned int mode, unsigned padding, + unsigned char *key, unsigned int key_len, unsigned char *iv) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + //deal with CTS base CBC + if (mode == ID_UCI_ENC_CTS || mode == ID_UCI_DEC_CTS) { + pctx->flag = mode; + if (mode == ID_UCI_ENC_CTS) { + ret = ((CryptoCoreContainer *)pctx->imp)->SE_init( + (CryptoCoreContainer*)(pctx->imp), ID_UCI_ENC_CBC, + ID_UCI_ZERO_PADDING, key, key_len, iv); + } else { + ret = ((CryptoCoreContainer *)pctx->imp)->SE_init( + (CryptoCoreContainer*)(pctx->imp), ID_UCI_DEC_CBC, + ID_UCI_ZERO_PADDING, key, key_len, iv); + } + } else { + ret = ((CryptoCoreContainer *)pctx->imp)->SE_init( + (CryptoCoreContainer*)(pctx->imp), mode, padding, key, key_len, iv); + } + if (ret == CRYPTO_INVALID_ARGUMENT) { + return UCI_INVALID_ARGUMENT; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + + return UCI_SUCCESS; +} + +int cryptocore_se_process(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->SE_process( + (CryptoCoreContainer*)(pctx->imp), input, input_len, output, output_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_se_final(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + int ret; + unsigned int lastblocksize = 0; + unsigned char lastblock[SDRM_AES_BLOCK_SIZ]; + unsigned char secondlastblock[SDRM_AES_BLOCK_SIZ]; + unsigned char aIV[SDRM_AES_BLOCK_SIZ] = {0x0, }; + uci_context_s *pctx = (uci_context_s*)oh; + unsigned char *psecondlastblk = NULL; //point to second last block + unsigned char *plastblk = NULL; //point to last block + CryptoCoreContainer *crt = NULL; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + crt = (CryptoCoreContainer*)(pctx->imp); + + if (input_len <= SDRM_AES_BLOCK_SIZ) { + goto final; + } + + plastblk = input + SDRM_AES_BLOCK_SIZ; + psecondlastblk = input; + + //cts encrypt + if (pctx->flag == ID_UCI_ENC_CTS) { + +#if 0 + lastblocksize = input_len % SDRM_AES_BLOCK_SIZ; + if(lastblocksize == 0) + { + lastblocksize = 16; + } + + ret = crt->SE_process(crt, psecondlastblk, SDRM_AES_BLOCK_SIZ, lastblock, output_len); + if(ret!=CRYPTO_SUCCESS) + { + return UCI_ERROR; + } +#endif + if (input_len % SDRM_AES_BLOCK_SIZ == 0) { + crt->ctx->aesctx->padding = ID_NO_PADDING; + } + ret = crt->SE_final(crt, input, input_len, output, output_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + //swap last block + memcpy(lastblock, output + *output_len - 2 * SDRM_AES_BLOCK_SIZ, + SDRM_AES_BLOCK_SIZ); + memcpy(output + *output_len - 2 * SDRM_AES_BLOCK_SIZ, + output + *output_len - SDRM_AES_BLOCK_SIZ, + SDRM_AES_BLOCK_SIZ); + memcpy(output + *output_len - SDRM_AES_BLOCK_SIZ, lastblock, + SDRM_AES_BLOCK_SIZ); + return UCI_SUCCESS; + + } + //cts decrypt + if (pctx->flag == ID_UCI_DEC_CTS) { + lastblocksize = input_len % SDRM_AES_BLOCK_SIZ; + + if (input_len != 2 * SDRM_AES_BLOCK_SIZ) { + //1.Dn = Decrypt (K, Cn-1). Decrypt the second to last ciphertext block, using zeros as IV. + + memcpy(aIV, crt->ctx->aesctx->IV, SDRM_AES_BLOCK_SIZ); + memset(crt->ctx->aesctx->IV, 0, SDRM_AES_BLOCK_SIZ); + + memset(crt->ctx->aesctx->Block, 0, SDRM_AES_BLOCK_SIZ); + + crt->ctx->aesctx->BlockLen = 0; + ret = crt->SE_process(crt, psecondlastblk, + SDRM_AES_BLOCK_SIZ, secondlastblock, output_len); + if (ret != CRYPTO_SUCCESS) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + return UCI_ERROR; + } + + // 2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the nearest multiple of the block size using the last B-M bits of block cipher decryption of the second-to-last ciphertext block. + memcpy(lastblock, plastblk, lastblocksize); + memcpy(lastblock + lastblocksize, secondlastblock + lastblocksize, + SDRM_AES_BLOCK_SIZ - lastblocksize); + memcpy(crt->ctx->aesctx->IV, aIV, SDRM_AES_BLOCK_SIZ); + // 3. Swap the last two ciphertext blocks. + + // 4. Decrypt the (modified) ciphertext using the standard CBC mode up to the last block. + ret = crt->SE_process(crt, lastblock, + SDRM_AES_BLOCK_SIZ, output, output_len); + if (ret != CRYPTO_SUCCESS) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + return UCI_ERROR; + } + ret = crt->SE_process(crt, psecondlastblk, + SDRM_AES_BLOCK_SIZ, lastblock, output_len); + if (ret != CRYPTO_SUCCESS) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + return UCI_ERROR; + } + memcpy(output + SDRM_AES_BLOCK_SIZ, lastblock, lastblocksize); + *output_len = input_len; + return UCI_SUCCESS; + } + //swap last two block and decrypto + if (input_len == 2 * SDRM_AES_BLOCK_SIZ) { + ret = crt->SE_process(crt, input + SDRM_AES_BLOCK_SIZ, + SDRM_AES_BLOCK_SIZ, output, output_len); + if (ret != CRYPTO_SUCCESS) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + return UCI_ERROR; + } + crt->ctx->aesctx->padding = ID_NO_PADDING; + ret = crt->SE_final(crt, input, + SDRM_AES_BLOCK_SIZ, output + SDRM_AES_BLOCK_SIZ, output_len); + if (ret != CRYPTO_SUCCESS) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + return UCI_ERROR; + } + *output_len = 2 * SDRM_AES_BLOCK_SIZ; + return UCI_SUCCESS; + } + } +// deal with other mode except cts + final: ret = crt->SE_final(crt, input, input_len, output, output_len); + if (ret != CRYPTO_SUCCESS) { + TZ_ERROR("UCI_ERROR error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + return UCI_ERROR; + } + return UCI_SUCCESS; +} +int cryptocore_se_encrypt_oneblock(UCI_HANDLE oh, unsigned char *cipher_text, + unsigned char * plain_text, unsigned char *user_key) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->SE_EncryptOneBlock(cipher_text, + plain_text, user_key); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_se_decrypt_oneblock(UCI_HANDLE oh, unsigned char *plain_text, + unsigned char *cipher_text, unsigned char *user_key) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->SE_DecryptOneBlock(cipher_text, + plain_text, user_key); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_ae_gen_param(UCI_HANDLE oh, uci_param_s *param, + unsigned int size) { + int ret; + unsigned int alg; + //uci_param_imp_u *uciparm = NULL; + CryptoCoreContainer *crt = NULL; + uci_context_s *pctx = (uci_context_s*)oh; + if (param == NULL) { + return UCI_INVALID_ARGUMENT; + } + + alg = pctx->alg; + + switch (alg) { + case ID_UCI_DH: + crt = create_CryptoCoreContainer(ID_DH); + if (crt == NULL) { + return UCI_ERROR; + } + if (crt->DH_GenerateParam(crt, param->uparam.udhp.prime, size, + param->uparam.udhp.generator) != CRYPTO_SUCCESS) { + destroy_CryptoCoreContainer(crt); + return UCI_ERROR; + } + param->uparam.udhp.len = size; + destroy_CryptoCoreContainer(crt); + break; + case ID_UCI_DSA: + crt = create_CryptoCoreContainer(ID_DSA); + if (crt == NULL) { + return UCI_ERROR; + } + + ret = crt->DSA_genParam(crt, size, param->uparam.udp.dsa_p_data, + &(param->uparam.udp.dsa_p_len), param->uparam.udp.dsa_q_data, + &(param->uparam.udp.dsa_q_len), param->uparam.udp.dsa_g_data, + &(param->uparam.udp.dsa_g_len)); + + if (ret != UCI_SUCCESS) { + destroy_CryptoCoreContainer(crt); + return UCI_ERROR; + } + destroy_CryptoCoreContainer(crt); + break; + default: + return UCI_INVALID_HANDLE; + } + return UCI_SUCCESS; +} + +int cryptocore_ae_gen_keypair(UCI_HANDLE oh, uci_key_s *keymaterial, + uci_param_s *param) { + uci_context_s *pctx = (uci_context_s*)oh; + unsigned int alg; + unsigned int pad; + uci_key_s *ucikey = keymaterial; + int ret = UCI_ERROR; + uci_param_imp_u *uciparm = NULL; + if (param == NULL) { + return UCI_INVALID_ARGUMENT; + } + uciparm = ¶m->uparam; + + if (pctx->config != UCI_SW_CRYPTOCORE) { + return UCI_INVALID_HANDLE; + } + alg = pctx->alg; + switch (alg) { + case ID_UCI_RSA512: + case ID_UCI_RSA: + case ID_UCI_RSA1024: + case ID_UCI_RSA2048: + case ID_UCI_RSA3072: + pad = SDRM_LOW_HALF(uciparm->urp.padding); + if (pad != ID_UCI_RSAES_PKCS15 && pad != ID_UCI_RSAES_OAEP + && pad != ID_UCI_NO_PADDING && pad != ID_UCI_RSASSA_PKCS15 + && pad != ID_UCI_RSASSA_PSS) { + return UCI_INVALID_ARGUMENT; + } + if (uciparm->urp.flag == RSA_GENKEYWITHNON) { + ret = ((CryptoCoreContainer *)pctx->imp)->RSA_genKeypair( + (CryptoCoreContainer *)pctx->imp, uciparm->urp.padding, + ucikey->imp.rkey.n, &(ucikey->imp.rkey.n_len), ucikey->imp.rkey.e, + &(ucikey->imp.rkey.e_len), ucikey->imp.rkey.d, + &(ucikey->imp.rkey.d_len)); + break; + } + if (uciparm->urp.flag == RSA_GENKEYWITHE) { + ret = ((CryptoCoreContainer *)pctx->imp)->RSA_genKeypairWithE( + (CryptoCoreContainer *)pctx->imp, uciparm->urp.padding, + uciparm->urp.e, uciparm->urp.e_len, ucikey->imp.rkey.n, + &(ucikey->imp.rkey.n_len), ucikey->imp.rkey.d, + &(ucikey->imp.rkey.d_len)); + break; + } + if (uciparm->urp.flag == RSA_GENKEYWITHPQE) { + ret = ((CryptoCoreContainer *)pctx->imp)->RSA_genKeyDWithPQE( + (CryptoCoreContainer *)pctx->imp, uciparm->urp.padding, + uciparm->urp.e, uciparm->urp.e_len, uciparm->urp.p, + uciparm->urp.p_len, uciparm->urp.q, uciparm->urp.q_len, + ucikey->imp.rkey.n, &(ucikey->imp.rkey.n_len), ucikey->imp.rkey.d, + &(ucikey->imp.rkey.d_len)); + break; + } + if (uciparm->urp.flag == RSA_KEYFORCRT) { + ret = ((CryptoCoreContainer *)pctx->imp)->RSA_genKeypairForCRT( + (CryptoCoreContainer *)pctx->imp, uciparm->urp.padding, + ucikey->imp.rkey.n, &(ucikey->imp.rkey.n_len), ucikey->imp.rkey.e, + &(ucikey->imp.rkey.e_len), ucikey->imp.rkey.d, + &(ucikey->imp.rkey.d_len), uciparm->urp.p, &(uciparm->urp.p_len), + uciparm->urp.q, &(uciparm->urp.q_len), uciparm->urp.dmodp1, + &(uciparm->urp.dmodp1_len), uciparm->urp.dmodq1, + &(uciparm->urp.dmodq1_len), uciparm->urp.iqp, + &(uciparm->urp.iqp_len)); + } + break; + case ID_UCI_DSA: + ret = ((CryptoCoreContainer *)pctx->imp)->DSA_setParam( + (CryptoCoreContainer *)pctx->imp, uciparm->udp.dsa_p_data, + uciparm->udp.dsa_p_len, uciparm->udp.dsa_q_data, + uciparm->udp.dsa_q_len, uciparm->udp.dsa_g_data, + uciparm->udp.dsa_g_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->DSA_genKeypair( + (CryptoCoreContainer *)pctx->imp, ucikey->imp.dkey.ydata, + &(ucikey->imp.dkey.ydata_len), ucikey->imp.dkey.xdata, + &(ucikey->imp.dkey.xdata_len)); + break; + case ID_UCI_ECDSA: + case ID_UCI_ECDH: + //set curver parameter + ret = ((CryptoCoreContainer *)pctx->imp)->EC_setCurve( + (CryptoCoreContainer *)pctx->imp, uciparm->uep.dimension, + uciparm->uep.ecc_p_data, uciparm->uep.ecc_p_len, + uciparm->uep.ecc_a_data, uciparm->uep.ecc_a_len, + uciparm->uep.ecc_b_data, uciparm->uep.ecc_b_len, + uciparm->uep.ecc_g_x_data, uciparm->uep.ecc_g_x_len, + uciparm->uep.ecc_g_y_data, uciparm->uep.ecc_g_y_len, + uciparm->uep.ecc_r_data, uciparm->uep.ecc_r_len); + if (ret != CRYPTO_SUCCESS) { + break; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->EC_genKeypair( + (CryptoCoreContainer *)pctx->imp, ucikey->imp.ekey.privatekey, + &(ucikey->imp.ekey.privatekey_len), ucikey->imp.ekey.publickey_x, + &(ucikey->imp.ekey.publickey_x_len), ucikey->imp.ekey.publickey_y, + &(ucikey->imp.ekey.publickey_y_len)); + break; + default: + return UCI_ERROR; + } + if (ret == CRYPTO_INVALID_ARGUMENT) { + return UCI_INVALID_ARGUMENT; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; + +} + +int cryptocore_ae_set_keypair(UCI_HANDLE oh, uci_key_s *keymaterial, + uci_param_s *param) { + uci_context_s *pctx = (uci_context_s*)oh; + uci_key_s *ucikey = keymaterial; + uci_param_imp_u *uciparm = ¶m->uparam; + int ret; + unsigned int pad; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + int alg = pctx->alg; + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + switch (alg) { + case ID_UCI_RSA512: + case ID_UCI_RSA: + case ID_UCI_RSA1024: + case ID_UCI_RSA2048: + case ID_UCI_RSA3072: + pad = SDRM_LOW_HALF(uciparm->urp.padding); + + if (pad != ID_UCI_RSAES_PKCS15 && pad != ID_UCI_RSAES_OAEP + && pad != ID_UCI_NO_PADDING && pad != ID_UCI_RSASSA_PKCS15 + && pad != ID_UCI_RSASSA_PSS) { + return UCI_INVALID_ARGUMENT; + } + + if (uciparm->urp.flag == RSA_KEYFORCRT) { + ret = ((CryptoCoreContainer *)pctx->imp)->RSA_setKeypairForCRT( + (CryptoCoreContainer *)pctx->imp, uciparm->urp.padding, + ucikey->imp.rkey.n, ucikey->imp.rkey.n_len, ucikey->imp.rkey.e, + ucikey->imp.rkey.e_len, ucikey->imp.rkey.d, ucikey->imp.rkey.d_len, + uciparm->urp.p, uciparm->urp.p_len, uciparm->urp.q, + uciparm->urp.q_len, uciparm->urp.dmodp1, uciparm->urp.dmodp1_len, + uciparm->urp.dmodq1, uciparm->urp.dmodq1_len, uciparm->urp.iqp, + uciparm->urp.iqp_len); + } else { + ret = ((CryptoCoreContainer *)pctx->imp)->RSA_setKeypair( + (CryptoCoreContainer *)pctx->imp, uciparm->urp.padding, + ucikey->imp.rkey.n, ucikey->imp.rkey.n_len, ucikey->imp.rkey.e, + ucikey->imp.rkey.e_len, ucikey->imp.rkey.d, ucikey->imp.rkey.d_len); + } + break; + case ID_UCI_DSA: + ret = ((CryptoCoreContainer *)pctx->imp)->DSA_setParam( + (CryptoCoreContainer *)pctx->imp, uciparm->udp.dsa_p_data, + uciparm->udp.dsa_p_len, uciparm->udp.dsa_q_data, + uciparm->udp.dsa_q_len, uciparm->udp.dsa_g_data, + uciparm->udp.dsa_g_len); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + ret = ((CryptoCoreContainer *)pctx->imp)->DSA_setKeyPair( + (CryptoCoreContainer *)pctx->imp, ucikey->imp.dkey.ydata, + (ucikey->imp.dkey.ydata_len), ucikey->imp.dkey.xdata, + (ucikey->imp.dkey.xdata_len)); + break; + case ID_UCI_ECDSA: + ret = ((CryptoCoreContainer *)pctx->imp)->EC_setCurve( + (CryptoCoreContainer *)pctx->imp, uciparm->uep.dimension, + uciparm->uep.ecc_p_data, uciparm->uep.ecc_p_len, + uciparm->uep.ecc_a_data, uciparm->uep.ecc_a_len, + uciparm->uep.ecc_b_data, uciparm->uep.ecc_b_len, + uciparm->uep.ecc_g_x_data, uciparm->uep.ecc_g_x_len, + uciparm->uep.ecc_g_y_data, uciparm->uep.ecc_g_y_len, + uciparm->uep.ecc_r_data, uciparm->uep.ecc_r_len); + + ret = ((CryptoCoreContainer *)pctx->imp)->EC_setKeypair( + (CryptoCoreContainer *)pctx->imp, ucikey->imp.ekey.privatekey, + (ucikey->imp.ekey.privatekey_len), ucikey->imp.ekey.publickey_x, + (ucikey->imp.ekey.publickey_x_len), ucikey->imp.ekey.publickey_y, + (ucikey->imp.ekey.publickey_y_len)); + break; + case ID_UCI_DH: + ret = ((CryptoCoreContainer *)pctx->imp)->DH_SetParam( + (CryptoCoreContainer *)pctx->imp, uciparm->udhp.prime, + uciparm->udhp.len, uciparm->udhp.generator, uciparm->udhp.len); + break; + default: + return UCI_ERROR; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_ae_encrypt(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + if (pctx->alg < ID_UCI_RSA || pctx->alg > ID_UCI_RSA512) { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)pctx->imp)->AE_encrypt( + ((CryptoCoreContainer*)pctx->imp), input, input_len, output, output_len); + if (ret == CRYPTO_MSG_TOO_LONG) { + return UCI_MSG_TOO_LONG; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_ae_decrypt(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + if (pctx->alg < ID_UCI_RSA || pctx->alg > ID_UCI_RSA512) { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)pctx->imp)->AE_decrypt( + ((CryptoCoreContainer*)pctx->imp), input, input_len, output, output_len); + if (ret == CRYPTO_MSG_TOO_LONG) { + return UCI_MSG_TOO_LONG; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_ae_decryptbycrt(UCI_HANDLE oh, unsigned char *input, + unsigned int input_len, unsigned char *output, unsigned int *output_len) { + + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + // ctr=(CryptoCoreContainer *)(pctx->imp); + // ctr->MD_update(ctr,msg,msg_len); + ret = ((CryptoCoreContainer *)pctx->imp)->AE_decryptByCRT( + ((CryptoCoreContainer*)pctx->imp), input, input_len, output, output_len); + if (ret == CRYPTO_MSG_TOO_LONG) { + return UCI_MSG_TOO_LONG; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_ds_sign(UCI_HANDLE oh, unsigned char *hash, + unsigned int hash_len, unsigned char *signature, unsigned int *sign_len) { + + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->DS_sign( + ((CryptoCoreContainer*)pctx->imp), hash, hash_len, signature, sign_len); + if (ret == CRYPTO_MSG_TOO_LONG) { + return UCI_MSG_TOO_LONG; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_ds_verify(UCI_HANDLE oh, unsigned char *hash, + unsigned int hash_len, unsigned char *signature, unsigned int sign_len, + int *result) { + + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + ret = ((CryptoCoreContainer *)pctx->imp)->DS_verify( + (CryptoCoreContainer*)pctx->imp, hash, hash_len, signature, sign_len, + result); + if (ret == CRYPTO_MSG_TOO_LONG) { + return UCI_MSG_TOO_LONG; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_dh_gen_dh1stphasekey(UCI_HANDLE oh, unsigned char *pch_xk, + unsigned char *pch_xv, uci_param_s *param) { + int ret; + uci_param_imp_u *uciparam = ¶m->uparam; + uci_context_s *pctx = (uci_context_s*)oh; + unsigned int alg; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + + alg = pctx->alg; + if (alg == ID_UCI_ECDH) { + ret = ((CryptoCoreContainer *)pctx->imp)->EC_setCurve( + (CryptoCoreContainer *)pctx->imp, uciparam->uep.dimension, + uciparam->uep.ecc_p_data, uciparam->uep.ecc_p_len, + uciparam->uep.ecc_a_data, uciparam->uep.ecc_a_len, + uciparam->uep.ecc_b_data, uciparam->uep.ecc_b_len, + uciparam->uep.ecc_g_x_data, uciparam->uep.ecc_g_x_len, + uciparam->uep.ecc_g_y_data, uciparam->uep.ecc_g_y_len, + uciparam->uep.ecc_r_data, uciparam->uep.ecc_r_len); + + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + ret = ((CryptoCoreContainer *)pctx->imp)->ECDH_Gen1stPhaseKey( + (CryptoCoreContainer*)pctx->imp, pch_xk, pch_xv); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } else { + return UCI_SUCCESS; + } + } + if (alg == ID_UCI_DH) { + ret = ((CryptoCoreContainer *)pctx->imp)->DH_SetParam( + (CryptoCoreContainer *)pctx->imp, uciparam->udhp.prime, + uciparam->udhp.len, uciparam->udhp.generator, uciparam->udhp.len); + + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + ret = ((CryptoCoreContainer *)pctx->imp)->DH_Gen1stPhaseKey( + (CryptoCoreContainer*)pctx->imp, pch_xk, pch_xv); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } else { + return UCI_SUCCESS; + } + } + return UCI_ERROR; +} + +int cryptocore_dh_gen_dhkey(UCI_HANDLE oh, unsigned char *pch_xk, + unsigned char *pch_xv, unsigned char *pch_kauth) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + unsigned int alg; + + if (pctx->config != UCI_SW_CRYPTOCORE) { + return UCI_INVALID_HANDLE; + } + alg = pctx->alg; + + if (alg == ID_UCI_ECDH) { + ret = ((CryptoCoreContainer *)pctx->imp)->ECDH_GenAuthKey( + (CryptoCoreContainer*)pctx->imp, pch_xk, pch_xv, pch_kauth); + } else if (alg == ID_UCI_DH) { + ret = ((CryptoCoreContainer *)pctx->imp)->DH_GenAuthKey( + (CryptoCoreContainer*)pctx->imp, pch_xk, pch_xv, pch_kauth); + } else { + return UCI_INVALID_HANDLE; + } + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return CRYPTO_SUCCESS; + +} + +int cryptocore_prng_seed(UCI_HANDLE oh, unsigned char *seed) { + + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + if (pctx->alg != ID_UCI_X931) { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)pctx->imp)->PRNG_seed( + (CryptoCoreContainer*)(pctx->imp), seed); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + +int cryptocore_prng_get(UCI_HANDLE oh, unsigned int bit_len, + unsigned char *data) { + int ret; + uci_context_s *pctx = (uci_context_s*)oh; + if (pctx == NULL) { + return UCI_INVALID_HANDLE; + } + + if (pctx->config != UCI_SW) { + return UCI_INVALID_HANDLE; + } + if (pctx->alg != ID_UCI_X931) { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)pctx->imp)->PRNG_get( + (CryptoCoreContainer*)(pctx->imp), bit_len, data); + if (ret != CRYPTO_SUCCESS) { + return UCI_ERROR; + } + return UCI_SUCCESS; +} + diff --git a/ssflib/dep/uci/source/uci_hwcrypto.c b/ssflib/dep/uci/source/uci_hwcrypto.c new file mode 100755 index 0000000..ff15c41 --- /dev/null +++ b/ssflib/dep/uci/source/uci_hwcrypto.c @@ -0,0 +1,813 @@ +/* +* Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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 PC_I586 + +/** +* @file uci_hwcrypto.cpp +* @brief UCI codec. +* @author guoxing.xu +* @version 1.0 +* @date 2013.11 +**/ +#ifndef PC_I586 +#include +#include +#include +#include +#else +#include +#endif +#include "uci_internal.h" +#include "uci_hwcrypto.h" +#include + + +/*! \brief print out by byte unit */ +#undef PrintBYTE +#define PrintBYTE(msg, Data, DataLen) { \ + int idx; \ + printf("%10s =", msg); \ + for( idx=0; idx<(int)DataLen; idx++) { \ + if( (idx!=0) && ((idx%16)==0) ) printf("\n"); \ + if((idx % 4) == 0) printf(" 0x"); \ + printf("%.2x", Data[idx]); \ + } \ + printf("\n"); \ +} + +#define g_bTAdbug 0 +#define TA_PRINT(fmt...) \ + do {if (g_bTAdbug) printf(fmt);}while(0) +#define TA_ERROR(fmt...) \ + do {if (g_bTAdbug) printf(fmt);}while(0) + +/*! \brief convert 32-bit unit to 4 byte */ +#undef GET_UINT32 +#define GET_UINT32(n,b,i) \ + { \ + (n) = ((unsigned int)((b)[(i) ]) << 24 ) \ + | ((unsigned int)((b)[(i) + 1]) << 16 ) \ + | ((unsigned int)((b)[(i) + 2]) << 8 ) \ + | ((unsigned int)((b)[(i) + 3]) ); \ + } + +UCI_HANDLE hwcrypto_context_alloc(unsigned int algorithm, uci_engine_config_e config) +{ + + UCI_HANDLE fd; + uci_context_s* ctx; + ctx = (uci_context_s*)malloc(sizeof(uci_context_s)); + if(ctx == NULL) + { + return UCI_MEM_ALLOR_ERROR; + } + ctx->config = config; + ctx->alg = algorithm; +#ifndef PC_I586 + ctx->imp = malloc(sizeof(struct crypt_info)); +#else + ctx->imp = create_CryptoCoreContainer(algorithm); +#endif + if(ctx->imp == NULL) + { + free(ctx); + return UCI_MEM_ALLOR_ERROR; + } + fd = (UCI_HANDLE)ctx; + return fd; +} + +int hwcrypto_context_free( UCI_HANDLE oh ) +{ + uci_context_s *pctx = (uci_context_s*)oh; + if(pctx == NULL) + { + return UCI_INVALID_HANDLE; + } + if(pctx->imp != NULL) + { +#ifndef PC_I586 + free(pctx->imp); +#else + destroy_CryptoCoreContainer((CryptoCoreContainer*)pctx->imp); +#endif + pctx->imp = NULL; + } +#ifndef PC_I586 + /*close crypto handle*/ + if(pctx->handle >= 0) + { + close(pctx->handle); + } +#endif + free(pctx); + pctx = NULL; + return UCI_SUCCESS; +} + +int hwcrypto_se_init(UCI_HANDLE oh, unsigned int mode, unsigned int padding, unsigned char *key, unsigned int key_len, unsigned char *iv) +{ +#ifndef PC_I586 + uci_context_s *pctx; + struct crypt_info *info; + unsigned int keytype; + int ret = 0; + pctx = (uci_context_s*)oh; + if(pctx == NULL) + { + return UCI_INVALID_HANDLE; + } + info = (struct crypt_info*)pctx->imp; + keytype = SDRM_HIGH_HALF(pctx->config); + + + if(keytype == UCI_USER_KEY && key == NULL) + { + return UCI_ERROR; + } + + switch(pctx->alg) + { + case ID_UCI_AES128: + switch(mode) + { + case ID_UCI_ENC_CBC: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_CBC_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_CBC; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_CBC; + break; + case ID_UCI_ENC_CTR: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_CTR_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_CTR; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_CTR; + break; + case ID_UCI_ENC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_ECB_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_ECB; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_ECB; + break; + case ID_UCI_DEC_CBC: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_CBC_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_CBC | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_CBC; + break; + case ID_UCI_DEC_CTR: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_CTR_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_CTR | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_CTR; + break; + case ID_UCI_DEC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_ECB_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_ECB | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_ECB; + break; + default: + return UCI_INVALID_ARGUMENT; + } + info->keylen = 16; + info->ivlen = 16; + break; + case ID_UCI_AES256:/*now only support ecb and ctr*/ + switch(mode) + { + case ID_UCI_ENC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_ECB_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_ECB; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_ECB; + break; + case ID_UCI_DEC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_ECB_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_ECB | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_ECB; + break; + case ID_UCI_ENC_CTR: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_CTR_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_CTR; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_CTR; + break; + case ID_UCI_DEC_CTR: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_AES_CTR_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_AES_CTR | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_CTR; + break; + default: + return UCI_INVALID_ARGUMENT; + } + info->keylen = 32; + info->ivlen = 16; + break; + case ID_UCI_DES: + switch(mode) + { + case ID_UCI_ENC_CBC: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_DES_CBC_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_DES_CBC; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_CBC; + break; + case ID_UCI_ENC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_DES_ECB_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_DES_ECB; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_ECB; + break; + case ID_UCI_DEC_CBC: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_DES_CBC_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_DES_CBC | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_CBC; + break; + case ID_UCI_DEC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_DES_ECB_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_DES_ECB | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_ECB; + break; + default: + return UCI_INVALID_ARGUMENT; + + } + info->keylen = 8; + info->ivlen = 8; + break; + case ID_UCI_TDES: + switch(mode) + { + case ID_UCI_ENC_CBC: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_TDES_CBC_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_TDES_CBC; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_CBC; + break; + case ID_UCI_ENC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_TDES_ECB_PAD; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_TDES_ECB; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_ECB; + break; + case ID_UCI_DEC_CBC: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_TDES_CBC_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_TDES_CBC | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_ENC_ECB; + break; + case ID_UCI_DEC_ECB: + if(padding == ID_UCI_PKCS5) + { + info->mode = MI_TDES_ECB_PAD | _MODE_DEC_; + } + else if(padding == ID_UCI_NO_PADDING) + { + info->mode = MI_TDES_ECB | _MODE_DEC_; + } + else + { + return UCI_INVALID_ARGUMENT; + } + pctx->mode = ID_UCI_DEC_ECB; + break; + default: + return UCI_INVALID_ARGUMENT; + + } + info->keylen = 24; + info->ivlen = 8; + break; + default: + return UCI_INVALID_HANDLE; + + } + + /*set info key*/ + + switch(keytype) + { + case UCI_USER_KEY: + info->keytype = KEYID_USER_KEY; + if(key_len != 8 && key_len != 16 && key_len != 24 && key_len != 32) + { + return UCI_INVALID_ARGUMENT; + } + memcpy(info->key, key, key_len); + break; + case UCI_SECRET_KEY: + info->keytype = KEYID_SECURE_KEY; + break; + case UCI_MASTER_KEY: + info->keytype = KEYID_MASTER_KEY; + break; + default : + return UCI_INVALID_ARGUMENT; + } + /*setiv*/ + if(iv) + { + memcpy(info->iv, iv, info->ivlen); + } + else + { + memset(info->iv, 0x0, info->ivlen); + } + pctx->handle = open("/dev/crypto", 0, 0 ); //return hndl; + //TA_PRINT("hand = %d \n",pctx->handle); + if(pctx->handle < 0) + { + return UCI_ERROR; + } + if (ret = ioctl(pctx->handle, IOCTL_CRYPTO_INIT, info)) + { + TA_PRINT("error:ioctl(hndl, IOCTL_CRYPTO_INIT, info) returned %d\n",ret); + return UCI_ERROR; + } + return UCI_SUCCESS; + +#else + + int ret = UCI_ERROR; + uci_context_s *pctx = (uci_context_s*)oh; + unsigned int keytype; + unsigned int alg; + //!AS current hw is not ready, so using SW pseduo way temproray. + unsigned char hwkey_master[32]={ 0xAB, 0x12, 0x45, 0x67, 0x3F, 0x80, 0x98, 0x35, + 0x06, 0x4F, 0x33, 0x39, 0x72, 0x1C, 0xDF, 0x23, + 0xAB, 0x12, 0x45, 0x67, 0x3F, 0x80, 0x98, 0x35, + 0x06, 0x4F, 0x33, 0x39, 0x72, 0x1C, 0xDF, 0x23}; + unsigned char hwiv_master[16] ={ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; + unsigned char hwkey_unique[32]={ 0xF0, 0x22, 0x34, 0x67, 0x66, 0x88, 0xAB, 0xCD, + 0x12, 0x67, 0x89, 0x54, 0x32, 0x10, 0xCC, 0xFE, + 0xAB, 0x12, 0x45, 0x67, 0x3F, 0x80, 0x98, 0x35, + 0x06, 0x4F, 0x33, 0x39, 0x72, 0x1C, 0xDF, 0x23}; + unsigned char hwiv_unique[16] ={ 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; + if(pctx == NULL) + { + return UCI_INVALID_HANDLE; + } + alg = pctx->alg; + switch(alg) + { + case ID_UCI_AES128: + key_len = 16; + break; + case ID_UCI_AES256: + key_len = 32; + break; + case ID_UCI_DES: + key_len = 8; + break; + case ID_UCI_TDES: + key_len = 24; + + } + keytype = SDRM_HIGH_HALF(pctx->config); + if (keytype != UCI_USER_KEY) + { + if(keytype == UCI_MASTER_KEY) + { + ret = ((CryptoCoreContainer *)pctx->imp)->SE_init((CryptoCoreContainer *)pctx->imp, mode, padding, hwkey_master,key_len,hwiv_master); + + } + else if(keytype == UCI_SECRET_KEY) + { + ret =((CryptoCoreContainer *)pctx->imp)->SE_init((CryptoCoreContainer *)pctx->imp, mode, padding, hwkey_unique,key_len,hwiv_unique); + } + } + else + { + ret = ((CryptoCoreContainer *)pctx->imp)->SE_init((CryptoCoreContainer *)pctx->imp, mode, padding, key,key_len, iv); + + } + + if(ret == CRYPTO_INVALID_ARGUMENT) + { + return UCI_INVALID_ARGUMENT; + } + if(ret != CRYPTO_SUCCESS) + { + return UCI_ERROR; + } + + return UCI_SUCCESS; +#endif +} + +int hwcrypto_se_process(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len) +{ +#ifndef PC_I586 + uci_context_s *pctx = NULL; + unsigned int alg = 0; + unsigned int counter = 0; + struct crypt_oper oper; + int ret = 0; + int blocksize = 0; + + memset(&oper, 0, sizeof(struct crypt_oper)); + + pctx = (uci_context_s*)oh; + if(pctx == NULL) + { + return UCI_INVALID_HANDLE; + } + if(pctx->handle < 0) + { + TA_PRINT("Handle error \n"); + return UCI_ERROR; + } + if(output_len != NULL) + { + *output_len = 0; + } + + if(alg == ID_UCI_AES128 || alg == ID_UCI_AES256) + { + if((input_len % 16) != 0) + { + TA_PRINT("input_len error\n"); + return UCI_ERROR; + } + blocksize = 16; + } + if(alg == ID_UCI_DES || alg == ID_UCI_TDES) + { + if((input_len % 8) != 0) + { + TA_PRINT("input_len error\n"); + return UCI_ERROR; + } + blocksize = 8; + } + + oper.src_addr = input; + oper.src_len = input_len; + oper.dst_addr = output; + oper.dst_len = output_len; + if (ret = ioctl(pctx->handle, IOCTL_CRYPTO_CRYPT, &oper)) + { + TA_PRINT("error:ioctl(pctx->handle , 1, &oper) returned %d\n",ret); + return UCI_ERROR; + } + + return UCI_SUCCESS; +#else + int ret; + uci_context_s *ucictx = (uci_context_s *)oh; + if(ucictx == NULL) + { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)ucictx->imp)->SE_process((CryptoCoreContainer*)(ucictx->imp), input, input_len, output, output_len); + if(ret != CRYPTO_SUCCESS) + { + return UCI_ERROR; + } + return UCI_SUCCESS; + +#endif +} + +int hwcrypto_se_final(UCI_HANDLE oh, unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len) +{ +#ifndef PC_I586 + uci_context_s *pctx = NULL; + struct crypt_oper oper; + struct crypt_info *info = NULL; + int ret = -1; + int hndl = -1; + unsigned int blocksize = 0; + unsigned int alg = 0; + unsigned int padlen = 0; + unsigned int len = 0; + unsigned int lastlen = 0; + unsigned char padding[32] = {0x0}; + + memset(padding, 0, sizeof(padding)/sizeof(padding[0])); + memset(&oper, 0, sizeof(struct crypt_oper)); + pctx = (uci_context_s*)oh; + if(pctx == NULL) + { + return UCI_INVALID_HANDLE; + } + + info = (struct crypt_info*) pctx->imp; + if(info == NULL) + { + return UCI_INVALID_HANDLE; + } + hndl = pctx->handle; + alg = pctx->alg; + if(hndl < 0) + { + return UCI_INVALID_HANDLE; + } + if(alg == ID_UCI_AES128 || alg == ID_UCI_AES256) + { + blocksize = 16; + } + else if(alg == ID_UCI_DES|| alg == ID_UCI_TDES) + { + blocksize = 8; + } + else + { + return +UCI_INVALID_HANDLE; + } + + if(pctx->mode == ID_UCI_ENC_CBC || pctx->mode == ID_UCI_ENC_CTR || pctx->mode == ID_UCI_ENC_ECB)/*encrypt*/ + { + lastlen = input_len % blocksize; + if(input_len > lastlen ) /* last blocksize is bigger than blocksize or equal to blocksize*/ + { + len = input_len -lastlen; + ret = hwcrypto_se_process(oh,input,len,output,output_len); + if(ret != UCI_SUCCESS) + { + TA_PRINT("hwcrypto_se_process error \n"); + return ret; + } + } + if(MI_GET_PADDING(info->mode) == _PAD_PKCS7_)/*do padding*/ + { + + if(lastlen >0) + { + memcpy(padding, input + len, lastlen); + } + memset(padding + lastlen, blocksize - lastlen, blocksize - lastlen); + oper.src_addr = padding; + oper.src_len = blocksize; + oper.dst_addr = output + len; + oper.dst_len = output_len; + //oper.final = 1; + + if(ret = ioctl(hndl, IOCTL_CRYPTO_CRYPT, &oper)) + { + TA_PRINT("error:ioctl(hndl, 1, &oper) returned %d\n",ret); + return UCI_ERROR; + } + + *output_len = input_len - lastlen + blocksize; + } + if(MI_GET_PADDING(info->mode) == _PAD_NO_)/*do padding*/ + { + if(lastlen >0) + { + memcpy(output + len, output + len, lastlen); + } + *output_len = input_len ; + } + } + else/*decrypt*/ + { + lastlen = input_len % blocksize; + if(input_len > lastlen) + { + len = input_len -lastlen; + } + if(len > 0) + { + + oper.src_addr = (char *)input; + oper.src_len = len; + oper.dst_addr = (char *)output; + oper.dst_len = output_len; + //oper.final = 1; + if (ret = ioctl(hndl, IOCTL_CRYPTO_CRYPT, &oper)) + { + TA_PRINT("error:ioctl(hndl, 1, &oper) returned %d\n",ret); + return UCI_ERROR; + } + } + if(MI_GET_PADDING(info->mode) == _PAD_NO_)/*do padding*/ + { + if(lastlen >0) + { + memcpy(output + len, input + len, lastlen); + } + *output_len = input_len ; + } + if(MI_GET_PADDING(info->mode) == _PAD_PKCS7_)/*de padding*/ + { + if(lastlen >0) + { + TA_PRINT("psrc_len is not aligen to %d\n",blocksize); + return UCI_ERROR; + } + + padlen = output[input_len -1]; + //PrintBYTE("padding",output,input_len); + //PrintBYTE("input",input,input_len); + if(padlen < 1 || padlen > 16) + { + *output_len = 0; + TA_PRINT("padding size{%d} is incorretc ",padlen); + return UCI_ERROR; + } + memset(padding, padlen, blocksize); + if(memcmp(output + input_len - padlen ,padding, padlen) != 0) + { + *output_len = 0; + TA_PRINT("padding size{%d} is incorretc ",padlen); + return UCI_ERROR; + } + + *output_len = input_len - padlen; + } + + } + + return UCI_SUCCESS; +#else + int ret; + uci_context_s *ucictx = (uci_context_s *)oh; + if(ucictx==NULL) + { + return UCI_INVALID_HANDLE; + } + ret = ((CryptoCoreContainer *)ucictx->imp)->SE_final((CryptoCoreContainer*)(ucictx->imp), input, input_len, output, output_len); + if(ret!=CRYPTO_SUCCESS) + { + return UCI_ERROR; + } + return UCI_SUCCESS; + +#endif +} + diff --git a/ssflib/inc/app_debug.h b/ssflib/inc/app_debug.h new file mode 100755 index 0000000..30b14de --- /dev/null +++ b/ssflib/inc/app_debug.h @@ -0,0 +1,75 @@ + +/** + * @file app_debug.h + * @brief + * @author longhai.wu (longhai.wu@samsung.com) + * @version 0.9 Initial Draft Version + * @date 2013/04/13 + * - Revision History : + * Version Date Author Detail description + * -------------------------------------------------------------------- + * 0.9 2013/04/03 longhai.wu + * -------------------------------------------------------------------- + */ + +#ifndef _APP_DEBUG_H_ +#define _APP_DEBUG_H_ +#include +#define APP_MODULE_NAME "TrustApp" +#define ONE_TIME_PRINT_LENGTH_MAX 10240 +unsigned char one_time_print_buffer[ONE_TIME_PRINT_LENGTH_MAX]; +extern int g_app_svc_dbglvl; + + +unsigned char one_time_print_buffer_test[10240]; + +//!disable all msg +#define TRUSTAPP_DEBUG_LEVEL_NON 0 +//!enable message level > ERROR +#define TRUSTAPP_DEBUG_LEVEL_ERR 1 +//!enable message level > WARNING +#define TRUSTAPP_DEBUG_LEVEL_WRN 2 +//!enable message level > DEBUG +#define TRUSTAPP_DEBUG_LEVEL_DBG 3 +//!enable message level > LOG/INFO +#define TRUSTAPP_DEBUG_LEVEL_LOG 4 +//!enable all level +#define TRUSTAPP_DEBUG_LEVEL_ALL 5 + + +#define APP_SVC_ERR(title, format,...) do{sprintf(one_time_print_buffer,"[%s][ERR]" format, title,##__VA_ARGS__);\ + }while(0); +#define APP_SVC_WRN(title, format,...) do{sprintf(one_time_print_buffer,"[%s][WRN]" format, title,##__VA_ARGS__);\ + app_print_log(one_time_print_buffer);\ + }while(0); +#define APP_SVC_DBG(title, format,...) do{sprintf(one_time_print_buffer,"[%s][DBG]" format, title,##__VA_ARGS__);\ + app_print_log(one_time_print_buffer);\ + }while(0); +#define APP_SVC_LOG(title, format,...) do{sprintf((char *)one_time_print_buffer,"[%s][LOG]" format, title,##__VA_ARGS__);\ + app_print_log(one_time_print_buffer);\ + }while(0); + +#define APP_SVC_LOG_test(title, format,...) do{sprintf(()one_time_print_buffer_test,"[%s][LOG]" format, title,##__VA_ARGS__);\ + app_print_log_test(one_time_print_buffer_test);\ + }while(0); + +#define TURST_APP_LOG_TEST(fmt,...) {APP_SVC_LOG_test("test", fmt, ##__VA_ARGS__)} + +#define TURST_APP_ERR(fmt, ...) if(g_app_svc_dbglvl >= TRUSTAPP_DEBUG_LEVEL_ERR) {APP_SVC_ERR(APP_MODULE_NAME, fmt, ##__VA_ARGS__)} +#define TURST_APP_WRN(fmt, ...) if(g_app_svc_dbglvl >= TRUSTAPP_DEBUG_LEVEL_WRN) {APP_SVC_WRN(APP_MODULE_NAME, fmt, ##__VA_ARGS__)} +#define TURST_APP_DBG(fmt, ...) if(g_app_svc_dbglvl >= TRUSTAPP_DEBUG_LEVEL_DBG) {APP_SVC_DBG(APP_MODULE_NAME, fmt, ##__VA_ARGS__)} +#define TURST_APP_LOG(fmt, ...) if(g_app_svc_dbglvl >= TRUSTAPP_DEBUG_LEVEL_LOG) {APP_SVC_LOG(APP_MODULE_NAME, fmt, ##__VA_ARGS__)} +//#define TURST_APP_LOG(fmt, ...) TURST_APP_LOG_TEST(fmt,##__VA_ARGS__) + + + +#define TRACE_FUNCTION_IN TURST_APP_LOG("[%s][%d] In ... \n",__FUNCTION__,__LINE__); +#define TRACE_FUNCTION_OUT TURST_APP_LOG("[%s][%d] Out ... \n",__FUNCTION__,__LINE__); + +int app_open_log_file( char *processName); +void app_print_log(unsigned char logBuffer[]); +void app_close_log_file(void); + +void app_print_log_test(unsigned char logBuffer[]); + +#endif diff --git a/ssflib/inc/ssf_client.h b/ssflib/inc/ssf_client.h new file mode 100755 index 0000000..2d50d8d --- /dev/null +++ b/ssflib/inc/ssf_client.h @@ -0,0 +1,34 @@ +/* + * ===================================================================================== + * + * Filename: ssfclient.h + * + * Description: SSF client header file + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Cheryl (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef SSF_CLIENT_H_ +#define SSF_CLIENT_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include "tee_command.h" +#include "log.h" + +int32_t connecttoServer(void); +void disconnectfromServer(int32_t ServerSocket); +uint32_t sendCommand(int32_t sockfd, TEE_CMD cmd, void* data, size_t size); + +#endif /* SSF_CLIENT_H_ */ diff --git a/ssflib/inc/ssf_lib.h b/ssflib/inc/ssf_lib.h new file mode 100755 index 0000000..0726a10 --- /dev/null +++ b/ssflib/inc/ssf_lib.h @@ -0,0 +1,45 @@ +/* + * ===================================================================================== + * + * Filename: ssflib.h + * + * Description: SSF Lib header file + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef SSF_LIB_H_ +#define SSF_LIB_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_internal_api.h" +#include "teestub_command_data.h" +#include "OsaLinuxUser.h" +#include + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +typedef struct { + bool isPanicSet; + bool thisTaskCancel; + bool thisTaskMask; +} TeeStubSSFSharedData; + +extern pthread_mutex_t socketLock; +//TODO: clean up this variable location. This is not the right place +extern TeeStubSSFSharedData sharedData; +extern int32_t socketSimulatorDaemonFD; +extern TEE_UUID ssf_sharedthisTAUUID; + +#endif /* SSF_LIB_H_ */ diff --git a/ssflib/inc/ssf_storage.h b/ssflib/inc/ssf_storage.h new file mode 100755 index 0000000..0000976 --- /dev/null +++ b/ssflib/inc/ssf_storage.h @@ -0,0 +1,263 @@ +/* + * ===================================================================================== + * + * Filename: ssf_storage.h + * + * Description: SSF Storage header file + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +#ifndef SSF_STORAGE_H_ +#define SSF_STORAGE_H_ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "tee_internal_api.h" +#include +#include +#include +#include +#include "ss_api.h" +#include "uci_api.h" +#include +#include + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + +#define MSG(fmt, ARG...) printf(fmt"\n", ##ARG) + +#define MAX_ATTRIBUTE_NUMBER 35 // Maximum number of attributes for each object +#define FLAG_STORAGE_ENUMERATOR 0x20000000 + +#define PO_FILE_NAME_MAX_LEN 128 +#define PO_FILE_KEY_MAT_SIZE 64 +#define PO_FILE_KEY_SIZE 16 +#define PO_FILE_HASH_SIZE 20 +#define BLOCK_SIZE 16 + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +// structure definition +struct __TEE_Attributees { + int attr_number; + TEE_Attribute attr_array[MAX_ATTRIBUTE_NUMBER]; +}; + +typedef struct { + TEE_ObjectInfo info; + struct __TEE_Attributees attr; +} TransientObject; + +struct __TEE_ObjectHandle { + TransientObject tr; +}; + +typedef struct { + char object_id[TEE_OBJECT_ID_MAX_LEN]; + int obj_id_len; + TEE_ObjectInfo info; +} persistent_object_info; + +// share rules check +typedef struct _po_user { + volatile int lock; + uint32_t x_user; + uint32_t rs_user; + uint32_t ws_user; + uint32_t rws_user; +} po_user; + +typedef struct { + char name[PO_FILE_NAME_MAX_LEN + 1]; + int fd; + po_user* usr_info; +} po_share_info; + +typedef struct { + uint32_t storageID; // reserved + ss_credential_s cred; + char filename[PO_FILE_NAME_MAX_LEN]; + int b_inited; + int po_num; + persistent_object_info* po_info; +} po_info_file; + +typedef struct { + ss_credential_s cred; + char file_name[PO_FILE_NAME_MAX_LEN + 1]; + TEE_ObjectInfo po_info; + // attr + uint8_t* attr; + uint32_t attr_size; + // data + uint8_t* object_data; + uint32_t obj_data_size; +} persistent_object_file; + +// persisent object list +struct _persistent_object; + +typedef struct _po_list_node { + struct _persistent_object* po; + struct _po_list_node* next; + struct _po_list_node* prev; +} po_list_node; + +typedef struct _persistent_object { + TransientObject attr; + uint32_t storage_id; + TEE_UUID TA_UUID; + char object_id[TEE_OBJECT_ID_MAX_LEN]; + int obj_id_len; + persistent_object_file po_file; + po_share_info share_info; + struct _po_list_node po_list; +} persistent_object; + +typedef enum { + ENUM_STATE_INIT, ENUM_STATE_STARTED, ENUM_STATE_END +} enumerator_state; + +struct __TEE_ObjectEnumHandle { + persistent_object_info* po_info; + int po_num; + int curr_position; + enumerator_state state; +}; + +extern po_list_node g_po_list; + +extern po_info_file g_po_info_file; + +#if 0 +// Generic Object Functions +void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo* objectInfo); +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage); +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, uint32_t attributeID, void* buffer, size_t* size); +TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, uint32_t attributeID, uint32_t* a, uint32_t* b); +void TEE_CloseObject(TEE_ObjectHandle object); + +// Transient Object Functions +TEE_Result TEE_AllocateTransientObject(uint32_t objectType, uint32_t maxObjectSize, TEE_ObjectHandle* object); +void TEE_FreeTransientObject(TEE_ObjectHandle object); +void TEE_ResetTransientObject(TEE_ObjectHandle object); +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, TEE_Attribute* attrs, uint32_t attrCount); +void TEE_InitRefAttribute(TEE_Attribute* attr, uint32_t attributeID, void* buffer, size_t length); +void TEE_InitValueAttribute(TEE_Attribute* attr, uint32_t attributeID, uint32_t a, uint32_t b); +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, TEE_ObjectHandle srcObject); +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, TEE_Attribute* params, uint32_t paramCount); + +// Persistent Object Functions +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, void* objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, void* initialData, size_t initialDataLen, TEE_ObjectHandle* object); +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, void* objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle* object); +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object); +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, void* newObjectID, size_t newObjectIDLen); + +// Persistent Object Enumeration Functions +TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle* objectEnumerator); +void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); +void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); +TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator, uint32_t storageID); +TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, TEE_ObjectInfo* objectInfo, void* objectID, size_t* objectIDLen); + +// Data Stream Access Functions +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void* buffer, size_t size, uint32_t* count); +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, void* buffer, size_t size); +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size); +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, TEE_Whence whence); +#endif + +// attribute operations +TEE_Result copy_attribute(TEE_Attribute* dest, TEE_Attribute* src); +void free_attribute(TEE_Attribute* attr); + +//internal transient object operations +TEE_Result allocate_transient_object(TransientObject* tr, uint32_t objectType, + uint32_t maxObjectSize); +size_t calc_attr_size(TransientObject* tr); +TEE_Result serialise_attr(TransientObject* tr, char* buf); +TEE_Result deserialise_attr(char* buf, TransientObject* tr); + +// internal persistent object operations +TEE_Result allocate_persistent_object(persistent_object** po, + uint32_t storageID, const void* objectID, size_t objectIDLen, + uint32_t flags); +TEE_Result create_po(persistent_object* po, TransientObject* attr, + const void* init_data, size_t data_size); +TEE_Result open_po(persistent_object* po); +TEE_Result read_object_data(persistent_object* po, void* buffer, size_t size, + uint32_t* count); +TEE_Result seek_object_data(persistent_object* po, int32_t offset, + TEE_Whence whence); +TEE_Result write_object_data(persistent_object* po, const void* buffer, + size_t size); +TEE_Result truncate_object_data(persistent_object* po, size_t size); +void close_po(persistent_object* po); +TEE_Result free_po(persistent_object* po); +TEE_Result rename_po(persistent_object* po, const void* newObjectID, + size_t newObjectIDLen); +TEE_Result exist_po(persistent_object* po); +void init_po(persistent_object* po); + +// persistent object file operations +int derive_po_file_name(const void* obj_id, int obj_id_len, char* fn); +int load_po_file(persistent_object* po); +int write_po_file(persistent_object* po); +int rename_po_file(persistent_object* po, const void* newObjectID, + size_t newObjectIDLen); +void clean_po_file(persistent_object* po); +int delete_po_file(persistent_object* po); + +// po info file +int init_po_info_file(po_info_file* pi_file); +int load_po_info_file(po_info_file* pi_file); +int get_po_info(po_info_file* pi_file, persistent_object_info** po_info, + int* po_num); +int write_po_info(po_info_file* pi_file, const void* objectID, + uint32_t obj_id_len, TEE_ObjectInfo* info); +int delete_po_info(po_info_file* pi_file, const void* objectID, + uint32_t obj_id_len); +persistent_object_info* find_po_info(po_info_file* pi_file, + const void* objectID, uint32_t obj_id_len); + +// po share rule +int init_share_info(po_share_info* share_info); +int check_share_rule(po_share_info* share_info, uint32_t handleFlags); +int update_share_info(po_share_info* share_info, uint32_t handleFlags, + int b_open); +int release_share_info(po_share_info* share_info); +void lock_po_share_info(po_share_info* share_info); +void unlock_po_share_info(po_share_info* share_info); + +// po list operations +void add_to_po_list(persistent_object* po); +void rem_from_po_list(persistent_object* po); +void cleanup(); +void regist_clean_up(); + +// misc +void byte_to_hex(uint8_t* dest, const uint8_t* src, unsigned long src_len); +void convert_TA_UUID(char* uuid, TEE_UUID TA_UUID); +int gen_random(uint8_t* dest, uint8_t data_len); + +#ifdef __cplusplus +} +#endif + +#endif /* SSF_STORAGE_H_ */ diff --git a/ssflib/src/app_debug.c b/ssflib/src/app_debug.c new file mode 100755 index 0000000..8db9d26 --- /dev/null +++ b/ssflib/src/app_debug.c @@ -0,0 +1,108 @@ +/** + * @file app_debug.h + * @brief + * @author longhai.wu (longhai.wu@samsung.com) + * @version 0.9 Initial Draft Version + * @date 2013/04/13 + * - Revision History : + * Version Date Author Detail description + * -------------------------------------------------------------------- + * 0.9 2013/04/03 longhai.wu + * -------------------------------------------------------------------- + */ + +#include +#include +#include + +//#define PRINT_LOG_TO_CONSOLE +#ifdef PRINT_LOG_TO_CONSOLE +#include +#define portname "/dev/ttyS0" +static int m_fd = -1; +int g_app_svc_dbglvl = TRUSTAPP_DEBUG_LEVEL_NON; + +int app_open_log_file( char *processName) +{ + + /* save log to LOGFILE */ + + m_fd = open( portname,O_RDWR | O_NOCTTY | O_NONBLOCK); + if(m_fd < 0) + { + return -1; + } + + write(m_fd,processName,strlen(processName)); + + memset(one_time_print_buffer,0,sizeof(one_time_print_buffer)); + return 0; + +} + +void app_close_log_file(void) +{ + + close(m_fd); + m_fd = -1; +} +void app_print_log(unsigned char logBuffer[]) +{ + + write(m_fd,logBuffer,strlen(logBuffer)); +} + +#else +#define SVC1_LOGFILE "/opt/usr/apps/tz_simulator/data/SWDLog.txt" + +static FILE *fp = NULL; + +#ifdef _TURN_ON_TALOG_ +int g_app_svc_dbglvl = TRUSTAPP_DEBUG_LEVEL_ALL; +#else +int g_app_svc_dbglvl = TRUSTAPP_DEBUG_LEVEL_NON; +#endif + +int app_open_log_file(char *processName) +{ + + /* save log to LOGFILE */ + fp = fopen(SVC1_LOGFILE, "a+"); + if(!fp) + { + return -1; + } + + fprintf(fp,"Trust App name : %s.\n",processName); + fflush(fp); + + memset(one_time_print_buffer,0,sizeof(one_time_print_buffer)); + return 0; + +} + +void app_close_log_file(void) +{ + + fclose(fp); + fp = NULL; +} +void app_print_log(unsigned char logBuffer[]) +{ + + fprintf(fp,"%s",logBuffer); + fflush(fp); +} + +void app_print_log_test(unsigned char logBuffer[]) +{ + + fprintf(fp,"%s",logBuffer); + fflush(fp); +} + + + + +#endif + diff --git a/ssflib/src/ssf_arithmetic.c b/ssflib/src/ssf_arithmetic.c new file mode 100755 index 0000000..cbe4e68 --- /dev/null +++ b/ssflib/src/ssf_arithmetic.c @@ -0,0 +1,741 @@ +/* + * ===================================================================================== + * + * Filename: ssf_arithmetic.c + * + * Description: SSF arithmetic functions + * + * Version: 1.0 + * Created: 29 June 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Cheryl (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include "tee_internal_api.h" +#include "CC_API.h" +#include "base/cc_bignum.h" + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define TAG SSF_LIB +#define SDRM_API_METADATA_LENGTH_IN_U32 4 +#define CNT_OF_BIT_IN_BYTE 8 +#define PASS_NOT_IMP_CODE + +/*----------------------------------------------------------------------------- + * TEE API implementation + *-----------------------------------------------------------------------------*/ +/** + * The TEE_BigIntInit function initializes bigInt and sets its represented + * value to zero. This function assumes that bigInt points to a memory area + * of len uint32_t. + * @param value A pointer to the TEE_BigInt to be initialized + * @param length The size in uint32_t of the memory pointed to by bigInt + */ +void TEE_BigIntInit(TEE_BigInt* value, const size_t length) { + + LOGD(TAG, "TEE_BigIntInit - length : %d", length); + uint32_t teeMaxBigIntSize; + TEE_Result result = TEE_GetPropertyAsU32( + (TEE_PropSetHandle)TEE_PROPSET_TEE_IMPLEMENTATION, + "gpd.tee.arith.maxBigIntSize", &teeMaxBigIntSize); + LOGD(TAG, "TEE_GetPropertyAsU32(arith.maxBigIntSize) : %d (ret:%d)", + teeMaxBigIntSize, result); +#ifndef PASS_NOT_IMP_CODE + if(result == TEE_SUCCESS) + { + if(teeMaxBigIntSize == 0 || + (length - SDRM_API_METADATA_LENGTH_IN_U32) * SDRM_SIZE_OF_DWORD * CNT_OF_BIT_IN_BYTE < teeMaxBigIntSize) + { + LOGE(TAG, "Panic Reason: BN size is creater than max allowed"); + TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); + } + } +#endif + if (length <= SDRM_API_METADATA_LENGTH_IN_U32) { + LOGE(TAG, "Panic Reason: insufficient length"); + TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); + } + SDRM_BIG_NUM *bn = SDRM_BN_Alloc((cc_u8*)value, + length - SDRM_API_METADATA_LENGTH_IN_U32); + if (bn == NULL) { + LOGE(TAG, "Panic Reason: SDRM_BN_Alloc fail"); + TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); + } + LOGD(TAG, "Success"); +} + +/** + * The TEE_BigIntConvertFromOctetString function converts a bufferLen byte + * octet string buffer into a TEE_BigInt format. The octet string is in most + * significant byte first representation. The input parameter sign will set + * the sign of dest. It will be set to negative if sign<0 and to positive if + * sign>=0. + * @param dest Pointer to a TEE_BigInt to hold the result + * @param buffer Pointer to the buffer containing the octet string + * representation of the integer + * @param sz_buffer The length of *buffer in bytes + * @param sign The sign of dest is set to the sign of sign + */ +TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt* dest, + const uint8_t* buffer, const size_t sz_buffer, const int32_t sign) { + + LOGD(TAG, + "TEE_BigIntConvertFromOctetString - dest:%p buffer:%p sz_buffer:%d sign:%d", + dest, buffer, sz_buffer, sign); + TEE_Result result = TEE_SUCCESS; + SDRM_BIG_NUM *bn = (SDRM_BIG_NUM*)dest; + + if (bn->Size * SDRM_SIZE_OF_DWORD < sz_buffer) { + LOGD(TAG, "Fail Reason: TEE_ERROR_OVERFLOW(%d %d)", + bn->Size * SDRM_SIZE_OF_DWORD, sz_buffer); + return TEE_ERROR_OVERFLOW; + } + int ret = SDRM_OS2BN((cc_u8*)buffer, sz_buffer, bn); + if (ret == CRYPTO_SUCCESS) { + bn->sign = ((sign < 0) ? 1 : 0); + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_OS2BN fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } + return result; +} + +/** + * The TEE_BigIntConvertToOctetString function converts the absolute value of + * an integer in TEE_BigInt format into an octet string. The octet string is + * written in a most significant byte first representation. + * @param buffer Output buffer where converted octet string representation + * of the integer is written + * @param sz_buffer_out The length of *buffer in bytes + * @param value Pointer to the integer that will be converted to an octet + * string + */ +TEE_Result TEE_BigIntConvertToOctetString(void* buffer, size_t* sz_buffer_out, + const TEE_BigInt* value) { + + LOGD(TAG, "TEE_BigIntConvertToOctetString - buffer:%p value:%p", buffer, + value); + TEE_Result result = TEE_SUCCESS; + SDRM_BIG_NUM *bn = (SDRM_BIG_NUM*)value; + if (*sz_buffer_out == 0) { + if (bn->Length != 0) { + *sz_buffer_out = bn->Length * 4; + result = TEE_ERROR_SHORT_BUFFER; + } + return result; + } + int ret = SDRM_BN2OS(bn, *sz_buffer_out, (cc_u8 *)buffer); + if (ret == CRYPTO_BUFFER_TOO_SMALL || ret == CRYPTO_NULL_POINTER) { + LOGD(TAG, "Fail Reason: CRYPTO_BUFFER_TOO_SMALL or CRYPTO_NULL_POINTER"); + *sz_buffer_out = bn->Length * 4; + result = TEE_ERROR_SHORT_BUFFER; + } else if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN2OS fail(%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } + return result; +} + +/** + * The TEE_BigIntConvertFromS32 function sets *result to the value input. + * @param result Pointer to a TEE_BigInt to store the result + * @param input Input value + */ +void TEE_BigIntConvertFromS32(TEE_BigInt* result, const int32_t input) { + SDRM_BIG_NUM *bn = (SDRM_BIG_NUM*)result; + bn->pData[0] = ((input < 0) ? (input * -1) : (input)); + bn->Length = 1; + bn->sign = ((input < 0) ? 1 : 0); + LOGD(TAG, "Success"); +} + +/** + * The TEE_BigIntConvertToS32 function sets *result to the value of input, + * including the sign of input. If input does not fit within an int32_t, + * the value of *result is undefined. + * @param result Pointer to an int32_t to store the result + * @param input Pointer to the input value + */ +TEE_Result TEE_BigIntConvertToS32(int32_t* value_result, + const TEE_BigInt* input) { + SDRM_BIG_NUM *bn = (SDRM_BIG_NUM*)input; + *value_result = (bn->sign == 1) ? (bn->pData[0] * -1) : (bn->pData[0]); + LOGD(TAG, "Success"); + return TEE_SUCCESS; +} + +/** + * The TEE_BigIntCmp function checks whether op1>op2, op1==op2, or op1value2, + * value1_raw==value2, or value1_raw value2) + ret = 1; + else ret = -1; + return ret; +} + +/** + * The TEE_BigIntShiftRight function computes + * |destination_raw| = |source_raw| >> bits and destination_raw will have the + * same sign as source_raw.4 If bits is greater than the bit length of + * source_raw then the result is zero. destination_raw and source_raw MAY + * point to the same memory region. + * @param destination_raw Pointer to TEE_BigInt to hold the shifted result + * @param source_raw Pointer to the operand to be shifted + * @param bits Number of bits to shift + */ +void TEE_BigIntShiftRight(TEE_BigInt* destination_raw, + const TEE_BigInt* source_raw, const size_t bits) { + SDRM_BIG_NUM *dstBn = (SDRM_BIG_NUM*)destination_raw; + SDRM_BIG_NUM *srcBn = (SDRM_BIG_NUM*)source_raw; + int ret = SDRM_BN_SHR(dstBn, srcBn, bits); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_SHR fail"); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntGetBit function returns the indexth bit of the natural binary + * representation of |object_raw|. A true return value indicates a “1” and a + * false return value indicates a “0” in the indexth position. If index is + * larger than the number of bits in object_raw, the return value is false, + * thus indicating a “0”. + * @param object_raw Pointer to the integer + * @param index The offset of the bit to be read, starting at offset 0 for the + * least significant bit + */ +bool TEE_BigIntGetBit(const TEE_BigInt* object_raw, const uint32_t index) { + SDRM_BIG_NUM *objBn = (SDRM_BIG_NUM*)object_raw; + bool bitValue = (bool)SDRM_BN_num_bits_index(objBn, index); + LOGD(TAG, "Success"); + return bitValue; + +} + +/** + * The TEE_BigIntGetBitCount function returns the number of bits in the + * natural binary representation of |object_raw|; that is, the magnitude of + * object_raw. + * @param object_raw Pointer to the integer + */ +uint32_t TEE_BigIntGetBitCount(const TEE_BigInt* object_raw) { + SDRM_BIG_NUM *objBn = (SDRM_BIG_NUM*)object_raw; + int retCnt = SDRM_BN_num_bits(objBn); + LOGD(TAG, "Success"); + return retCnt; +} + +/** + * The TEE_BigIntAdd function computes dest = op1 + op2. All or some of dest, + * op1, and op2 MAY point to the same memory region. + * @param dest Pointer to TEE_BigInt to store the result op1 + op2 + * @param op1 Pointer to the first operand + * @param op2 Pointer to the second operand + */ +void TEE_BigIntAdd(TEE_BigInt* dest, const TEE_BigInt* op1, + const TEE_BigInt* op2) { + SDRM_BIG_NUM *bn1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bn2 = (SDRM_BIG_NUM*)op2; + SDRM_BIG_NUM *dst = (SDRM_BIG_NUM*)dest; + int ret = SDRM_BN_Add(dst, bn1, bn2); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_Add fail"); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntSub function computes dest = op1 – op2. All or some of dest, + * op1, and op2 MAY point to the same memory region. + * @param dest Pointer to TEE_BigInt to store the result op1 - op2 + * @param op1 Pointer to the first operand + * @param op2 Pointer to the second operand + */ +void TEE_BigIntSub(TEE_BigInt* dest, const TEE_BigInt* op1, + const TEE_BigInt* op2) { + SDRM_BIG_NUM *bn1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bn2 = (SDRM_BIG_NUM*)op2; + SDRM_BIG_NUM *dst = (SDRM_BIG_NUM*)dest; + int ret = SDRM_BN_Sub(dst, bn1, bn2); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_Sub fail"); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntNeg function negates an operand: dest = -op. dest and op MAY + * point to the same memory region. + * @param dest Pointer to TEE_BigInt to store the result -op + * @param op Pointer to the operand to be negated + */ +void TEE_BigIntNeg(TEE_BigInt* dest, const TEE_BigInt* op) { + SDRM_BIG_NUM *bnOp = (SDRM_BIG_NUM*)op; + if (dest == op) + bnOp->sign = ((bnOp->sign == 1) ? 0 : 1); + else { + SDRM_BIG_NUM *dst = (SDRM_BIG_NUM*)dest; + SDRM_BN_Copy(dst, bnOp); + dst->sign = ((dst->sign == 1) ? 0 : 1); + } + LOGD(TAG, "Success"); +} + +/** + * The TEE_BigIntMul function computes dest = op1 * op2. All or some of dest, + * op1, and op2 MAY point to the same memory region. + * @param dest Pointer to TEE_BigInt to store the result op1 * op2 + * @param op1 Pointer to the first operand + * @param op2 Pointer to the second operand + */ +void TEE_BigIntMul(TEE_BigInt* dest, const TEE_BigInt* op1, + const TEE_BigInt* op2) { + SDRM_BIG_NUM *bn1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bn2 = (SDRM_BIG_NUM*)op2; + SDRM_BIG_NUM *dst = (SDRM_BIG_NUM*)dest; + int ret = SDRM_BN_Mul(dst, bn1, bn2); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_Mul fail"); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntSquare function computes dest = op * op. dest and op MAY point + * to the same memory region. + * @param dest Pointer to TEE_BigInt to store the result op * op + * @param op Pointer to the operand to be squared + */ +void TEE_BigIntSquare(TEE_BigInt* dest, const TEE_BigInt* op) { + TEE_BigIntMul(dest, op, op); + LOGD(TAG, "Called"); +} + +/** + * The TEE_BigIntDiv function computes dest_r and dest_q such that + * op1 = dest_q * op2 + dest_r. It will round dest_q towards zero and dest_r + * will have the same sign as op1. + * @param dest_q Pointer to a TEE_BigInt to store the quotient. + * dest_q can be NULL. + * @param dest_r Pointer to a TEE_BigInt to store the remainder. + * dest_r can be NULL. + * @param op1 Pointer to the first operand, the dividend + * @param op2 Pointer to the second operand, the divisor + */ +void TEE_BigIntDiv(TEE_BigInt* dest_q, TEE_BigInt* dest_r, + const TEE_BigInt* op1, const TEE_BigInt* op2) { + SDRM_BIG_NUM *dst_q = (SDRM_BIG_NUM*)dest_q; + SDRM_BIG_NUM *dst_r = (SDRM_BIG_NUM*)dest_r; + SDRM_BIG_NUM *bn1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bn2 = (SDRM_BIG_NUM*)op2; + + if (dst_q == NULL) { + SDRM_BIG_NUM *tmp = SDRM_BN_Init(bn1->Size); + if (tmp != NULL) { + SDRM_BN_Copy(tmp, bn1); + dst_q = tmp; + } + } + int ret = SDRM_BN_Div(dst_q, dst_r, bn1, bn2); + if ((void*)dst_q != (void*)dest_q) { + SDRM_BN_FREE(dst_q); + } + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_Div fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntMod function computes dest = op (mod n) such that + * 0 <= dest < n. dest and op MAY point to the same memory region but n MUST + * point to a unique memory region. For negative op the function follows the + * normal convention that -1 = (n-1) mod n. + * @param dest Pointer to TEE_BigInt to hold the result op (mod n). The + * result dest will be in the interval [0, n-1]. + * @param op Pointer to the operand to be reduced mod n + * @param n Pointer to the modulus. Modulus MUST be larger than 1. + */ +void TEE_BigIntMod(TEE_BigInt* dest, const TEE_BigInt* op, const TEE_BigInt* n) { + + SDRM_BIG_NUM *bnDst = (SDRM_BIG_NUM*)dest; + SDRM_BIG_NUM *bnOp = (SDRM_BIG_NUM*)op; + SDRM_BIG_NUM *bnN = (SDRM_BIG_NUM*)n; + int32_t integerN = 0; + TEE_BigIntConvertToS32(&integerN, (TEE_BigInt*)bnN); + if (integerN < 2) { + LOGE(TAG, "Panic Reason: Modulus should be large than 2"); + TEE_Panic(TEE_ERROR_GENERIC); + } + int ret = SDRM_BN_ModRed(bnDst, bnOp, bnN); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_ModRed fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntAddMod function computes dest = (op1 + op2) (mod n). All or + * some of dest, op1, and op2 MAY point to the same memory region but n MUST + * point to a unique memory region. + * @param dest Pointer to TEE_BigInt to hold the result (op1 + op2) (mod n) + * @param op1 Pointer to the first operand. Operand MUST be in the interval + * [0,n-1]. + * @param op2 Pointer to the second operand. Operand MUST be in the interval + * [0,n-1]. + * @param n Pointer to the modulus. Modulus MUST be larger than 1. + */ +void TEE_BigIntAddMod(TEE_BigInt* dest, const TEE_BigInt* op1, + const TEE_BigInt* op2, const TEE_BigInt* n) { + + SDRM_BIG_NUM *bnDst = (SDRM_BIG_NUM*)dest; + SDRM_BIG_NUM *bnOp1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bnOp2 = (SDRM_BIG_NUM*)op2; + SDRM_BIG_NUM *bnN = (SDRM_BIG_NUM*)n; + int32_t integerN = 0; + TEE_BigIntConvertToS32(&integerN, (TEE_BigInt*)bnN); + if (integerN < 2) { + LOGE(TAG, "Panic Reason: Modulus should be large than 2"); + TEE_Panic(TEE_ERROR_GENERIC); + } + int ret = SDRM_BN_ModAdd(bnDst, bnOp1, bnOp2, bnN); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_ModAdd fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntSubMod function computes dest = (op1 - op2) (mod n). All or + * some of dest, op1, and op2 MAY point to the same memory region but n MUST + * point to a unique memory region. + * @param dest Pointer to TEE_BigInt to hold the result (op1 - op2) (mod n) + * @param op1 Pointer to the first operand. Operand MUST be in the interval + * [0,n-1]. + * @param op2 Pointer to the second operand. Operand MUST be in the interval + * [0,n-1]. + * @param n Pointer to the modulus. Modulus MUST be larger than 1. + */ +void TEE_BigIntSubMod(TEE_BigInt* dest, const TEE_BigInt* op1, + const TEE_BigInt* op2, const TEE_BigInt* n) { + + SDRM_BIG_NUM *bnDst = (SDRM_BIG_NUM*)dest; + SDRM_BIG_NUM *bnOp1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bnOp2 = (SDRM_BIG_NUM*)op2; + SDRM_BIG_NUM *bnN = (SDRM_BIG_NUM*)n; + int32_t integerN = 0; + TEE_BigIntConvertToS32(&integerN, (TEE_BigInt*)bnN); + if (integerN < 2) { + LOGE(TAG, "Panic Reason: Modulus should be large than 2"); + TEE_Panic(TEE_ERROR_GENERIC); + } + int ret = SDRM_BN_ModSub(bnDst, bnOp1, bnOp2, bnN); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_ModSub fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntMulMod function computes dest = (op1 * op2) (mod n). All or + * some of dest, op1, and op2 MAY point to the same memory region but n MUST + * point to a unique memory region. + * @param dest Pointer to TEE_BigInt to hold the result (op1 * op2) (mod n) + * @param op1 Pointer to the first operand. Operand MUST be in the interval + * [0,n-1]. + * @param op2 Pointer to the second operand. Operand MUST be in the interval + * [0,n-1]. + * @param n Pointer to the modulus. Modulus MUST be larger than 1. + */ +void TEE_BigIntMulMod(TEE_BigInt* dest, const TEE_BigInt* op1, + const TEE_BigInt* op2, const TEE_BigInt* n) { + + SDRM_BIG_NUM *bnDst = (SDRM_BIG_NUM*)dest; + SDRM_BIG_NUM *bnOp1 = (SDRM_BIG_NUM*)op1; + SDRM_BIG_NUM *bnOp2 = (SDRM_BIG_NUM*)op2; + SDRM_BIG_NUM *bnN = (SDRM_BIG_NUM*)n; + int32_t integerN = 0; + TEE_BigIntConvertToS32(&integerN, (TEE_BigInt*)bnN); + if (integerN < 2) { + LOGE(TAG, "Panic Reason: Modulus should be large than 2"); + TEE_Panic(TEE_ERROR_GENERIC); + } + int ret = SDRM_BN_ModMul(bnDst, bnOp1, bnOp2, bnN); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_ModMul fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/** + * The TEE_BigIntSquareMod function computes dest = (op * op) (mod n). + * dest and op MAY point to the same memory region but n MUST + * point to a unique memory region. + * @param dest Pointer to TEE_BigInt to hold the result (op * op) (mod n) + * @param op Pointer to the operand. Operand MUST be in the interval + * [0,n-1]. + * @param n Pointer to the modulus. Modulus MUST be larger than 1. + */ +void TEE_BigIntSquareMod(TEE_BigInt* dest, const TEE_BigInt* op, + const TEE_BigInt* n) { + + SDRM_BIG_NUM *bnN = (SDRM_BIG_NUM*)n; + int32_t integerN = 0; + TEE_BigIntConvertToS32(&integerN, (TEE_BigInt*)bnN); + if (integerN < 2) { + LOGE(TAG, "Panic Reason: Modulus should be large than 2"); + TEE_Panic(TEE_ERROR_GENERIC); + } + TEE_BigIntMulMod(dest, op, op, n); + LOGD(TAG, "Called"); +} + +/** + * The TEE_BigIntInvMod function computes dest such that dest * op = 1 (mod n). + * dest and op MAY point to the same memory region. This function assumes that + * gcd(op,n) is equal to 1. If gcd(op,n) is greater than 1 then the result is + * unreliable. + * @param dest Pointer to TEE_BigInt to hold the result (op^-1) (mod n) + * @param op Pointer to the operand. Operand MUST be in the interval + * [0,n-1]. + * @param n Pointer to the modulus. Modulus MUST be larger than 1. + */ +void TEE_BigIntInvMod(TEE_BigInt* dest, const TEE_BigInt* op, + const TEE_BigInt* n) { + + SDRM_BIG_NUM *bnDst = (SDRM_BIG_NUM*)dest; + SDRM_BIG_NUM *bnOp = (SDRM_BIG_NUM*)op; + SDRM_BIG_NUM *bnN = (SDRM_BIG_NUM*)n; + + int32_t integerOp = 0; + int32_t integerN = 0; + TEE_BigIntConvertToS32(&integerN, (TEE_BigInt*)bnN); + TEE_BigIntConvertToS32(&integerOp, (TEE_BigInt*)bnOp); + if (integerN < 2 || integerOp == 0) { + LOGE(TAG, "Panic Reason: Modulus should be large than 2"); + TEE_Panic(TEE_ERROR_GENERIC); + } + int ret = SDRM_BN_ModInv(bnDst, bnOp, bnN); + if (ret == CRYPTO_SUCCESS) { + LOGD(TAG, "Success"); + } else { + LOGE(TAG, "Panic Reason: SDRM_BN_ModInv fail(ret:%d)", ret); + TEE_Panic(TEE_ERROR_GENERIC); + } +} + +/* TODO : NOT IMPLEMENTED */ +/** + * The TEE_BigIntRelativePrime function determines whether gcd(op1, op2)==1. + * op1 and op2 MAY point to the same memory region. + * @param op1 Pointer to the first operand + * @param op2 Pointer to the second operand + */ +bool TEE_BigIntRelativePrime(const TEE_BigInt* op1, const TEE_BigInt* op2) { + (void)op1; + (void)op2; + return false; +} + +/* TODO : NOT IMPLEMENTED */ +/** + * The TEE_BigIntComputeExtendedGcd function computes the greatest common + * divisor of the input parameters op1 and op2. Furthermore it computes the + * coefficients u and v such that u*op1+v*op2==gcd. op1 and op2 MAY point to + * the same memory region. u, v, or both can be NULL. If both are NULL then + * the function only computes the gcd of op1 and op2. + * @param gcd Pointer to TEE_BigInt to hold the greatest common divisor of + * op1 and op2 + * @param u Pointer to TEE_BigInt to hold the first coefficient + * @param v Pointer to TEE_BigInt to hold the second coefficient + * @param op1 Pointer to the first operand + * @param op2 Pointer to the second operand + */ +void TEE_BigIntComputeExtendedGcd(TEE_BigInt* gcd, TEE_BigInt* u, TEE_BigInt* v, + const TEE_BigInt* op1, const TEE_BigInt* op2) { + (void)gcd; + (void)u; + (void)v; + (void)op1; + (void)op2; +} + +/* TODO : NOT IMPLEMENTED */ +/** + * The TEE_BigIntIsProbablePrime function performs a probabilistic primality + * test on op. The parameter confidenceLevel is used to specify the probability + * of a non-conclusive answer. If the function cannot guarantee that op is + * prime or composite, it MUST iterate the test until the probability that op + * is composite is less than 2^(-confidenceLevel). Values smaller than 80 for + * confidenceLevel will not be recognized and will default to 80. The maximum + * honored value of confidenceLevel is implementation-specific, but MUST be at + * least 80. + * The algorithm for performing the primality test is implementation-specific, + * but its correctness and efficiency MUST be equal to or better than the + * Miller-Rabin test. + * @param op Candidate number that is tested for primality + * @param confidenceLevel The desired confidence level for a non-conclusive + * test. This parameter (usually) maps to the number of iterations and thus to + * the running time of the test. Values smaller than 80 will be treated as 80. + */ +int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt* op, + uint32_t confidenceLevel) { + (void)op; + (void)confidenceLevel; + return 0; +} + +/** + * The TEE_BigIntFMMSizeInU32 function returns the size of the array of + * uint32_t values needed to represent an integer in the fast modular + * multiplication representation, given the size of the modulus in bits. + * This function MUST never fail. + * @param modulusSizeInBits Size of modulus in bits + */ +size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits) { + return TEE_BigIntSizeInU32(modulusSizeInBits); +} + +/** + * The TEE_BigIntInitFMM function initializes bigIntFMM and sets its + * represented value to zero. This function assumes that bigIntFMM points to + * a memory area of len uint32_t. + * @param object A pointer to the TEE_BigIntFMM to be initialized + * @param len The size in uint32_t of the memory pointed to by bigIntFMM + */ +void TEE_BigIntInitFMM(TEE_BigIntFMM* object, const size_t len) { + TEE_BigIntInit((TEE_BigInt*)object, len); +} + +/** + * The TEE_BigIntFMMContextSizeInU32 function returns the size of the array + * of uint32_t values needed to represent a fast modular context using a + * given modulus size. This function MUST never fail. + * @param modulusSizeInBits Size of modulus in bits + */ +size_t TEE_BigIntFMMContextSizeInU32(const size_t modulusSizeInBits) { + return TEE_BigIntSizeInU32(modulusSizeInBits); +} + +/** + * The TEE_BigIntInitFMMContext function calculates the necessary + * prerequisites for the fast modular multiplication and stores them in a + * context. This function assumes that context points to a memory area of + * len uint32_t. + * @param context A pointer to the TEE_BigIntFMMContext to be initialized + * @param len The size in uint32_t of the memory pointed to by context + * @param modulus The modulus, an odd integer larger than 2 and less than 2 + * to the power of gpd.tee.arith.maxBigIntSize + */ +void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext* context, const size_t len, + const TEE_BigInt* modulus) { +} + +/** + * The TEE_BigIntConvertToFMM function converts src into a representation + * suitable for doing fast modular multiplication. If the operation is + * successful, the result will be written in implementation-specific format + * into the buffer dest, which MUST have been allocated by the TA and + * initialized using TEE_BigIntInitFMM. + * @param dest Pointer to an initialized TEE_BigIntFMM memory area + * @param src Pointer to the TEE_BigInt to convert + * @param n Pointer to the modulus + * @param context Pointer to a context previously initialized using + * TEE_BigIntInitFMMContext + */ +void TEE_BigIntConvertToFMM(TEE_BigIntFMM* dest, const TEE_BigInt* src, + const TEE_BigInt* n, const TEE_BigIntFMMContext* context) { +} + +/** + * The TEE_BigIntConvertFromFMM function converts src in the fast modular + * multiplication representation back to a TEE_BigInt representation. + * @param dest Pointer to an initialized TEE_BigInt memory area to hold + * the converted result + * @param src Pointer to a TEE_BigIntFMM holding the value in the fast + * modular multiplication representation + * @param n Pointer to the modulus + * @param context Pointer to a context previously initialized using + * TEE_BigIntInitFMMContext + */ +void TEE_BigIntConvertFromFMM(TEE_BigInt* dest, const TEE_BigIntFMM* src, + const TEE_BigInt* n, const TEE_BigIntFMMContext* context) { +} + +/** + * The TEE_BigIntComputeFMM function calculates dest = op1 * op2 in the fast + * modular multiplication representation. The pointers dest, op1, and op2 MUST + * each point to a TEE_BigIntFMM which has been previously initialized with + * the same modulus and context as used in this function call; otherwise the + * result is undefined. All or some of dest, op1, and op2 MAY point to the + * same memory region. + * @param dest Pointer to TEE_BigIntFMM to hold the result op1 * op2 in the + * fast modular multiplication representation + * @param op1 Pointer to the first operand + * @param op2 Pointer to the second operand + * @param n Pointer to the modulus + * @param context Pointer to a context previously initialized using + * TEE_BigIntInitFMMContext + */ +void TEE_BigIntComputeFMM(TEE_BigIntFMM* dest, const TEE_BigIntFMM* op1, + const TEE_BigIntFMM* op2, const TEE_BigInt* n, + const TEE_BigIntFMMContext* context) { +} diff --git a/ssflib/src/ssf_client.c b/ssflib/src/ssf_client.c new file mode 100755 index 0000000..b76f0c8 --- /dev/null +++ b/ssflib/src/ssf_client.c @@ -0,0 +1,190 @@ +/* + * ===================================================================================== + * + * Filename: ssfclient.c + * + * Description: SSF client functions + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: Cheryl (cb), cheryl.b@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "teestub_command_data.h" +#include "tee_internal_api.h" +#include +#include +#include "ssf_client.h" +#include + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define SOCKPATH "/tmp/simdaemon" //path to be updated + +//#define TEST + +/*----------------------------------------------------------------------------- + * local functions + *-----------------------------------------------------------------------------*/ +/** + * API (Interface for TEECAPI) implementation for connecting to + * the Simulator daemon through socket + * @return socket file descriptor to connected server + */ +int32_t connecttoServer(void) { + LOGD(SSF_LIB, "Entry"); + int serverSocket, socklen; + size_t sock_path_len = 0; + struct sockaddr* sockptr; + struct sockaddr_un daemonsock; + + if ((serverSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + LOGE(SSF_LIB, "No socket for simdaemon"); + return -1; + } + daemonsock.sun_family = AF_UNIX; + + sock_path_len = strlen(SOCKPATH); + strncpy(daemonsock.sun_path, SOCKPATH, sock_path_len+1); + + socklen = sizeof(daemonsock); + sockptr = (struct sockaddr*)&daemonsock; + if (connect(serverSocket, sockptr, socklen) == -1) { + LOGE(SSF_LIB, "connection to simdaemon failed"); + close(serverSocket); + return -1; + } + return serverSocket; +} + +/** + * API (Interface for TEECAPI) implementation for disconnecting + * from the Simulator daemon through socket + * @param ServerSocket + */ +void disconnectfromServer(int32_t serverSocket) { + int32_t result; + LOGD(SSF_LIB, "Entry"); + if (serverSocket > 0) { + result = shutdown(serverSocket, SHUT_WR); + if (result != 0) LOGE(SSF_LIB, "disconnectfromServer failed"); + close(serverSocket); + } else { + LOGE(SSF_LIB, "Invalid socket, disconnectfromServer failed"); + } +} + +/** + * Function implementation for sending data to Simulator daemon + * through socket + * @param sockfd file descriptor + * @param fdata structured data to daemon + * @param size size of fdata in bytes + * @return + */ +static uint32_t sendCommandtoDaemon(int32_t sockfd, char* fdata, size_t size) { + LOGD(SSF_LIB, "Entry"); + ssize_t nwrite = 0; + size_t nbytes = 0; + if (sockfd > 0) { + do { + nwrite = send(sockfd, fdata + nbytes, size - nbytes, 0); + } while ((nwrite == -1 && errno == EINTR) || (nwrite > 0 && ((nbytes += + nwrite) < size))); + return (size != nbytes) ? errno : 0; + } + LOGE(SSF_LIB, "failed"); + return TEEC_ERROR_COMMUNICATION; +} + +/** + * Function implementation for recieving data from Simulator + * daemon through socket + * @param sockfd file descriptor + * @param fdata structured data to be received + * @param size size of fdata in bytes + * @return + */ +static uint32_t receiveResponse(int32_t sockfd, char* fdata, size_t size) { + LOGD(SSF_LIB, "Entry"); + ssize_t nread = 0; + size_t nbytes = 0; + if (sockfd > 0) { + do { + nread = recv(sockfd, fdata + nbytes, size - nbytes, 0); + } while ((nread == -1 && errno == EINTR) + || (nread > 0 && ((nbytes += nread) < size))); + return (size != nbytes) ? errno : 0; + } + LOGE(SSF_LIB, "failed"); + return TEEC_ERROR_COMMUNICATION; +} + +/** + * Test function to test the daemon + * @param cmd + * @param fdata + * @param size + * @param in + * @return + */ +#ifdef TEST +static uint32_t Test(char cmd, char* fdata, size_t size, uint32_t in) { + //TODO: Implementation + return TEE_SUCCESS; +} +#endif + +/** + * API (Interface for TEECAPI) implementation for sending a + * command to Simulator daemon + * @param sockfd file descriptor + * @param cmd command to simulator daemon + * @param data structured data to daemon + * @param size size of data + * @return + */ +uint32_t sendCommand(int32_t sockfd, TEE_CMD cmd, void* data, size_t size) { + LOGD(SSF_LIB, "Entry"); + TEE_Result result = TEE_SUCCESS; + char command = (char)cmd; +#ifdef TEST + result = Test(command, (char*)data, size, 1); + if (result != TEE_SUCCESS) { + return TEE_ERROR_GENERIC; + } +#endif + result = sendCommandtoDaemon(sockfd, (char*)&command, sizeof(char)); + if (result != TEE_SUCCESS) { + return TEE_ERROR_GENERIC; + } + result = sendCommandtoDaemon(sockfd, (char*)data, size); + if (result != TEE_SUCCESS) { + return TEE_ERROR_GENERIC; + } + result = receiveResponse(sockfd, (char*)&command, sizeof(char)); + if (result != TEE_SUCCESS) { + return TEE_ERROR_GENERIC; + } + result = receiveResponse(sockfd, (char*)data, size); + if (result != TEE_SUCCESS) { + return TEE_ERROR_GENERIC; + } +#ifdef TEST + result = Test(command, (char*)data, size, 0); + if (result != TEE_SUCCESS) { + return TEE_ERROR_GENERIC; + } +#endif + return result; +} diff --git a/ssflib/src/ssf_crypto.c b/ssflib/src/ssf_crypto.c new file mode 100755 index 0000000..655eabd --- /dev/null +++ b/ssflib/src/ssf_crypto.c @@ -0,0 +1,2598 @@ +/* + * ===================================================================================== + * + * Filename: ssf_crypto.c + * + * Description: SSF crypto functions + * + * Version: 1.0 + * Created: 23 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ +#define _CRT_RAND_S +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "uci_api.h" +#include +#include +#include +#include +#include +#include "unistd.h" +#include "uci_internal.h" +#include "tee_internal_api.h" +#include +#include + + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define g_bTAdbug 1 +#define TZ_PRINT(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) +#define TZ_ERROR(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) +#undef PrintBYTE +#define PrintBYTE(msg, Data, DataLen) { \ + int idx; \ + TZ_PRINT("%10s =", msg); \ + for(idx=0; idx<(int)DataLen; idx++) { \ + if((idx!=0) && ((idx%16)==0)) TZ_PRINT("\n"); \ + if((idx % 4) == 0) TZ_PRINT(" 0x"); \ + TZ_PRINT("%.2x", Data[idx]); \ + } \ + TZ_PRINT("\n"); \ + } + +/*----------------------------------------------------------------------------- + * Definitions + *-----------------------------------------------------------------------------*/ +struct __TEE_ObjectHandle { + TEE_ObjectInfo info; +}; + +struct __TEE_OperationHandle { + TEE_OperationInfo info; +}; + +struct TEE_Operation { + TEE_OperationInfo info; + TEE_ObjectHandle key1; + TEE_ObjectHandle key2; + int crypto; // handle to crypto driver or ponter to crypto library context +}; + +static long getClock(void) { + struct timeval tv; + gettimeofday (&tv, NULL); + return (tv.tv_sec * 1000 + tv.tv_usec / 1000); +} + +/*----------------------------------------------------------------------------- + * Local functions + *-----------------------------------------------------------------------------*/ +static uint32_t object_type_from_algorithm(uint32_t alg, uint32_t *obj_type, + uint32_t * uci_type) { + switch (alg) { + + // KRISHNA: ADDED BELOW, VERIFY ONCE + case TEE_ALG_AES_ECB_PKCS5: + case TEE_ALG_AES_ECB_PKCS7: + case TEE_ALG_AES_ECB_ISO9797_M1: + case TEE_ALG_AES_ECB_ISO9797_M2: + case TEE_ALG_AES_CBC_PKCS5: + case TEE_ALG_AES_CBC_PKCS7: + case TEE_ALG_AES_CBC_ISO9797_M1: + case TEE_ALG_AES_CBC_ISO9797_M2: + // OLD CODE + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CTR_NOPAD: + case TEE_ALG_AES_CTS: + case TEE_ALG_AES_XTS: + case TEE_ALG_AES_CCM: + case TEE_ALG_AES_GCM: + *obj_type = TEE_TYPE_AES; + *uci_type = ID_UCI_AES; + break; + case TEE_ALG_AES_CBC_MAC_NOPAD: + *obj_type = TEE_TYPE_AES; + *uci_type = ID_UCI_XCBCMAC; + break; + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + *obj_type = TEE_TYPE_AES; + *uci_type = ID_UCI_CMAC; + break; + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + *obj_type = TEE_TYPE_DES; + *uci_type = ID_UCI_DES; + break; + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + *obj_type = TEE_TYPE_DES3; + *uci_type = ID_UCI_TDES; + break; + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + case TEE_ALG_RSA_NOPAD: + *obj_type = TEE_TYPE_RSA_KEYPAIR; + *uci_type = 0; + break; + case TEE_ALG_DSA_SHA1: + *obj_type = TEE_TYPE_DSA_KEYPAIR; + *uci_type = ID_UCI_DSA; + break; +#ifdef ECC_IMPLEMENTATION + case TEE_ALG_ECDSA_P160: + case TEE_ALG_ECDSA_P192: + case TEE_ALG_ECDSA_P224: + case TEE_ALG_ECDSA_P256: + case TEE_ALG_ECDSA_P384: + case TEE_ALG_ECDSA_P521: + *obj_type = TEE_TYPE_ECDSA_KEYPAIR; + *uci_type = ID_UCI_ECDSA; + break; + case TEE_ALG_ECDH_P192: + case TEE_ALG_ECDH_P224: + case TEE_ALG_ECDH_P256: + case TEE_ALG_ECDH_P384: + case TEE_ALG_ECDH_P521: + *obj_type = TEE_TYPE_ECDH_KEYPAIR; + *uci_type = ID_UCI_ECDH; + break; +#endif + case TEE_ALG_DH_DERIVE_SHARED_SECRET: + *obj_type = TEE_TYPE_DH_KEYPAIR; + *uci_type = ID_UCI_DH; + break; + case TEE_ALG_HMAC_MD5: + *obj_type = TEE_TYPE_HMAC_MD5; + *uci_type = ID_UCI_HMD5; + break; + case TEE_ALG_HMAC_SHA1: + *obj_type = TEE_TYPE_HMAC_SHA1; + *uci_type = ID_UCI_HSHA1; + break; + case TEE_ALG_HMAC_SHA224: + *obj_type = TEE_TYPE_HMAC_SHA224; + *uci_type = ID_UCI_HSHA224; + break; + case TEE_ALG_HMAC_SHA256: + *obj_type = TEE_TYPE_HMAC_SHA256; + *uci_type = ID_UCI_HSHA256; + break; + case TEE_ALG_HMAC_SHA384: + *obj_type = TEE_TYPE_HMAC_SHA384; + *uci_type = ID_UCI_HSHA384; + break; + case TEE_ALG_HMAC_SHA512: + *obj_type = TEE_TYPE_HMAC_SHA512; + *uci_type = ID_UCI_HSHA512; + break; + case TEE_ALG_MD5: + *uci_type = ID_UCI_MD5; + break; + case TEE_ALG_SHA1: + *uci_type = ID_UCI_SHA1; + break; + case TEE_ALG_SHA224: + *uci_type = ID_UCI_SHA224; + break; + case TEE_ALG_SHA256: + *uci_type = ID_UCI_SHA256; + break; + case TEE_ALG_SHA384: + *uci_type = ID_UCI_SHA384; + break; + case TEE_ALG_SHA512: + *uci_type = ID_UCI_SHA512; + break; + } + return *obj_type; +} + +static int crypto_lib_init_operation(TEE_OperationHandle operation) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + if (uci_md_init(op->crypto) != UCI_SUCCESS) { + TEE_Panic(0); + } + return 0; +} + +/*----------------------------------------------------------------------------- + * TEE API implementation + *-----------------------------------------------------------------------------*/ +// Generic Operation Functions +TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, + uint32_t algorithm, uint32_t mode, uint32_t maxKeySize) { + struct TEE_Operation * op; + uint32_t alg_class = 0; + uint32_t object_type = 0; + uint32_t uci_type = 0; + TEE_Result rc; + TEE_ObjectHandle key1 = TEE_HANDLE_NULL; + TEE_ObjectHandle key2 = TEE_HANDLE_NULL; + int digest_len = 0; + uint32_t block_len = 0; + uint32_t key_object_type = 0; + /* NEW CODE FROM PLATFORM CODE BASE OF SECURE OS */ + // check parameters compatibility + switch(algorithm) + { + /* Algorithm Class is SYMMETRIC CIPHER */ + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CTR_NOPAD: + case TEE_ALG_AES_ECB_PKCS5: + case TEE_ALG_AES_ECB_PKCS7: + case TEE_ALG_AES_ECB_ISO9797_M1: + case TEE_ALG_AES_ECB_ISO9797_M2: + case TEE_ALG_AES_CBC_PKCS5: + case TEE_ALG_AES_CBC_PKCS7: + case TEE_ALG_AES_CBC_ISO9797_M1: + case TEE_ALG_AES_CBC_ISO9797_M2: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_AES; + block_len = 16; + digest_len = 0; + break; + + case TEE_ALG_AES_XTS: + case TEE_ALG_AES_CTS: + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_DES; + block_len = 8; + digest_len = 0; + break; + + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_DES3; + block_len = 8; + digest_len = 0; + break; + + /* Algorithm Class is AE */ + case TEE_ALG_AES_CCM: + case TEE_ALG_AES_GCM: + return TEE_ERROR_NOT_SUPPORTED; + break; + + /* Algorithm Class is MAC */ + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + return TEE_ERROR_NOT_SUPPORTED; + break; + + + + case TEE_ALG_HMAC_MD5: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_MD5; + block_len = 64; + digest_len = 16; + break; + + case TEE_ALG_HMAC_SHA1: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA1; + block_len = 64; + digest_len = 20; + break; + + case TEE_ALG_HMAC_SHA224: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA224; + block_len = 64; + digest_len = 28; + break; + + case TEE_ALG_HMAC_SHA256: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA256; + block_len = 64; + digest_len = 32; + break; + + case TEE_ALG_HMAC_SHA384: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA384; + block_len = 64; + digest_len = 48; + break; + + case TEE_ALG_HMAC_SHA512: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA512; + block_len = 64; + digest_len = 64; + break; + + /* Algorithm Class is DIGIT */ + case TEE_ALG_MD5: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 16; + block_len = 64; + break; + + case TEE_ALG_SHA1: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 20; + block_len = 64; + break; + + case TEE_ALG_SHA224: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 28; + block_len = 64; + break; + + case TEE_ALG_SHA256: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 32; + block_len = 64; + break; + + case TEE_ALG_SHA384: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 48; + block_len = 64; + break; + + case TEE_ALG_SHA512: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 64; + block_len = 64; + break; + + /* Algorithm Class is ASYMMETRIC CIPHER */ + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + case TEE_ALG_RSA_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_CIPHER; + key_object_type = TEE_TYPE_RSA_KEYPAIR; + block_len = 0; + digest_len = 0; + break; + + /* Algorithm Class is SIGNATURE */ + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_SIGNATURE; + key_object_type = TEE_TYPE_RSA_KEYPAIR; + break; + + case TEE_ALG_ECDSA_P160: + case TEE_ALG_ECDSA_P192: + case TEE_ALG_ECDSA_P224: + case TEE_ALG_ECDSA_P256: + case TEE_ALG_ECDSA_P384: + case TEE_ALG_ECDSA_P521: + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_DSA_SHA1: + case TEE_ALG_ECDH_P192: + case TEE_ALG_ECDH_P224: + case TEE_ALG_ECDH_P256: + case TEE_ALG_ECDH_P384: + case TEE_ALG_ECDH_P521: + return TEE_ERROR_NOT_SUPPORTED; + break; + + /* Algorithm Class is KEY DERIVATION */ + case TEE_ALG_DH_DERIVE_SHARED_SECRET: + return TEE_ERROR_NOT_SUPPORTED; + break; + + default: + //printf("Not Support Algorithm : %X", algorithm); + TZ_ERROR("Not Support Algorithm %d,%s %X\n", __LINE__, __func__, algorithm); + rc = TEE_ERROR_NOT_SUPPORTED; + goto exit; + break; + } + + + + + + + /* + // OLD SWITCH + switch (algorithm) { + case TEE_ALG_AES_XTS: + return TEE_ERROR_NOT_SUPPORTED; + break; + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CTS: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + alg_class = TEE_OPERATION_CIPHER; + break; + case TEE_ALG_AES_CCM: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 0; // will be set during initialisation + alg_class = TEE_OPERATION_AE; + break; + case TEE_ALG_AES_GCM: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 0; // will be set during initialisation + alg_class = TEE_OPERATION_AE; + break; + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + alg_class = TEE_OPERATION_MAC; + break; + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + alg_class = TEE_OPERATION_MAC; + return TEE_ERROR_NOT_SUPPORTED; + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + case TEE_ALG_DSA_SHA1: +#ifdef ECC_IMPLEMENTATION + case TEE_ALG_ECDSA_P160: + case TEE_ALG_ECDSA_P192: + case TEE_ALG_ECDSA_P224: + case TEE_ALG_ECDSA_P256: + case TEE_ALG_ECDSA_P384: + case TEE_ALG_ECDSA_P521: +#endif + if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) { + return TEE_ERROR_NOT_SUPPORTED; + } + alg_class = TEE_OPERATION_ASYMMETRIC_SIGNATURE; + break; + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + case TEE_ALG_RSA_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + alg_class = TEE_OPERATION_ASYMMETRIC_CIPHER; + break; + case TEE_ALG_DH_DERIVE_SHARED_SECRET: + if (mode != TEE_MODE_DERIVE) { + return TEE_ERROR_NOT_SUPPORTED; + } + alg_class = TEE_OPERATION_KEY_DERIVATION; + break; + case TEE_ALG_MD5: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 16; + alg_class = TEE_OPERATION_DIGEST; + break; + case TEE_ALG_SHA1: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 20; + alg_class = TEE_OPERATION_DIGEST; + break; + case TEE_ALG_SHA224: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 28; + alg_class = TEE_OPERATION_DIGEST; + break; + case TEE_ALG_SHA256: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 32; + alg_class = TEE_OPERATION_DIGEST; + break; + case TEE_ALG_SHA384: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 48; + alg_class = TEE_OPERATION_DIGEST; + break; + case TEE_ALG_SHA512: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 64; + alg_class = TEE_OPERATION_DIGEST; + break; + case TEE_ALG_HMAC_MD5: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 16; + alg_class = TEE_OPERATION_MAC; + break; + case TEE_ALG_HMAC_SHA1: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 20; + alg_class = TEE_OPERATION_MAC; + break; + case TEE_ALG_HMAC_SHA224: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 28; + alg_class = TEE_OPERATION_MAC; + break; + case TEE_ALG_HMAC_SHA256: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 32; + alg_class = TEE_OPERATION_MAC; + break; + case TEE_ALG_HMAC_SHA384: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 48; + alg_class = TEE_OPERATION_MAC; + break; + case TEE_ALG_HMAC_SHA512: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + digest_len = 64; + alg_class = TEE_OPERATION_MAC; + break; + default: + TZ_ERROR("algorithm error %d,%s\n", __LINE__, __func__); + return TEE_ERROR_NOT_SUPPORTED; + } + */ + object_type = object_type_from_algorithm(algorithm, &object_type, &uci_type); + if (alg_class != TEE_OPERATION_DIGEST) { + rc = TEE_AllocateTransientObject(object_type, maxKeySize, &key1); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_AllocateTransientObject error %d,%s\n", __LINE__, __func__); + return rc; + } +#if 0 + // TODO: TEE_ALG_AES_XTS not supported + if (algorithm == TEE_ALG_AES_XTS)// 2 keys for TEE_ALG_AES_XTS + { + rc = TEE_AllocateTransientObject(object_type, maxKeySize, &key2); + if (rc != TEE_SUCCESS) { + TEE_CloseObject(key1); + TZ_ERROR("TEE_AllocateTransientObject error %d,%s\n", + __LINE__, + __func__); + return rc; + } + } +#endif + } + //ALLOC MEMORY + op = (TEE_Operation*)OsaMalloc(sizeof(struct TEE_Operation)); + if (!op) { + if (key1) { + TEE_CloseObject(key1); + } +#if 0 + // TODO: TEE_ALG_AES_XTS not supported + if (key2) { + TEE_CloseObject(key2); + } +#endif + TZ_ERROR("malloc error %d,%s\n", __LINE__, __func__); + return TEE_ERROR_OUT_OF_MEMORY; + } + memset(op, 0, sizeof(struct TEE_Operation)); + op->info.algorithm = algorithm; + op->info.mode = mode; + op->info.maxKeySize = maxKeySize; + op->info.digestLength = digest_len; + op->info.keySize = 0; + op->info.operationClass = alg_class; + op->info.requiredKeyUsage = 0; + switch (mode) { + case TEE_MODE_ENCRYPT: + op->info.requiredKeyUsage |= TEE_USAGE_ENCRYPT; + break; + case TEE_MODE_DECRYPT: + op->info.requiredKeyUsage |= TEE_USAGE_DECRYPT; + break; + case TEE_MODE_MAC: + op->info.requiredKeyUsage |= TEE_USAGE_MAC; + break; + case TEE_MODE_DERIVE: + op->info.requiredKeyUsage |= TEE_USAGE_DERIVE; + break; + case TEE_MODE_SIGN: + op->info.requiredKeyUsage |= TEE_USAGE_SIGN; + break; + case TEE_MODE_VERIFY: + op->info.requiredKeyUsage |= TEE_USAGE_VERIFY; + break; + } + op->info.handleState = 0; + if (alg_class == TEE_OPERATION_DIGEST) { + op->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + } +#if 1 + // TODO: TEE_ALG_AES_XTS not supported + if (algorithm == TEE_ALG_AES_XTS) { + op->info.handleState |= TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; + } + + /* key1 alloc */ + if (key_object_type) { + if (TEE_AllocateTransientObject(key_object_type, maxKeySize, &key1) != TEE_SUCCESS) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto error; + } + } + + /* key2 alloc for XTS */ + if (algorithm == TEE_ALG_AES_XTS) { + if (TEE_AllocateTransientObject(key_object_type, maxKeySize, &key2) != TEE_SUCCESS) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto error; + } + } +#endif + op->key1 = key1; + op->key2 = key2; + // [TODO] NEED TO FIX THIS STRUCTURE TO INCLUDE BLOCK_LEN MEMBER + //op->block_len = block_len; + if (uci_type != 0) { + op->crypto = uci_context_alloc(uci_type, UCI_SW); + } else { + op->crypto = 0; + } + *operation = (TEE_OperationHandle)&op->info; + + if (alg_class == TEE_OPERATION_DIGEST) { + crypto_lib_init_operation(*operation); //in case hash contex will not inited. + } + return TEE_SUCCESS; + + +error: + if (key1) { + TEE_CloseObject(key1); + } + if (key2) { + TEE_CloseObject(key2); + } + if (op) { + free(op); + } +exit: + *operation = TEE_HANDLE_NULL; + printf("Error : %X", rc); + + return rc; + +} +// KRISHNA - OLD CODE + + +/*TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, uint32_t algorithm, uint32_t mode, uint32_t maxKeySize) +{ + //PERMISSION_CHECK(PERM_CRYPTO); + + crypto_internal_operation * op; + TEE_Result rc=TEE_SUCCESS; + uint32_t alg_class = 0; + uint32_t key_object_type = 0; + uint32_t digest_len = 0; + uint32_t block_len = 0; + TEE_ObjectHandle key1 = TEE_HANDLE_NULL; + TEE_ObjectHandle key2 = TEE_HANDLE_NULL; + + // check parameters compatibility + switch(algorithm) + { + // Algorithm Class is SYMMETRIC CIPHER + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CTR_NOPAD: + case TEE_ALG_AES_ECB_PKCS5: + case TEE_ALG_AES_ECB_PKCS7: + case TEE_ALG_AES_ECB_ISO9797_M1: + case TEE_ALG_AES_ECB_ISO9797_M2: + case TEE_ALG_AES_CBC_PKCS5: + case TEE_ALG_AES_CBC_PKCS7: + case TEE_ALG_AES_CBC_ISO9797_M1: + case TEE_ALG_AES_CBC_ISO9797_M2: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_AES; + block_len = 16; + digest_len = 0; + break; + + case TEE_ALG_AES_XTS: + case TEE_ALG_AES_CTS: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_AES; + block_len = 32; // for CTS & XTS need 2 AES blocks + digest_len = 0; + break; + + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_DES; + block_len = 8; + digest_len = 0; + break; + + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_CIPHER; + key_object_type = TEE_TYPE_DES3; + block_len = 8; + digest_len = 0; + break; + + // Algorithm Class is AE + case TEE_ALG_AES_CCM: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_AE; + key_object_type = TEE_TYPE_AES; + block_len = 16; + digest_len = 0; + break; + + case TEE_ALG_AES_GCM: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_AE; + key_object_type = TEE_TYPE_AES; + block_len = 16; + digest_len = 0; + break; + + // Algorithm Class is MAC + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_AES; + block_len = 16; + digest_len = 16; + break; + + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_DES; + block_len = 8; + digest_len = 8; + break; + + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_DES3; + block_len = 8; + digest_len = 8; + break; + + case TEE_ALG_HMAC_MD5: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_MD5; + block_len = 64; + digest_len = 16; + break; + + case TEE_ALG_HMAC_SHA1: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA1; + block_len = 64; + digest_len = 20; + break; + + case TEE_ALG_HMAC_SHA224: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA224; + block_len = 64; + digest_len = 28; + break; + + case TEE_ALG_HMAC_SHA256: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA256; + block_len = 64; + digest_len = 32; + break; + + case TEE_ALG_HMAC_SHA384: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA384; + block_len = 64; + digest_len = 48; + break; + + case TEE_ALG_HMAC_SHA512: + if (mode != TEE_MODE_MAC) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_MAC; + key_object_type = TEE_TYPE_HMAC_SHA512; + block_len = 64; + digest_len = 64; + break; + + // Algorithm Class is DIGIT + case TEE_ALG_MD5: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 16; + block_len = 64; + break; + + case TEE_ALG_SHA1: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 20; + block_len = 64; + break; + + case TEE_ALG_SHA224: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 28; + block_len = 64; + break; + + case TEE_ALG_SHA256: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 32; + block_len = 64; + break; + + case TEE_ALG_SHA384: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 48; + block_len = 64; + break; + + case TEE_ALG_SHA512: + if (mode != TEE_MODE_DIGEST) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_DIGEST; + key_object_type = 0; + digest_len = 64; + block_len = 64; + break; + + // Algorithm Class is ASYMMETRIC CIPHER + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + case TEE_ALG_RSA_NOPAD: + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_CIPHER; + key_object_type = TEE_TYPE_RSA_KEYPAIR; + block_len = 0; + digest_len = 0; + break; + + // Algorithm Class is SIGNATURE + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_SIGNATURE; + key_object_type = TEE_TYPE_RSA_KEYPAIR; + break; + + case TEE_ALG_ECDSA_P160: + case TEE_ALG_ECDSA_P192: + case TEE_ALG_ECDSA_P224: + case TEE_ALG_ECDSA_P256: + case TEE_ALG_ECDSA_P384: + case TEE_ALG_ECDSA_P521: + if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_SIGNATURE; + key_object_type = TEE_TYPE_RSA_KEYPAIR; + break; + + case TEE_ALG_DSA_SHA1: + if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_SIGNATURE; + key_object_type = TEE_TYPE_DSA_KEYPAIR; + break; + + case TEE_ALG_ECDH_P192: + case TEE_ALG_ECDH_P224: + case TEE_ALG_ECDH_P256: + case TEE_ALG_ECDH_P384: + case TEE_ALG_ECDH_P521: + if (mode != TEE_MODE_SIGN && mode != TEE_MODE_VERIFY) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_ASYMMETRIC_SIGNATURE; + key_object_type = TEE_TYPE_ECDH_KEYPAIR; + break; + + // Algorithm Class is KEY DERIVATION + case TEE_ALG_DH_DERIVE_SHARED_SECRET: + if (mode != TEE_MODE_DERIVE) { + return TEE_ERROR_NOT_SUPPORTED; + } + + alg_class = TEE_OPERATION_KEY_DERIVATION; + key_object_type = TEE_TYPE_DH_KEYPAIR; + break; + + default: + LOGE(TAG, "Not Support Algorithm : %X", algorithm); + rc = TEE_ERROR_NOT_SUPPORTED; + goto exit; + break; + } + + // first malloc for crypto operation + op = malloc(sizeof (crypto_internal_operation)); + if (!op) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + memset(op, 0, sizeof (crypto_internal_operation)); + + // Set TEE_OperationInfo + op->info.algorithm = algorithm; + op->info.operationClass = alg_class; + op->info.mode = mode; + op->info.digestLength = digest_len; + op->info.maxKeySize = maxKeySize; + op->info.keySize = maxKeySize; + + if (mode == TEE_MODE_ENCRYPT) { + op->info.requiredKeyUsage |= TEE_USAGE_ENCRYPT; + } + if (mode == TEE_MODE_DECRYPT) { + op->info.requiredKeyUsage |= TEE_USAGE_DECRYPT; + } + if (mode == TEE_MODE_MAC) { + op->info.requiredKeyUsage |= TEE_USAGE_MAC; + } + if (mode == TEE_MODE_DERIVE) { + op->info.requiredKeyUsage |= TEE_USAGE_DERIVE; + } + if (mode == TEE_MODE_SIGN) { + op->info.requiredKeyUsage |= TEE_USAGE_SIGN; + } + if (mode == TEE_MODE_VERIFY) { + op->info.requiredKeyUsage |= TEE_USAGE_VERIFY; + } + if (algorithm == TEE_ALG_RSA_NOPAD) + { + if (mode == TEE_MODE_ENCRYPT) { + op->info.requiredKeyUsage |= TEE_USAGE_VERIFY; + } + else if (mode == TEE_MODE_DECRYPT) { + op->info.requiredKeyUsage |= TEE_USAGE_SIGN; + } + } + + if (algorithm == TEE_ALG_AES_XTS) { + op->info.handleState |= TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; + } + + // get handle + if(crypto_internal_open(op)!=0) { + rc = TEE_ERROR_NOT_SUPPORTED; + goto error; + } + + // key1 alloc + if (key_object_type) { + if (TEE_AllocateTransientObject(key_object_type, maxKeySize, &key1) != TEE_SUCCESS) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto error; + } + } + + // key2 alloc for XTS + if (algorithm == TEE_ALG_AES_XTS) { + if (TEE_AllocateTransientObject(key_object_type, maxKeySize, &key2) != TEE_SUCCESS) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto error; + } + } + + // key map for crypto operation + op->key1 = key1; + op->key2 = key2; + op->block_len = block_len; + + *operation = (TEE_OperationHandle) &op->info; + if (alg_class == TEE_OPERATION_DIGEST) { + TEE_DigestInit(*operation); + } + + return TEE_SUCCESS; + +error: + crypto_internal_close(op); + if (key1) { + TEE_CloseObject(key1); + } + if (key2) { + TEE_CloseObject(key2); + } + if (op) { + free(op); + } +exit: + *operation = TEE_HANDLE_NULL; + LOGE(TAG, "Error : %X", rc); + return rc; +} +*/ + + + +void TEE_FreeOperation(TEE_OperationHandle operation) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + if (op->key1) { + TEE_CloseObject(op->key1); + } + if (op->key2) { + TEE_CloseObject(op->key2); + } + if (uci_context_free(op->crypto) != UCI_SUCCESS) { + TZ_ERROR("free error %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + OsaFree(op); +} + +void TEE_GetOperationInfo(TEE_OperationHandle operation, + TEE_OperationInfo* operationInfo) { + operationInfo->algorithm = operation->info.algorithm; + operationInfo->digestLength = operation->info.digestLength; + operationInfo->handleState = operation->info.handleState; + operationInfo->keySize = operation->info.keySize; + operationInfo->maxKeySize = operation->info.maxKeySize; + operationInfo->mode = operation->info.mode; + operationInfo->operationClass = operation->info.operationClass; + operationInfo->requiredKeyUsage = operation->info.requiredKeyUsage; +} + +void TEE_ResetOperation(TEE_OperationHandle operation) { + operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; +} + +TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key) { + uci_key_s ucikey; + uci_param_s uciparam; + TEE_Result rc; + unsigned char pub[384]; + unsigned char priv[384]; + unsigned char module[384]; + unsigned int pubLen = 384; + unsigned int privLen = 384; + unsigned int moduleLen = 384; + unsigned int alg; + memset(&ucikey, 0, sizeof(uci_key_s)); + memset(&uciparam, 0, sizeof(uci_param_s)); + + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass == TEE_OPERATION_DIGEST + || operation->info.algorithm == TEE_ALG_AES_XTS) { + TZ_ERROR("operation error %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (key == TEE_HANDLE_NULL) { + TEE_CloseObject(op->key1); + op->key1 = TEE_HANDLE_NULL; + return TEE_SUCCESS; + } + // check key usage flags + if ((key->info.objectUsage | ~op->info.requiredKeyUsage) != 0xffffffff) { + TZ_ERROR("Usage don't match line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + + //set key pair + switch (op->info.algorithm) { + //SIGN OR VERIFY + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PKCS15_MD5; + break; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PKCS15_SHA1; + break; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PKCS15_SHA224; + break; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PKCS15_SHA256; + break; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PKCS15_SHA384; + break; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PKCS15_SHA512; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PSS_SHA1; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PSS_SHA224; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PSS_SHA256; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PSS_SHA384; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + uciparam.ucip_rsa_padding = ID_UCI_RSASSA_PSS_SHA512; + break; + case TEE_ALG_DSA_SHA1: + break; + //ENCRYPT OR DECRYPT + case TEE_ALG_RSAES_PKCS1_V1_5: + uciparam.ucip_rsa_padding = ID_UCI_RSAES_PKCS15; + break; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + uciparam.ucip_rsa_padding = ID_UCI_RSAES_OAEP_SHA1; + break; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + uciparam.ucip_rsa_padding = ID_UCI_RSAES_OAEP_SHA224; + break; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + uciparam.ucip_rsa_padding = ID_UCI_RSAES_OAEP_SHA256; + break; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + uciparam.ucip_rsa_padding = ID_UCI_RSAES_OAEP_SHA384; + break; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + uciparam.ucip_rsa_padding = ID_UCI_RSAES_OAEP_SHA512; + break; + case TEE_ALG_RSA_NOPAD: + uciparam.ucip_rsa_padding = ID_UCI_NO_PADDING; + break; + } + switch (key->info.objectType) { + case TEE_TYPE_RSA_PUBLIC_KEY: + case TEE_TYPE_RSA_KEYPAIR: + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_RSA_MODULUS, module, + &moduleLen); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_RSA_PUBLIC_EXPONENT, pub, + &pubLen); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + ucikey.ucik_rsa_n = module; + ucikey.ucik_rsa_n_len = moduleLen; + ucikey.ucik_rsa_e = pub; + ucikey.ucik_rsa_e_len = pubLen; + ucikey.ucik_rsa_d = NULL; + ucikey.ucik_rsa_d_len = 0; + + if (key->info.objectType == TEE_TYPE_RSA_KEYPAIR) { + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_RSA_PRIVATE_EXPONENT, + priv, &privLen); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", + __LINE__, __func__); + return rc; + } + ucikey.ucik_rsa_d = priv; + ucikey.ucik_rsa_d_len = privLen; + } + switch (key->info.objectSize) { + case 512: + alg = ID_UCI_RSA512; + break; + case 1024: + alg = ID_UCI_RSA1024; + break; + case 2048: + alg = ID_UCI_RSA2048; + break; + case 3072: + alg = ID_UCI_RSA3072; + break; + default: + TZ_ERROR("key->info.objectSize = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + //PrintBYTE("N",module,moduleLen); + //PrintBYTE("E",pub,pubLen); + op->crypto = uci_context_alloc(alg, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (uci_ae_set_keypair(op->crypto, &ucikey, &uciparam) != UCI_SUCCESS) { + TZ_ERROR("uci_ae_set_keypair error line = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + break; + case TEE_TYPE_DSA_PUBLIC_KEY: + case TEE_TYPE_DSA_KEYPAIR: + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DSA_PUBLIC_VALUE, pub, + &pubLen); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + + if (key->info.objectType == TEE_TYPE_DSA_KEYPAIR) { + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DSA_PRIVATE_VALUE, priv, + &privLen); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", + __LINE__, __func__); + return rc; + } + ucikey.ucik_dsa_privkey = priv; + ucikey.ucik_dsa_privk_len = privLen; + } + ucikey.ucik_dsa_pubkey = pub; + ucikey.ucik_dsa_pubk_len = pubLen; + + uciparam.ucip_dsa_tsize = 0; + uciparam.ucip_dsa_p = (unsigned char*)OsaMalloc(key->info.objectSize); + uciparam.ucip_dsa_q = (unsigned char*)OsaMalloc(key->info.objectSize); + uciparam.ucip_dsa_g = (unsigned char*)OsaMalloc(key->info.objectSize); + uciparam.ucip_dsa_p_len = key->info.objectSize; + uciparam.ucip_dsa_g_len = key->info.objectSize; + uciparam.ucip_dsa_q_len = key->info.objectSize; + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DSA_PRIME, + uciparam.ucip_dsa_p, &uciparam.ucip_dsa_p_len); + if (rc != TEE_SUCCESS) { + OsaFree(uciparam.ucip_dsa_p); + OsaFree(uciparam.ucip_dsa_q); + OsaFree(uciparam.ucip_dsa_g); + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DSA_BASE, + uciparam.ucip_dsa_g, &uciparam.ucip_dsa_g_len); + if (rc != TEE_SUCCESS) { + OsaFree(uciparam.ucip_dsa_p); + OsaFree(uciparam.ucip_dsa_q); + OsaFree(uciparam.ucip_dsa_g); + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DSA_SUBPRIME, + uciparam.ucip_dsa_q, &uciparam.ucip_dsa_q_len); + if (rc != TEE_SUCCESS) { + OsaFree(uciparam.ucip_dsa_p); + OsaFree(uciparam.ucip_dsa_q); + OsaFree(uciparam.ucip_dsa_g); + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + if (uci_ae_set_keypair(op->crypto, &ucikey, &uciparam) != UCI_SUCCESS) { + OsaFree(uciparam.ucip_dsa_p); + OsaFree(uciparam.ucip_dsa_q); + OsaFree(uciparam.ucip_dsa_g); + TZ_ERROR("uci_ae_set_keypair error line = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + OsaFree(uciparam.ucip_dsa_p); + OsaFree(uciparam.ucip_dsa_q); + OsaFree(uciparam.ucip_dsa_g); + break; + case TEE_TYPE_DH_KEYPAIR: + uciparam.ucip_dh_prime = (unsigned char*)OsaMalloc(key->info.objectSize); + uciparam.ucip_dh_generator = (unsigned char*)OsaMalloc( + key->info.objectSize); + uciparam.ucip_dh_len = key->info.objectSize; + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DH_PRIME, + uciparam.ucip_dh_prime, &uciparam.ucip_dh_len); + if (rc != TEE_SUCCESS) { + OsaFree(uciparam.ucip_dh_prime); + OsaFree(uciparam.ucip_dh_generator); + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + rc = TEE_GetObjectBufferAttribute(key, TEE_ATTR_DH_BASE, + uciparam.ucip_dh_generator, &uciparam.ucip_dh_len); + if (rc != TEE_SUCCESS) { + OsaFree(uciparam.ucip_dh_prime); + OsaFree(uciparam.ucip_dh_generator); + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return rc; + } + if (uci_ae_set_keypair(op->crypto, &ucikey, &uciparam) != UCI_SUCCESS) { + OsaFree(uciparam.ucip_dh_prime); + OsaFree(uciparam.ucip_dh_generator); + TZ_ERROR("uci_ae_set_keypair error line = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + OsaFree(uciparam.ucip_dh_prime); + OsaFree(uciparam.ucip_dh_generator); + } + if ((key->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY + && op->key1->info.objectType == TEE_TYPE_RSA_KEYPAIR) + || (key->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY + && op->key1->info.objectType == TEE_TYPE_DSA_KEYPAIR)) { + + op->key1->info.objectType = key->info.objectType; // change object object type of key1 in DSA or RSA case + } + TEE_CopyObjectAttributes(op->key1, key); // will Panic inside in the case of incompatible objects + operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + return TEE_SUCCESS; +} + +TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, TEE_ObjectHandle key2) { + + struct TEE_Operation * op = (struct TEE_Operation*)operation; + if ((key1 && !key2) || (!key1 && key2)) { + TZ_ERROR("key error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (operation->info.algorithm != TEE_ALG_AES_XTS) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!key1 && !key2) { + TEE_CloseObject(op->key1); + op->key1 = TEE_HANDLE_NULL; + TEE_CloseObject(op->key2); + op->key2 = TEE_HANDLE_NULL; + return TEE_SUCCESS; + } + // check key usage flags + if (key1 && (key1->info.objectUsage | ~op->info.requiredKeyUsage) != 0xffffffff) { + TZ_ERROR("Usage don't match line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (key2 && (key2->info.objectUsage | ~op->info.requiredKeyUsage) != 0xffffffff) { + TZ_ERROR("Usage don't match line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if(key1 != NULL) { + TEE_CopyObjectAttributes(op->key1, key1); + } + if(key2 != NULL) { + TEE_CopyObjectAttributes(op->key2, key2); + } + operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + return TEE_SUCCESS; +} + +void TEE_CopyOperation(TEE_OperationHandle dstOperation, + TEE_OperationHandle srcOperation) { + + struct TEE_Operation * dstOp = (struct TEE_Operation*)dstOperation; + struct TEE_Operation * srcOp = (struct TEE_Operation*)srcOperation; + + if (dstOperation->info.mode != srcOperation->info.mode + || dstOperation->info.algorithm != srcOperation->info.algorithm) { + TZ_ERROR("Operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (dstOperation->info.maxKeySize < srcOperation->info.maxKeySize) { + TZ_ERROR("Operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + dstOperation->info.algorithm = srcOperation->info.algorithm; + dstOperation->info.digestLength = srcOperation->info.digestLength; + dstOperation->info.handleState = srcOperation->info.handleState; + dstOperation->info.keySize = srcOperation->info.keySize; + dstOperation->info.maxKeySize = srcOperation->info.maxKeySize; + dstOperation->info.mode = srcOperation->info.mode; + dstOperation->info.operationClass = srcOperation->info.operationClass; + dstOperation->info.requiredKeyUsage = srcOperation->info.requiredKeyUsage; + + if (dstOp->key1) { + TEE_CopyObjectAttributes(dstOp->key1, srcOp->key1); + } + if (dstOp->key2) { + TEE_CopyObjectAttributes(dstOp->key2, srcOp->key2); + } + if (uci_dup_handle(srcOp->crypto, dstOp->crypto) != UCI_SUCCESS) { + TZ_ERROR("uci_dup_handle error , line = %d, %s\n", __LINE__, __func__); + TEE_Panic(0); + } +} + +// Message Digest Functions +void TEE_DigestUpdate(TEE_OperationHandle operation, const void* chunk, + size_t chunkSize) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_DIGEST) { + TZ_ERROR("param error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_md_update(op->crypto, (unsigned char*)chunk, chunkSize) != UCI_SUCCESS) { + TZ_ERROR("uci_md_update error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } +} + +TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void* chunk, + size_t chunkLen, void* hash, size_t *hashLen) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (!hash || !hashLen) { + return TEE_ERROR_SHORT_BUFFER; + } + if (operation->info.operationClass != TEE_OPERATION_DIGEST) { + TZ_ERROR("param error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (chunk + != NULL&& uci_md_update(op->crypto, (unsigned char*)chunk, chunkLen) != UCI_SUCCESS) { + TZ_ERROR("uci_md_update error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_md_final(op->crypto, (unsigned char*)hash) != UCI_SUCCESS) { + TZ_ERROR("uci_md_final error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + *hashLen = op->info.digestLength; + return TEE_SUCCESS; +} + +// Symmetric Cipher Functions +void TEE_CipherInit(TEE_OperationHandle operation, const void* IV, size_t IVLen) { + int ret; + unsigned int mode; + unsigned char key1[32] = {0x0, }; + //unsigned char key2[32] = {0x0, }; + unsigned int key_len1 = sizeof(key1); + //unsigned int key_len2 = sizeof(key2); + unsigned int uci_alg; + TEE_Result rc; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_CIPHER) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (op->key1) { + rc = TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_SECRET_VALUE, key1, + &key_len1); + if (rc != TEE_SUCCESS) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + } + switch (op->info.algorithm) { + case TEE_ALG_AES_ECB_NOPAD: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_ECB; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_ECB; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + switch (key_len1) { + case 16: + uci_alg = ID_UCI_AES128; + break; + case 24: + uci_alg = ID_UCI_AES192; + break; + case 32: + uci_alg = ID_UCI_AES256; + break; + default: + TZ_ERROR("key len error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(uci_alg, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + + + // KRISHNA - ADDED NEW ALGO + case TEE_ALG_AES_ECB_PKCS7: + case TEE_ALG_AES_ECB_PKCS5: + case TEE_ALG_AES_ECB_ISO9797_M1 : + case TEE_ALG_AES_ECB_ISO9797_M2 : + + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_ECB; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_ECB; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + switch (key_len1) { + case 16: + uci_alg = ID_UCI_AES128; + break; + case 24: + uci_alg = ID_UCI_AES192; + break; + case 32: + uci_alg = ID_UCI_AES256; + break; + default: + TZ_ERROR("key len error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + + op->crypto = uci_context_alloc(uci_alg, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + + + + + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CBC_PKCS5: + case TEE_ALG_AES_CBC_PKCS7: + case TEE_ALG_AES_CBC_ISO9797_M1: + case TEE_ALG_AES_CBC_ISO9797_M2: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_CBC; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_CBC; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + switch (key_len1) { + case 16: + uci_alg = ID_UCI_AES128; + break; + case 24: + uci_alg = ID_UCI_AES192; + break; + case 32: + uci_alg = ID_UCI_AES256; + break; + default: + TZ_ERROR("key len error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(uci_alg, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_CTR_NOPAD: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_CTR; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_CTR; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + switch (key_len1) { + case 16: + uci_alg = ID_UCI_AES128; + break; + case 24: + uci_alg = ID_UCI_AES192; + break; + case 32: + uci_alg = ID_UCI_AES256; + break; + default: + TZ_ERROR("key len error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(uci_alg, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_ALG_AES_CTS: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_CTS; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_CTS; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + switch (key_len1) { + case 16: + uci_alg = ID_UCI_AES128; + break; + case 24: + uci_alg = ID_UCI_AES192; + break; + case 32: + uci_alg = ID_UCI_AES256; + break; + default: + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(uci_alg, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_ZERO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_ALG_AES_XTS: + TZ_ERROR("TEE_ALG_AES_XTS not support NOW!!"); + TEE_Panic(0); + break; + case TEE_ALG_DES_ECB_NOPAD: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_ECB; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_ECB; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(ID_UCI_DES, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_ALG_DES_CBC_NOPAD: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_CBC; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_CBC; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(ID_UCI_DES, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_ALG_DES3_ECB_NOPAD: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_ECB; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_ECB; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(ID_UCI_TDES, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_ALG_DES3_CBC_NOPAD: + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = ID_UCI_ENC_CBC; + } else if (op->info.mode == TEE_MODE_DECRYPT) { + mode = ID_UCI_DEC_CBC; + } else { + TZ_ERROR("Invalid mode error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op->crypto = uci_context_alloc(ID_UCI_TDES, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_se_init(op->crypto, mode, ID_UCI_NO_PADDING, key1, key_len1, + (unsigned char *)IV); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + default: + TZ_ERROR("algorithm error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; +} + +TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void* srcData, + size_t srcLen, void* destData, size_t *destLen) { + int ret; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_CIPHER) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (destData == NULL) { + return TEE_ERROR_SHORT_BUFFER; + } + ret = uci_se_process(op->crypto, (unsigned char *)srcData, srcLen, + (unsigned char*)destData, (unsigned int*)destLen); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_process error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + ; + } + return TEE_SUCCESS; +} + +TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, const void* srcData, + size_t srcLen, void* destData, size_t *destLen) { + int ret; + size_t blocksize = 8; + int tmp = 0; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_CIPHER) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (destData == NULL) { + return TEE_ERROR_SHORT_BUFFER; + } + *destLen = 0; + if (op->info.algorithm == TEE_ALG_AES_CTS) { + + ret = uci_se_final(op->crypto, (unsigned char *)srcData, srcLen, + (unsigned char*)destData, (unsigned int*)destLen); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_final error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + ; + } + return TEE_SUCCESS; + } + if (op->info.algorithm == TEE_ALG_AES_ECB_NOPAD + || op->info.algorithm == TEE_ALG_AES_CBC_NOPAD + || op->info.algorithm == TEE_ALG_AES_CTR + || op->info.algorithm == TEE_ALG_AES_XTS + ) { + + blocksize = 16; + } + // printf("srcLen is %d, blocksize is %d\n",srcLen, blocksize); + if (srcLen > blocksize) { + ret = uci_se_process(op->crypto, (unsigned char *)srcData, + srcLen - blocksize, (unsigned char*)destData, (unsigned int*)&tmp); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_final error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + + *destLen = tmp; + ret = uci_se_final(op->crypto, (unsigned char *)srcData + tmp, blocksize, + (unsigned char*)destData + tmp, (unsigned int*)&tmp); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_final error line = %d,%s,ret=%d\n", __LINE__, __func__, ret); + TEE_Panic(0); + ; + } + *destLen += tmp; + } else { + + ret = uci_se_final(op->crypto, (unsigned char *)srcData, srcLen, + (unsigned char*)destData, (unsigned int*)destLen); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_se_final error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + ; + } + } + return TEE_SUCCESS; +} + +// MAC Functions +void TEE_MACInit(TEE_OperationHandle operation, const void* IV, size_t IVLen) { + TEE_Result rc = TEE_SUCCESS; + unsigned char key[128] = {0x0, }; + size_t key_len = sizeof(key); + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_MAC) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (op->key1) { + rc = TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_SECRET_VALUE, key, + &key_len); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + TEE_Panic(0); + } + } + if (uci_mac_init(op->crypto, key, key_len) != UCI_SUCCESS) { + TZ_ERROR("uci_mac_init error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; +} + +void TEE_MACUpdate(TEE_OperationHandle operation, const void* chunk, + size_t chunkSize) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_MAC) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_mac_update(op->crypto, (unsigned char *)chunk, + chunkSize) != UCI_SUCCESS) { + TZ_ERROR("uci_mac_update error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } +} + +TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, + const void* message, size_t messageLen, void* mac, size_t *macLen) { + + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_MAC) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_mac_update(op->crypto, (unsigned char *)message, + messageLen) != UCI_SUCCESS) { + TZ_ERROR("uci_mac_update error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_mac_final(op->crypto, (unsigned char*)mac, macLen) != UCI_SUCCESS) { + TZ_ERROR("uci_mac_final error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, + const void* message, size_t messageLen, const void* mac, size_t *macLen) { + unsigned char tmpmac[128]; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_MAC) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_mac_update(op->crypto, (unsigned char*)message, + messageLen) != UCI_SUCCESS) { + TZ_ERROR("uci_mac_update error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_mac_final(op->crypto, tmpmac, macLen) != UCI_SUCCESS) { + TZ_ERROR("uci_mac_final error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (memcmp(mac, tmpmac, *macLen) != 0) { + return TEE_ERROR_MAC_INVALID; + } + return TEE_SUCCESS; +} + +// Authenticated Encryption Functions + +TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void* nonce, + size_t nonceLen, uint32_t tagLen, uint32_t AADLen, uint32_t payloadLen) { + + TEE_Result rc = TEE_SUCCESS; + unsigned char key[128]; + size_t key_len = sizeof(key); + int ret; + int mode; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_AE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (op->key1) { + rc = TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_SECRET_VALUE, key, + &key_len); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + TEE_Panic(0); + } + } + if (op->info.mode == TEE_MODE_ENCRYPT) { + mode = 1; + } else { + mode = 0; + } + if (operation->info.algorithm == TEE_ALG_AES_CCM) { + if (tagLen != 128 && tagLen != 112 && tagLen != 96 && tagLen != 64 + && tagLen != 48 && tagLen != 32) { + TZ_ERROR("tagLen error line = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_NOT_SUPPORTED; + } + op->crypto = uci_context_alloc(ID_UCI_AE_CCM, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + + ret = uci_authcrypt_init(op->crypto, mode, (unsigned char*)nonce, nonceLen, + tagLen / 8, AADLen, payloadLen, key, key_len); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_authcrypt_init error line = %d,%s \n", __LINE__, __func__); + TEE_Panic(0); + } + } else if (operation->info.algorithm == TEE_ALG_AES_GCM) { + if (tagLen != 128 && tagLen != 120 && tagLen != 112 && tagLen != 104 + && tagLen != 96) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + return TEE_ERROR_NOT_SUPPORTED; + } + op->crypto = uci_context_alloc(ID_UCI_AE_GCM, UCI_SW); + if (op->crypto == UCI_ERROR || op->crypto == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_authcrypt_init(op->crypto, mode, (unsigned char*)nonce, nonceLen, + tagLen / 8, 0, 0, key, key_len); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_authcrypt_init error line = %d,%s \n", __LINE__, __func__); + TEE_Panic(0); + } + } + operation->info.digestLength = tagLen; + operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; + return TEE_SUCCESS; +} + +void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void* AADdata, + size_t AADdataLen) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_AE) { + TZ_ERROR("operation error line = %d,%s \n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s \n", __LINE__, __func__); + TEE_Panic(0); + } + if (operation->info.algorithm == TEE_ALG_AES_CCM + || operation->info.algorithm == TEE_ALG_AES_GCM) { + if (uci_authcrypt_update_aad(op->crypto, (unsigned char*)AADdata, + AADdataLen) != UCI_SUCCESS) { + TZ_ERROR("uci_authcrypt_update_aad error line = %d,%s \n", __LINE__, + __func__); + TEE_Panic(0); + } + } +} + +TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void* srcData, + size_t srcLen, void* destData, size_t *destLen) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_AE) { + TZ_ERROR("operation error line = %d,%s \n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s \n", __LINE__, __func__); + TEE_Panic(0); + } + if (*destLen < srcLen) { + return TEE_ERROR_SHORT_BUFFER; + } + if (operation->info.algorithm == TEE_ALG_AES_CCM + || operation->info.algorithm == TEE_ALG_AES_GCM) { + if (uci_authcrypt_update(op->crypto, (unsigned char*)srcData, srcLen, + (unsigned char*)destData, destLen) != UCI_SUCCESS) { + TZ_ERROR("uci_authcrypt_update_aad error line = %d,%s \n", __LINE__, + __func__); + TEE_Panic(0); + } + } + return TEE_SUCCESS; +} + +TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, + const void* srcData, size_t srcLen, void* destData, size_t* destLen, + void* tag, size_t* tagLen) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_AE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (*destLen < srcLen) { + return TEE_ERROR_SHORT_BUFFER; + } + if (uci_authcrypt_encryptfinal(op->crypto, (unsigned char*)srcData, srcLen, + (unsigned char*)destData, destLen, (unsigned char*)tag, + tagLen) != UCI_SUCCESS) { + TZ_ERROR("uci_authcrypt_encryptfinal error line = %d,%s \n", __LINE__, + __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void* srcData, size_t srcLen, void* destData, size_t *destLen, + void* tag, size_t tagLen) { + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_AE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (*destLen < srcLen) { + TZ_ERROR("destLen error line = %d,%s \n", __LINE__, __func__); + return TEE_ERROR_SHORT_BUFFER; + } + if (uci_authcrypt_decryptfinal(op->crypto, (unsigned char*)srcData, srcLen, + (unsigned char*)destData, destLen, (unsigned char*)tag, + tagLen) != UCI_SUCCESS) { + TZ_ERROR("uci_authcrypt_decryptfinal error line = %d,%s \n", __LINE__, + __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, + const TEE_Attribute* params, uint32_t paramCount, const void* srcData, + size_t srcLen, void* destData, size_t *destLen) { + int ret; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_ae_encrypt(op->crypto, (unsigned char *)srcData, srcLen, + (unsigned char*)destData, destLen); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_ae_encrypt error. ret= %d,line = %d,%s\n", ret, __LINE__, + __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, + const TEE_Attribute* params, uint32_t paramCount, const void* srcData, + size_t srcLen, void* destData, size_t *destLen) { + int ret; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_ae_decrypt(op->crypto, (unsigned char *)srcData, srcLen, + (unsigned char*)destData, destLen); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_ae_decrypt error. ret= %d,line = %d,%s\n", ret, __LINE__, + __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, + const TEE_Attribute* params, uint32_t paramCount, const void* digest, + size_t digestLen, void* signature, size_t *signatureLen) { + int ret; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_ds_sign(op->crypto, (unsigned char *)digest, digestLen, + (unsigned char*)signature, signatureLen); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_ds_sign error. ret= %d,line = %d,%s\n", ret, __LINE__, + __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, + const TEE_Attribute* params, uint32_t paramCount, const void* digest, + size_t digestLen, void* signature, size_t signatureLen) { + int ret = UCI_ERROR; + int result = -1; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + ret = uci_ds_verify(op->crypto, (unsigned char *)digest, digestLen, + (unsigned char*)signature, signatureLen, &result); + if (ret != UCI_SUCCESS) { + TZ_ERROR("uci_ds_verify error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (result != UCI_VALID_SIGN) { + TZ_ERROR("uci_ds_verify error. ret= %d,line = %d,%s\n", result, __LINE__, + __func__); + TEE_Panic(0); + } + return TEE_SUCCESS; +} + +void TEE_DeriveKey(TEE_OperationHandle operation, const TEE_Attribute* params, + uint32_t paramCount, TEE_ObjectHandle derivedKey) { + uint32_t i = 0; + unsigned char authkey[512]; + unsigned char privkey[512]; + unsigned char *pubkey = NULL; + unsigned int pubkey_len = 0; + unsigned int privkey_len = sizeof(privkey); + TEE_Attribute attrs[1]; + TEE_Result rc; + struct TEE_Operation * op = (struct TEE_Operation*)operation; + + if (op->info.operationClass != TEE_OPERATION_KEY_DERIVATION) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!params) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (op->info.mode != TEE_MODE_DERIVE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + for (i = 0; i < paramCount; i++) { + if (params[i].attributeID == TEE_ATTR_DH_PUBLIC_VALUE) { + pubkey = (unsigned char*)params[i].content.ref.buffer; + pubkey_len = params[i].content.ref.length / 8; + break; + } + } + rc = TEE_GetObjectBufferAttribute(op->key1, TEE_ATTR_DH_PRIVATE_VALUE, + privkey, &privkey_len); + if (rc != TEE_SUCCESS) { + TZ_ERROR("TEE_GetObjectBufferAttribute error line = %d,%s\n", __LINE__, + __func__); + return; + } + if (pubkey_len == 0 || !pubkey || privkey_len == 0) { + TZ_ERROR("params error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if ((i = uci_dh_gen_authkey(op->crypto, privkey, pubkey, authkey)) + != UCI_SUCCESS) { + TZ_ERROR(" uci_dh_gen_authkey error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + PrintBYTE("privkey", privkey, privkey_len); + PrintBYTE("pubkey", pubkey, privkey_len); + TEE_InitRefAttribute(&attrs[0], TEE_ATTR_SECRET_VALUE, authkey, pubkey_len); + TEE_PopulateTransientObject(derivedKey, attrs, 1); +} + +void TEE_GenerateRandom(void* randomBuffer, size_t randomBufferLen) { + int i = 0; + unsigned char seed[16]; + //unsigned int seedLen = 16; + unsigned int res; + unsigned long get_time = getClock(); + + srand(get_time); + + for (i = 0; i < 16; i++) { + res = rand(); + seed[i] = res & 0xFF; + } + UCI_HANDLE oh = uci_context_alloc(ID_UCI_X931, UCI_SW); + if (oh == UCI_ERROR || oh == UCI_MEM_ALLOR_ERROR) { + TZ_ERROR("uci_context_alloc error line = %d, %s", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_prng_seed(oh, seed) != UCI_SUCCESS) { + TZ_ERROR("uci_prng_seed line = %d, %s", __LINE__, __func__); + TEE_Panic(0); + } + if (uci_prng_get(oh, randomBufferLen, + (unsigned char*)randomBuffer) != UCI_SUCCESS) { + TZ_ERROR("uci_prng_get line = %d, %s", __LINE__, __func__); + TEE_Panic(0); + } +} diff --git a/ssflib/src/ssf_lib.c b/ssflib/src/ssf_lib.c new file mode 100755 index 0000000..428c053 --- /dev/null +++ b/ssflib/src/ssf_lib.c @@ -0,0 +1,114 @@ +/* + * ===================================================================================== + * + * Filename: ssflib.c + * + * Description: SSF Library functions + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ssf_lib.h" +#include "ssf_client.h" +#include +#include + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +extern TEE_UUID sharedthisTAUUID; +int32_t socketSimulatorDaemonFD = 0; +pthread_mutex_t socketLock = PTHREAD_MUTEX_INITIALIZER; +TeeStubSSFSharedData sharedData = {false, false, true}; + +/*----------------------------------------------------------------------------- + * Local functions + *-----------------------------------------------------------------------------*/ +extern "C"{ + +/** + * Initializes SSF for use by TA + */ +__attribute__((constructor)) void initializeSSF() { + + socketSimulatorDaemonFD = connecttoServer(); + assert(socketSimulatorDaemonFD != -1); + LOGD(SIM_DAEMON, "Done");} + +/** + * Deinits SSF. Should be called by TA once + */ + +__attribute__((destructor)) void deinitializeSSF() { + disconnectfromServer(socketSimulatorDaemonFD); + LOGD(SIM_DAEMON, "Done"); } + +} +/* ========================================================================= + * OPERATION CANCELLATION + * ========================================================================= + */ + +/** + * Determines whether the current task's Cancellation Flag is set + * + * The TEE_GetCancellationFlag function determines whether the current task's + * Cancellation Flag is set. If cancellations are masked, this function must + * return false. + * + * @return 'false' if the cancellation flag is not set or if cancellations are + * masked; 'true' if the cancellation flag is set and cancellations are not + * masked + */ +bool TEE_GetCancellationFlag(void) { +return (sharedData.thisTaskMask ? false : sharedData.thisTaskCancel); +} + +/** + * Unmasks the effects of cancellation + * + * The TEE_UnmaskCancellation function unmasks the effects of cancellation for + * the current task. When cancellation requests are unmasked, the Cancellation + * Flag interrupts cancellable functions such as @ref TEE_Wait and requests the + * cancellation of operations started with @ref TEE_OpenTASession or + * @ref TEE_InvokeTACommand. By default, tasks created to handle a TA entry + * point have cancellation masked, so that a TA does not have to cope with the + * effects of cancellation requests. + * @return 'true' if cancellations were masked prior to calling this function; + * 'false' otherwise + */ +bool TEE_UnmaskCancellation(void) { +bool preState = sharedData.thisTaskMask; +sharedData.thisTaskMask = false; +return (preState ? true : false); +} + +/** + * Masks the effects of cancellation + * + * The TEE_MaskCancellation function masks the effects of cancellation for the + * current task. When cancellation requests are masked, the Cancellation Flag + * does not have an effect on the cancellable functions and cannot be retrieved + * using @ref TEE_GetCancellationFlag. By default, tasks created to handle a TA + * entry point have cancellation masked, so that a TA does not have to cope with + * the effects of cancellation requests. + * + * @return 'true' if cancellations were masked prior to calling this function; + * 'false' otherwise + */ +bool TEE_MaskCancellation(void) { +bool preState = sharedData.thisTaskMask; +sharedData.thisTaskMask = true; +return (preState ? true : false); +} diff --git a/ssflib/src/ssf_malloc.c b/ssflib/src/ssf_malloc.c new file mode 100755 index 0000000..77e27a7 --- /dev/null +++ b/ssflib/src/ssf_malloc.c @@ -0,0 +1,239 @@ +/* + * ===================================================================================== + * + * Filename: ssf_malloc.c + * + * Description: SSF malloc functions + * + * Version: 1.0 + * Created: 23 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include +#include +#include "ssf_lib.h" + +/*----------------------------------------------------------------------------- + * Globals + *-----------------------------------------------------------------------------*/ +/** + * For use by: TEE_GetInstanceData and TEE_SetInstanceData + */ +static void* globalTAInstanceData = 0; + +/*----------------------------------------------------------------------------- + * TEE API implementation + *-----------------------------------------------------------------------------*/ +/** + * Allocates space for an object + * + * The TEE_Malloc function allocates space for an object whose size in bytes is + * specified in the parameter size. + * + * @param[in] size The size of the buffer to be allocated. + * @param[in] hint A hint to the allocator. Currently defined values are as + * follows: + * + * + The default value, 0, guarantees that the returned block of memory is + * filled with zeros. + * + * + Values in the range [0x00000001, 0x7FFFFFFF] are reserved for future + * version of this specification. + * + * + Values in the range [0x80000000, 0xFFFFFFFF] can be used for + * implementation-defined hints. + * + * @return Upon successful completion, with size not equal to zero, the function + * returns a pointer to the allocated space. If the space cannot be allocated, a + * NULL pointer is returned. + */ +void* TEE_Malloc(size_t size, uint32_t hint) { + void* buf = OsaMalloc(size); + if (NULL == buf) { + return NULL; + } + if (0 == hint) { + memset(buf, 0, size); + } + return buf; +} + +/** + * Changes the size of the memory object + * + * The TEE_Realloc function changes the size of the memory object pointed to by + * buffer to the size specified by nNewSize. + * + * @param[in] buffer: The pointer to the object to be reallocated + * @param[in] newSize: The new size required for the object + * + * @return Upon successful completion, TEE_Realloc returns a pointer to the + * (possibly moved) allocated space. If there is not enough available memory, + * TEE_Realloc returns a NULL pointer. + */ +void* TEE_Realloc(const void* buffer, uint32_t newSize) { + return realloc((void*)buffer, newSize); +} + +/** + * Causes the space pointed to by buffer to be deallocated + * + * The TEE_Free function causes the space pointed to by buffer to be + * deallocated; that is, made available for further allocation. If buffer is a + * NULL pointer, TEE_Free does nothing. Otherwise, it is a Programmer Error + * if the argument does not match a pointer previously returned by the + * @ref TEE_Malloc or @ref TEE_Realloc, or if the space has been deallocated by + * a call to TEE_Free or @ref TEE_Realloc. + * + * @param[in] buffer The pointer to the memory block to be freed + */ +void TEE_Free(const void *buffer) { + if (buffer) { + OsaFree((void*)buffer); + } +} + +/** + * Copies size bytes from one object to another + * + * The TEE_MemMove function copies size bytes from the object pointed to by src + * into the object pointed to by dest. Note that the buffers dest and src can + * reside in any kinds of memory, including shared memory. + * + * @param[in] dest A pointer to the destination buffer + * @param[in] src A pointer to the source buffer + * @param[in] size The number of bytes to be copied + */ +void TEE_MemMove(void* dest, const void* src, uint32_t size) { + memmove(dest, src, size); +} + +/** + * Compares bytes of one object to another + * + * The TEE_MemCompare function compares the first size bytes of the object + * pointed to by buffer1 to the first size bytes of the object pointed to by + * buffer2. Note that buffer1 and buffer2 can reside in any kinds of memory, + * including shared memory. + * + * @param[in] buffer1 A pointer to the first buffer + * @param[in] buffer2 A pointer to the second buffer + * @param[in] size The number of bytes to be compared + * + * @return The sign of a non-zero return value is determined by the sign of the + * difference between the values of the first pair of bytes (both interpreted as + * type uint8_t) that differ in the objects being compared. + * + * + If the first byte that differs is higher in buffer1, then return an integer + * greater than zero. + * + * + If the first size bytes of the two buffers are identical, then return zero. + * + * + If the first byte that differs is higher in buffer2, then return an integer + * lower than zero. + */ +int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size) { + uint32_t i = 0; + uint8_t* buf1 = (uint8_t*)buffer1; + uint8_t* buf2 = (uint8_t*)buffer2; + for (; i < size; ++i) { + if (buf1[i] > buf2[i]) { + return 1; + } else if (buf1[i] < buf2[i]) { + return -1; + } + } + return 0; +} + +/** + * Writes the byte x into the object + * + * The TEE_MemFill function writes the byte x (converted to a uint8_t) into the + * first size bytes of the object pointed to by buffer. Note that buffer can + * reside in any kinds of memory, including shared memory. + * + * @param[in] buffer A pointer to the destination buffer + * @param[in] x The value to be set + * @param[in] size The number of bytes to be set + */ +void TEE_MemFill(void* buffer, uint32_t x, uint32_t size) { + if (NULL == buffer) { + return; + } + uint32_t i = 0; + uint8_t* buf = (uint8_t*)buffer; + for (; i < size; ++i) { + buf[i] = (uint8_t)x; + } +} + +/** + * Checks specified buffer for access rights + * + * The TEE_CheckMemoryAccessRights function causes the Implementation to examine + * a buffer of memory specified in the parameters buffer and size and to + * determine whether the current Trusted Application instance has the access + * rights requested in the parameter accessFlags. If the characteristics of the + * buffer are compatible with accessFlags, then the function returns + * TEE_SUCCESS. Otherwise, it returns TEE_ERROR_ACCESS_DENIED. Note that the + * buffer should not be accessed by the function, but the Implementation should + * check the access rights based on the address of the buffer and internal + * memory management information. + * This function MUST NOT panic for any reason. + * + * @param[in] buffer Pointer to the buffer to check + * @param[in] size Size of the buffer to check + * @param[in] accessFlags The access flags to check + * + * @return TEE_SUCCESS: If the entire buffer allows the requested accesses or + * TEE_ERROR_ACCESS_DENIED: If at least one byte in the buffer is not accessible + * with the requested accesses + */ +TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void* buffer, + size_t size) { + //TODO: Need to verify ow this function will be used + return TEE_SUCCESS; +} + +/** + * Provides an alternative to writable global data + * + * The TEE_SetInstanceData and TEE_GetInstanceData functions provide an + * alternative to writable global data (writable variables with global scope and + * writable static variables with global or function scope). While an + * Implementation supports C global variables, using these functions may be + * sometimes more efficient, especially if only a single instance data variable + * is required. + * + * @param[in] instanceData A pointer to the global Trusted Application instance + * data. This pointer may be NULL. + */ +void TEE_SetInstanceData(void* instanceData) { + globalTAInstanceData = instanceData; +} + +/** + * Retrieves the instance data pointer + * + * The TEE_GetInstanceData function retrieves the instance data pointer set by + * the Trusted Application using the @ref TEE_GetInstanceData function. + * + * @return The value returned is the previously set pointer to the Trusted + * Application instance data, or NULre:\L if no instance data pointer has yet been + * set. + */ +void* TEE_GetInstanceData(void) { + return globalTAInstanceData; +} diff --git a/ssflib/src/ssf_panic.c b/ssflib/src/ssf_panic.c new file mode 100755 index 0000000..e08f5f2 --- /dev/null +++ b/ssflib/src/ssf_panic.c @@ -0,0 +1,48 @@ +/* + * ===================================================================================== + * + * Filename: ssf_panic.c + * + * Description: SSF oanic functions + * + * Version: 1.0 + * Created: 23 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include +#include "ssf_lib.h" +#include "ssf_client.h" +#include "tee_command.h" + +/* ========================================================================= + * PANIC + * ========================================================================= + */ +/* Krishna Devale: + * Options to implement panic and send back a signal to the execution logic of + * TEEStub to clean up and exit + * 1. Use pthread lock on a global variable "bool panic" + * The TEEStub will wait on this lock for read/write access to global variable "panic" + * When "panic" is detected as true in execution engine, TEEStub exits. + * Here TEE_Panic allows the the called entry point to complete and exit + * This behaviour may be not desirable. [Confirm this] + * + * 2. Use a callback function registered to SSFLib on its init. + * This callback is defined in TEEStub. The TEE_Panic function calls the callback function. + * This callback is expected to perform cleanup and do a clean exit. + * This callback never returns to TEE_Panic. Thus, TEE_Panic is guaranteed to exit + * without returning to its calling function + */ +void TEE_Panic(TEE_Result panic_code) { + exit(0); +} diff --git a/ssflib/src/ssf_storage.c b/ssflib/src/ssf_storage.c new file mode 100755 index 0000000..60ad4fb --- /dev/null +++ b/ssflib/src/ssf_storage.c @@ -0,0 +1,2037 @@ +/* + * ===================================================================================== + * + * Filename: ssf_storage.c + * + * Description: SSF storage functions + * + * Version: 1.0 + * Created: 23 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ssf_storage.h" +#include +#include + +/*----------------------------------------------------------------------------- + * MACROS + *-----------------------------------------------------------------------------*/ +#define __FREE(buf) if(buf) {OsaFree(buf); buf = NULL;} +#define FREE_PO(po) if(po) {clean_po_file(po);OsaFree(po); po = NULL;} + +#define PO_INTERNAL_MODULE_NAME "po_file" +#define PO_STAT_INTERNAL_MODULE_NAME "po_stat" +#define PI_FILE_NAME "pi_file" +#define UUID_FILE "/usr/apps/tee/TA-UUID.list" + +TEE_UUID ssf_sharedthisTAUUID; +static TEE_UUID this_uuid; +static int uuid_got = 0; + +#define g_bTAdbug 1 +#define TZ_PRINT(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) +#define TZ_ERROR(fmt...) \ + do {if (g_bTAdbug) printf("[SSFLIB] ");printf(fmt);}while(0) + +#if 0 +int get_ta_name(char* ta_name) { + pid_t pid = getpid(); + char path[256] = {0}; + char ta_path[256] = {0}; + sprintf(path, "/proc/%d/exe", pid); + int cnt = readlink(path, ta_path, 256); + if (cnt < 0 || cnt > 256) { + MSG("Error readlink."); + return -1; + } + ta_path[cnt] = '\0'; + int idx = cnt - 1; + for (; idx >= 0; idx--) { + if (ta_path[idx] == '/') { + strcpy(ta_name, ta_path + idx + 1); + return 0; + } + } + return -1; +} +#endif + +/*----------------------------------------------------------------------------- + * Local functions + *-----------------------------------------------------------------------------*/ +int get_uuid() { +//assigns UIID obtained from TEEStub + this_uuid = ssf_sharedthisTAUUID; + uuid_got = 1; + return 0; +#if 0 + if (uuid_got) + { + return 0; + } + char ta_name[256] = + { 0}; + if (0 != get_ta_name(ta_name)) + { + MSG("Failed to get ta name."); + return -1; + } + FILE* f = fopen(UUID_FILE, "r"); + if (!f) + { + MSG("Can't open file %s\n", UUID_FILE); + return -1; + } + char name[256]; + char *line = NULL; + size_t len = 0; + ssize_t read_bytes; + int matched = 0; + TEE_UUID uuid; + while (-1 != getline(&line, &len, f)) + { + matched = + sscanf(line, + "TA={ %x , %hx , %hx , { %hhx , %hhx , %hhx , %hhx , %hhx , %hhx , %hhx , %hhx } } : %64s", + &uuid.timeLow, &uuid.timeMid, &uuid.timeHiAndVersion, + &uuid.clockSeqAndNode[0], &uuid.clockSeqAndNode[1], + &uuid.clockSeqAndNode[2], &uuid.clockSeqAndNode[3], + &uuid.clockSeqAndNode[4], &uuid.clockSeqAndNode[5], + &uuid.clockSeqAndNode[6], &uuid.clockSeqAndNode[7], + name); + if (matched != 12 || matched == EOF) + { + MSG("bad format for uuid:%s\n", line); + continue; + } + OsaFree(line); + line = NULL; + MSG("ta_name [%s] <=> name [%s]", ta_name, name); + if (0 == memcmp(ta_name, name, strlen(ta_name))) + { + this_uuid = uuid; + uuid_got = 1; + fclose(f); + return 0; + } + } + fclose(f); + return -1; +#endif +} + +void printhex(unsigned char* buf, unsigned int size) { + MSG("---------------------------------------------------"); + unsigned int i; + for (i = 0; i < size; ++i) { + if (0 == (i % 16) && i) { + printf("\n"); + } + printf("%02x ", buf[i]); + } + MSG("\n---------------------------------------------------"); +} + +/*----------------------------------------------------------------------------- + * TEE API implementation + *-----------------------------------------------------------------------------*/ +//////////////////////////////////////////////////////////////////////////////////// +// internal attribute operations +//////////////////////////////////////////////////////////////////////////////////// +TEE_Result copy_attribute(TEE_Attribute* dest, TEE_Attribute* src) { + if (!dest || !src) { + return TEE_ERROR_BAD_PARAMETERS; + } + dest->attributeID = src->attributeID; + if (src->attributeID & TEE_ATTR_FLAG_VALUE) { + dest->content.value.a = src->content.value.a; + dest->content.value.b = src->content.value.b; + } else { + int buf_size = (src->content.ref.length + 7) / 8; + void* buffer = OsaMalloc(buf_size); + if (!buffer) { + return TEE_ERROR_OUT_OF_MEMORY; + } + memcpy(buffer, src->content.ref.buffer, buf_size); + dest->content.ref.buffer = buffer; + dest->content.ref.length = src->content.ref.length; + } + return TEE_SUCCESS; +} + +void free_attribute(TEE_Attribute* attr) { + if (!attr) { + return; + } + if (!(attr->attributeID & TEE_ATTR_FLAG_VALUE)) { + OsaFree((void*)attr->content.ref.buffer); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// Internal transient Object Operations +///////////////////////////////////////////////////////////////////////////////////////////// +TEE_Result allocate_transient_object(TransientObject* tr, uint32_t objectType, + uint32_t maxObjectSize) { + tr->attr.attr_number = 0; + +/* switch (objectType) { + case TEE_TYPE_AES: + if (maxObjectSize != 128 && maxObjectSize != 192 + && maxObjectSize != 256) { + return TEE_ERROR_NOT_SUPPORTED; + } + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_DES: + //if (maxObjectSize != 64) { + // return TEE_ERROR_NOT_SUPPORTED; + //} + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_DES3: + if (maxObjectSize != 128 && maxObjectSize != 192) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_HMAC_MD5: + if (maxObjectSize < 64 || maxObjectSize > 512 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_HMAC_SHA1: + if (maxObjectSize < 80 || maxObjectSize > 512 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_HMAC_SHA224: + if (maxObjectSize < 112 || maxObjectSize > 512 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_HMAC_SHA256: + if (maxObjectSize < 192 || maxObjectSize > 1024 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_HMAC_SHA384: + if (maxObjectSize < 256 || maxObjectSize > 1024 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_HMAC_SHA512: + if (maxObjectSize < 256 || maxObjectSize > 1024 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + case TEE_TYPE_RSA_PUBLIC_KEY: + case TEE_TYPE_RSA_KEYPAIR: + if (maxObjectSize < 256 || maxObjectSize > 3072) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = sizeof(rsa_context); + break; + case TEE_TYPE_DSA_PUBLIC_KEY: + case TEE_TYPE_DSA_KEYPAIR: + if (maxObjectSize < 512 || maxObjectSize > 1024 || maxObjectSize % 64) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = sizeof(dsa_context); + break; + case TEE_TYPE_DH_KEYPAIR: + if (maxObjectSize < 256 || maxObjectSize > 2048) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = sizeof(dh_context); + break; + case TEE_TYPE_GENERIC_SECRET: + if (maxObjectSize > 4096 || maxObjectSize % 8) + return TEE_ERROR_NOT_SUPPORTED; + //tr->attr.buf_len = (maxObjectSize + 7)>>3; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } +*/ + // Object info + tr->info.objectType = objectType; + tr->info.objectSize = 0; + tr->info.maxObjectSize = maxObjectSize; + //tr->info.dataSize = 0; + //tr->info.dataPosition = 0; + //tr->info.handleFlags = 0; + tr->info.objectUsage = 0xffffffff; + return TEE_SUCCESS; +} + +size_t calc_attr_size(TransientObject* tr) { + size_t size = 0; + size += sizeof(int); + size += tr->attr.attr_number * 4; //attrID + TEE_Attribute* attrs = tr->attr.attr_array; + int i; + for (i = 0; i < tr->attr.attr_number; ++i) { + if (attrs[i].attributeID & TEE_ATTR_FLAG_VALUE) { + size += 2 * sizeof(uint32_t); + } else { + size += sizeof(size_t); + size += (attrs[i].content.ref.length + 7) / 8; + } + } + return size; +} + +TEE_Result serialise_attr(TransientObject* tr, char* buf) { + if (!buf) { + return TEE_ERROR_OUT_OF_MEMORY; + } + memcpy(buf, (void*)&tr->attr.attr_number, sizeof(int)); + buf += sizeof(int); + + TEE_Attribute* attrs = tr->attr.attr_array; + int i; + for (i = 0; i < tr->attr.attr_number; ++i) { + //AttrID + memcpy(buf, &(attrs[i].attributeID), 4); + buf += 4; + if (attrs[i].attributeID & TEE_ATTR_FLAG_VALUE) { + memcpy(buf, (void*)&(attrs[i].content.value.a), 2 * sizeof(uint32_t)); + buf += 2 * sizeof(uint32_t); + } else { + memcpy(buf, &(attrs[i].content.ref.length), 4); + buf += 4; + memcpy(buf, (void*)attrs[i].content.ref.buffer, + (attrs[i].content.ref.length + 7) / 8); + buf += (attrs[i].content.ref.length + 7) / 8; + } + } + return TEE_SUCCESS; +} + +TEE_Result deserialise_attr(char* buf, TransientObject* tr) { + if (!buf) { + return TEE_SUCCESS; + } + TEE_Attribute* attrs = tr->attr.attr_array; + memcpy(&tr->attr.attr_number, buf, sizeof(int)); + buf += sizeof(int); + + int i; + for (i = 0; i < tr->attr.attr_number; ++i) { + memcpy(&attrs[i].attributeID, buf, 4); + buf += 4; + if (attrs[i].attributeID & TEE_ATTR_FLAG_VALUE) { + memcpy((void*)&(attrs[i].content.value.a), buf, 2 * sizeof(uint32_t)); + buf += 2 * sizeof(uint32_t); + } else { + memcpy((void*)&attrs[i].content.ref.length, buf, 4); + buf += 4; + void* buffer = OsaMalloc((attrs[i].content.ref.length + 7) / 8); + if (!buffer) { + return TEE_ERROR_OUT_OF_MEMORY; + } + memcpy(buffer, buf, (attrs[i].content.ref.length + 7) / 8); + attrs[i].content.ref.buffer = buffer; + buf += (attrs[i].content.ref.length + 7) / 8; + } + } + return TEE_SUCCESS; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// Internal Persistent Object Operations +///////////////////////////////////////////////////////////////////////////////////////////// + +TEE_Result allocate_persistent_object(persistent_object** po, + uint32_t storageID, const void* objectID, size_t objectIDLen, + uint32_t flags) { + if (objectIDLen > TEE_OBJECT_ID_MAX_LEN) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (storageID != TEE_STORAGE_PRIVATE) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + persistent_object* tmp_po = (persistent_object*)OsaMalloc( + sizeof(persistent_object)); + if (!tmp_po) { + return TEE_ERROR_OUT_OF_MEMORY; + } + memset(tmp_po, 0, sizeof(persistent_object)); + + tmp_po->storage_id = storageID; + tmp_po->attr.info.handleFlags = flags; + tmp_po->obj_id_len = objectIDLen; + memcpy(tmp_po->object_id, objectID, objectIDLen); + if (0 != get_uuid()) { + MSG("Failed to get UUID of TA."); + FREE_PO(tmp_po); + return TEE_ERROR_GENERIC; + } + tmp_po->TA_UUID = this_uuid; + *po = tmp_po; + init_po(tmp_po); + return TEE_SUCCESS; +} + +TEE_Result create_po(persistent_object* po, TransientObject* attr, + const void* init_data, size_t data_size) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + TEE_Result rc; + if (NULL != attr) { + if (!(attr->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + rc = allocate_transient_object(&po->attr, attr->info.objectType, + attr->info.maxObjectSize); + if (rc != TEE_SUCCESS) { + return TEE_ERROR_OUT_OF_MEMORY; + } + // copy attributes +// TEE_CopyObjectAttributes((TEE_ObjectHandle) & po->attr, +// (TEE_ObjectHandle) attr); + + TEE_CopyObjectAttributes((TEE_ObjectHandle)&po->attr.info, + (TEE_ObjectHandle)attr); + + // get required buffer length + po->po_file.attr_size = calc_attr_size(&po->attr); + po->po_file.attr = (uint8_t*)OsaMalloc(po->po_file.attr_size); + if (NULL == po->po_file.attr) { + return TEE_ERROR_OUT_OF_MEMORY; + } + // fill attr + rc = serialise_attr(&po->attr, (char*)po->po_file.attr); + if (rc) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + } + + // fill data object + if (init_data && data_size) { + po->po_file.obj_data_size = data_size; + if (0 != po->po_file.obj_data_size) { + po->po_file.object_data = (uint8_t*)OsaMalloc(po->po_file.obj_data_size); + if (!po->po_file.object_data) { + return TEE_ERROR_OUT_OF_MEMORY; + } + memcpy(po->po_file.object_data, init_data, po->po_file.obj_data_size); + } + } + + // init object info + po->attr.info.dataPosition = 0; + po->attr.info.dataSize = data_size; + po->attr.info.handleFlags |= TEE_HANDLE_FLAG_PERSISTENT + | TEE_HANDLE_FLAG_INITIALIZED; + po->attr.info.objectUsage = 0xffffff; + po->attr.info.objectSize = + attr == TEE_HANDLE_NULL ? 0 : attr->info.objectSize; + + // write po file to ss + po->po_file.po_info = po->attr.info; + if (0 != write_po_file(po)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + memset(&g_po_info_file, 0, sizeof(po_info_file)); + // write to stat file. + if (write_po_info(&g_po_info_file, po->object_id, po->obj_id_len, + &po->attr.info)) { + return TEE_ERROR_GENERIC; + } + // update po share info + if (0 != update_share_info(&po->share_info, po->attr.info.handleFlags, 1)) { + return TEE_ERROR_GENERIC; + } + // add to po list + add_to_po_list(po); + return TEE_SUCCESS; +} + +TEE_Result open_po(persistent_object* po) { + int handleFlages; + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + int ret = update_share_info(&po->share_info, po->attr.info.handleFlags, 1); + if (0 != ret) { + return (1 == ret) ? TEE_ERROR_ACCESS_CONFLICT : TEE_ERROR_GENERIC; + } + // read and parse + ret = load_po_file(po); + if (0 != ret) { + ret = (1 == ret) ? TEE_ERROR_ITEM_NOT_FOUND : TEE_ERROR_GENERIC; + goto out; + } + if (deserialise_attr((char*)po->po_file.attr, (TransientObject*)&po->attr)) { + ret = TEE_ERROR_GENERIC; + goto out; + } + handleFlages = po->attr.info.handleFlags | TEE_HANDLE_FLAG_PERSISTENT + | TEE_HANDLE_FLAG_INITIALIZED; + po->attr.info = po->po_file.po_info; + po->attr.info.handleFlags = handleFlages; + po->attr.info.dataPosition = 0; + // add to po list + add_to_po_list(po); + ret = TEE_SUCCESS; + out: + if (ret) { + update_share_info(&po->share_info, po->attr.info.handleFlags, 0); + } + return ret; +} + +TEE_Result read_object_data(persistent_object* po, void* buffer, size_t size, + uint32_t* count) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!buffer) { + return TEE_ERROR_BAD_PARAMETERS; + } + if (0 == size || 0 == po->attr.info.dataSize) { + *count = 0; + return TEE_SUCCESS; + } + if (po->attr.info.dataPosition >= po->attr.info.dataSize) { + return TEE_ERROR_OVERFLOW; + } + int cpsz = + (po->attr.info.dataPosition + size >= po->attr.info.dataSize) ? + (po->attr.info.dataSize - po->attr.info.dataPosition) : size; + + void* src = po->po_file.object_data + po->attr.info.dataPosition; + memcpy(buffer, src, cpsz); + //update object info + po->attr.info.dataPosition += cpsz; + *count = cpsz; + return TEE_SUCCESS; +} + +TEE_Result seek_object_data(persistent_object* po, int32_t offset, + TEE_Whence whence) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + uint32_t begin_pos = 0; + if (TEE_DATA_SEEK_CUR == whence) { + begin_pos = po->attr.info.dataPosition; + } else if (TEE_DATA_SEEK_END == whence) { + begin_pos = po->attr.info.dataSize; + } + int32_t dataPos = begin_pos + offset; + if ((uint32_t)dataPos >= TEE_DATA_MAX_POSITION) { + return TEE_ERROR_OVERFLOW; + } + if (dataPos < 0) { + dataPos = 0; + } + // Not support "hole" in file in this version. + if ((uint32_t)dataPos > (po->attr.info.dataSize - 1)) { + dataPos = po->attr.info.dataSize; + } + po->attr.info.dataPosition = dataPos; + return TEE_SUCCESS; +} + +TEE_Result write_object_data(persistent_object* po, const void* buffer, + size_t size) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!buffer || !size) { + return TEE_SUCCESS; + } + if (po->attr.info.dataPosition > po->attr.info.dataSize) { + return TEE_ERROR_OVERFLOW; + } + uint32_t modified_size = po->attr.info.dataPosition + size; + if (modified_size <= po->attr.info.dataSize) { + memcpy(po->po_file.object_data + po->attr.info.dataPosition, buffer, size); + } else { + void* tmp_buf = OsaMalloc(modified_size); + if (NULL == tmp_buf) { + return TEE_ERROR_OUT_OF_MEMORY; + } + memcpy(tmp_buf, po->po_file.object_data, po->attr.info.dataPosition); + memcpy((uint8_t*)tmp_buf + po->attr.info.dataPosition, buffer, size); + OsaFree(po->po_file.object_data); + po->po_file.object_data = (unsigned char*)tmp_buf; + } + //update object info + po->attr.info.dataPosition += size; + po->attr.info.dataSize = + (modified_size > po->attr.info.dataSize) ? modified_size : + po->attr.info.dataSize; + // sync to ss. + po->po_file.po_info.dataSize = po->attr.info.dataSize; + if (-1 == write_po_file(po)) { + MSG("Failed to write po file to secure storage."); + return TEE_ERROR_GENERIC; + } + return TEE_SUCCESS; +} + +TEE_Result truncate_object_data(persistent_object* po, size_t size) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + // now not support the "hole" in file. + size_t trunc_sz = + po->attr.info.dataSize > size ? size : po->attr.info.dataSize; + if (trunc_sz == po->attr.info.dataSize) { + return TEE_SUCCESS; + } + po->attr.info.dataSize = trunc_sz; + po->po_file.po_info.dataSize = trunc_sz; + // write to ss + if (-1 == write_po_file(po)) { + return TEE_ERROR_GENERIC; + } + return TEE_SUCCESS; +} + +void close_po(persistent_object* po) { + if (NULL == po) { + return; + } + update_share_info(&po->share_info, po->attr.info.handleFlags, 0); + + // remove from po list + rem_from_po_list(po); + // free online attributes + TEE_Attribute* attrs = po->attr.attr.attr_array; + int i; + for (i = 0; i < po->attr.attr.attr_number; ++i) { + free_attribute(&attrs[i]); + } + FREE_PO(po); +} + +TEE_Result free_po(persistent_object* po) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (-1 == delete_po_file(po)) { + return TEE_ERROR_GENERIC; + } + // free online attributes + TEE_Attribute* attrs = po->attr.attr.attr_array; + int i; + for (i = 0; i < po->attr.attr.attr_number; ++i) { + free_attribute(&attrs[i]); + } + // remove from po list + rem_from_po_list(po); + release_share_info(&po->share_info); + FREE_PO(po); + return TEE_SUCCESS; +} + +TEE_Result rename_po(persistent_object* po, const void* newObjectID, + size_t newObjectIDLen) { + if (NULL == po) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (-1 == rename_po_file(po, newObjectID, newObjectIDLen)) { + return TEE_ERROR_GENERIC; + } + memcpy(po->object_id, newObjectID, newObjectIDLen); + po->obj_id_len = newObjectIDLen; + return TEE_SUCCESS; +} + +TEE_Result exist_po(persistent_object* po) { + int ret = ss_validate(po->po_file.file_name, &po->po_file.cred, + SS_OPT_DEFAULT); + if (SS_RET_CANT_FIND_REQUESTED_DATA == ret) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + if (SS_RET_SUCCESS == ret) { + return TEE_SUCCESS; + } + return TEE_ERROR_GENERIC; +} + +//////////////////////////////////////////////////////////////////////////////////// +// Persistent file operations +//////////////////////////////////////////////////////////////////////////////////// +void init_po(persistent_object* po) { + char uuid[64] = {0}; + convert_TA_UUID(uuid, po->TA_UUID); + MSG("UUID of the TA is %s.", uuid); + ss_set_credential(&po->po_file.cred, uuid, PO_INTERNAL_MODULE_NAME, 1, 0); + + //derive file name + derive_po_file_name((void*)po->object_id, po->obj_id_len, + po->po_file.file_name); + po->po_file.attr = NULL; + po->po_file.attr_size = 0; + po->po_file.object_data = NULL; + po->po_file.obj_data_size = 0; + // init po_share_info + po->share_info.fd = -1; + po->share_info.usr_info = NULL; + memcpy(po->share_info.name, po->po_file.file_name, PO_FILE_NAME_MAX_LEN); + po->po_list.prev = NULL; + po->po_list.next = NULL; + po->po_list.po = po; + regist_clean_up(); +} + +int derive_po_file_name(const void* obj_id, int obj_id_len, char* fn) { + byte_to_hex((unsigned char*)fn, (unsigned char*)obj_id, obj_id_len); + fn[2 * obj_id_len] = '\0'; + return 0; +} + +int load_po_file(persistent_object* po) { + uint8_t* retbuf = NULL; + uint8_t* tmp_ptr = NULL; + uint32_t read_size = 0; + int ret = ss_read(&retbuf, &read_size, 0, po->po_file.file_name, + &po->po_file.cred, SS_OPT_DEFAULT); + if (SS_RET_CANT_FIND_REQUESTED_DATA == ret) { + MSG("Po file not exist."); + return 1; + } + if (SS_RET_SUCCESS != ret) { + MSG("Failed to read data from secure storage, ret = %d.", ret); + return -1; + } + tmp_ptr = retbuf; + + // load po info + memcpy(&po->po_file.po_info, tmp_ptr, sizeof(TEE_ObjectInfo)); + tmp_ptr += sizeof(TEE_ObjectInfo); + // load attr + size_t attr_size = read_size - sizeof(TEE_ObjectInfo) + - po->po_file.po_info.dataSize; + po->po_file.attr_size = attr_size; + if (0 < po->po_file.attr_size) { + po->po_file.attr = (unsigned char*)OsaMalloc(attr_size); + memcpy(po->po_file.attr, tmp_ptr, attr_size); + } + tmp_ptr += attr_size; + + // load object data + po->po_file.obj_data_size = po->po_file.po_info.dataSize; + if (0 < po->po_file.obj_data_size) { + po->po_file.object_data = (unsigned char*)OsaMalloc( + po->po_file.obj_data_size); + memcpy(po->po_file.object_data, tmp_ptr, po->po_file.obj_data_size); + } + ss_free_buffer(retbuf); + return 0; +} + +int write_po_file(persistent_object* po) { + uint8_t* buf = NULL; + po->po_file.obj_data_size = po->attr.info.dataSize; + uint32_t buf_size = po->po_file.attr_size + po->po_file.obj_data_size + + sizeof(TEE_ObjectInfo); + buf = (unsigned char*)OsaMalloc(buf_size); + if (NULL == buf) { + MSG("Failed to allocate memory."); + OsaFree(buf); + return -1; + } + uint8_t* tmp_buf = buf; + + // po_info + memcpy(tmp_buf, &po->po_file.po_info, sizeof(TEE_ObjectInfo)); + tmp_buf += sizeof(TEE_ObjectInfo); + // attr + memcpy(tmp_buf, (void*)po->po_file.attr, po->po_file.attr_size); + tmp_buf += po->po_file.attr_size; + // object data + memcpy(tmp_buf, (void*)po->po_file.object_data, po->po_file.obj_data_size); + int ret = ss_write(buf, buf_size, 0, po->po_file.file_name, &po->po_file.cred, + SS_OPT_DEFAULT); + if (SS_RET_SUCCESS != ret) { + MSG("Failed to write data to securestorage, ret = %d.", ret); + OsaFree(buf); + return -1; + } + OsaFree(buf); + return 0; +} + +int rename_po_file(persistent_object* po, const void* newObjectID, + size_t newObjectIDLen) { + // first delete old file + if (-1 == delete_po_file(po)) { + MSG("Failed to delete old po file."); + return -1; + } + derive_po_file_name(newObjectID, newObjectIDLen, po->po_file.file_name); + if (0 != write_po_file(po)) { + MSG("Failed to write po file."); + return -1; + } + write_po_info(&g_po_info_file, newObjectID, newObjectIDLen, &po->attr.info); + return 0; +} + +void clean_po_file(persistent_object* po) { + if (!po) { + return; + } + __FREE(po->po_file.attr); + __FREE(po->po_file.object_data); +} + +int delete_po_file(persistent_object* po) { + int ret = ss_delete(po->po_file.file_name, &po->po_file.cred, SS_OPT_DEFAULT); + if (SS_RET_SUCCESS != ret) { + MSG("Failed to delete data from secure storage. ret = %d.", ret); + return -1; + } + ret = delete_po_info(&g_po_info_file, po->object_id, po->obj_id_len); + if (-1 == ret) { + MSG("Failed to delete po info."); + return -1; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////// +// misc operations +//////////////////////////////////////////////////////////////////////////////////// +po_info_file g_po_info_file; + +int init_po_info_file(po_info_file* pi_file) { + if (pi_file->b_inited) { + return 0; + } + TEE_UUID tmp_uuid; + if (0 != get_uuid()) { + MSG("Failed to get UUID of TA."); + return -1; + } + tmp_uuid = this_uuid; + char uuid[64] = {0}; + convert_TA_UUID(uuid, tmp_uuid); + ss_set_credential(&pi_file->cred, uuid, PO_INTERNAL_MODULE_NAME, 1, 0); + uint32_t fn_sz = strlen(PI_FILE_NAME); + memcpy(pi_file->filename, PI_FILE_NAME, fn_sz); + pi_file->filename[fn_sz] = '\0'; + pi_file->b_inited = 1; + return 0; +} + +int load_po_info_file(po_info_file* pi_file) { + if (init_po_info_file(pi_file)) { + return -1; + } + uint8_t* ret_buf = NULL; + uint32_t read_sz = 0; + int ret = ss_read(&ret_buf, &read_sz, 0, pi_file->filename, &pi_file->cred, + SS_OPT_DEFAULT); + if (SS_RET_CANT_FIND_REQUESTED_DATA == ret) { + pi_file->po_num = 0; + return 0; + } + if (SS_RET_SUCCESS != ret) { + MSG("Failed to read from secure storage, ret = %d.", ret); + return -1; + } + if (0 == read_sz) { + pi_file->po_num = 0; + return 0; + } + uint32_t po_info_sz = sizeof(persistent_object_info); + if (read_sz % po_info_sz) { + MSG("po_info file data error."); + ss_free_buffer(ret_buf); + return -1; + } + pi_file->po_num = read_sz / po_info_sz; + pi_file->po_info = (persistent_object_info*)ret_buf; + return 0; +} + +int get_po_info(po_info_file* pi_file, persistent_object_info** po_info, + int* po_num) { + if (-1 == load_po_info_file(pi_file)) { + return -1; + } + if (0 == pi_file->po_num) { + *po_num = 0; + return 0; + } + persistent_object_info* tmp_info = NULL; + tmp_info = (persistent_object_info*)OsaMalloc( + pi_file->po_num * sizeof(persistent_object_info)); + if (NULL == tmp_info) { + MSG("Failed to alloc memory."); + __FREE(pi_file->po_info); + return -1; + } + int32_t i = 0; + persistent_object_info* tmp_po_info = pi_file->po_info; + for (; i < pi_file->po_num; ++i) { + tmp_info[i] = *tmp_po_info; + tmp_po_info++; + } + *po_num = pi_file->po_num; + *po_info = tmp_info; + __FREE(pi_file->po_info); + return 0; +} + +int write_po_info(po_info_file* pi_file, const void* objectID, + uint32_t obj_id_len, TEE_ObjectInfo* info) { + if (-1 == load_po_info_file(pi_file)) { + return -1; + } + persistent_object_info po_info; + memcpy((void*)po_info.object_id, objectID, obj_id_len); + po_info.obj_id_len = obj_id_len; + po_info.info = *info; + persistent_object_info* po_infos = NULL; + uint32_t po_info_sz = sizeof(persistent_object_info); + po_infos = (persistent_object_info*)OsaMalloc( + (pi_file->po_num + 1) * po_info_sz); + uint32_t po_num = pi_file->po_num; + + memcpy((void*)po_infos, (void*)pi_file->po_info, po_num * po_info_sz); + memcpy((uint8_t*)po_infos + po_num * po_info_sz, (void*)&po_info, po_info_sz); + + pi_file->po_num += 1; + __FREE(pi_file->po_info); + int ret = ss_write((uint8_t*)po_infos, po_info_sz * pi_file->po_num, 0, + pi_file->filename, &pi_file->cred, SS_OPT_DEFAULT); + if (SS_RET_SUCCESS != ret) { + MSG("Failed to write po stat to secure storage,ret = %d.", ret); + __FREE(po_infos); + return -1; + } + __FREE(po_infos); + return 0; +} + +int delete_po_info(po_info_file* pi_file, const void* objectID, + uint32_t obj_id_len) { + persistent_object_info* po_del = NULL; + + if (-1 == load_po_info_file(pi_file)) { + return -1; + } + uint32_t po_info_sz = sizeof(persistent_object_info); + po_del = find_po_info(pi_file, objectID, obj_id_len); + if (NULL == po_del) { + MSG("po info to del not found."); + return 0; + } + uint8_t* po_del_pos = (uint8_t*)po_del; + uint8_t* cp_begin = po_del_pos + po_info_sz; + uint32_t cp_sz = po_info_sz * pi_file->po_num + - (cp_begin - (uint8_t*)pi_file->po_info); + + memcpy(po_del_pos, cp_begin, cp_sz); + pi_file->po_num--; + int ret = ss_write((uint8_t*)pi_file->po_info, po_info_sz * pi_file->po_num, + 0, pi_file->filename, &pi_file->cred, SS_OPT_DEFAULT); + if (SS_RET_SUCCESS != ret) { + MSG("Failed to write po stat to secure storage,ret = %d.", ret); + __FREE(pi_file->po_info); + return -1; + } + __FREE(pi_file->po_info); + return 0; +} + +persistent_object_info* find_po_info(po_info_file* pi_file, + const void* objectID, uint32_t obj_id_len) { + if (NULL == objectID || 0 == obj_id_len) { + MSG("objectID is invalid."); + return NULL; + } + int32_t i = 0; + int b_find = 0; + persistent_object_info* po_info_tmp = pi_file->po_info; + for (; i < pi_file->po_num; ++i) { + if (0 == memcmp(po_info_tmp->object_id, objectID, obj_id_len)) { + b_find = 1; + break; + } + po_info_tmp++; + } + return (b_find ? po_info_tmp : NULL); +} + +// po share rule +// TODO: locking mechanism to be improved using pthread locks ORr +// As ssflib is shared lib, instead of malloc'ing the share_info, +// just use a global variable, there by no need of locking +void lock_po_share_info(po_share_info* share_info) { + while (share_info->usr_info->lock) { + } + share_info->usr_info->lock = 1; +} + +void unlock_po_share_info(po_share_info* share_info) { + if (share_info->usr_info->lock) { + share_info->usr_info->lock = 0; + } +} + +int init_share_info(po_share_info* share_info) { + if (NULL != share_info->usr_info) { + MSG("Share info has been inited."); + return 0; + } + // is the shm exist + share_info->usr_info = (po_user*)OsaMalloc(sizeof(po_user)); + memset(share_info->usr_info, 0, sizeof(po_user)); +#if 0 + int b_shm_exist = 1; + if (0 > shm_open(share_info->name, O_EXCL | O_CREAT, 0666)) + { + b_shm_exist = 1; + } + share_info->fd = shm_open(share_info->name, O_RDWR | O_CREAT, 0666); + if (0 > share_info->fd) + { + MSG("Failed to open shm %s.", share_info->name); + return -1; + } + // linux posix shm need this + if (!b_shm_exist) + { + ftruncate(share_info->fd, sizeof(po_user)); + } + share_info->usr_info = (po_user*) mmap(NULL, sizeof(po_user), + PROT_READ | PROT_WRITE, MAP_SHARED, share_info->fd, 0); + if (share_info->usr_info == (void *) 0xFFFFFFFF) + { + MSG("Failed to mmap shm."); + return -1; + } + if (!b_shm_exist) + { + share_info->usr_info->lock = 0; + memset(share_info->usr_info, 0, sizeof(po_user)); + } +#endif + return 0; +} + +int check_share_rule(po_share_info* share_info, uint32_t handleFlags) { + if ((NULL == share_info) || (-1 == init_share_info(share_info))) { + return -1; + } + int ret = 0; + // no user + if ((0 == share_info->usr_info->x_user) + && (0 == share_info->usr_info->rs_user) + && (0 == share_info->usr_info->ws_user) + && (0 == share_info->usr_info->rws_user)) { + goto out; + } + if (handleFlags & TEE_DATA_FLAG_ACCESS_READ) { + if (!((handleFlags & TEE_DATA_FLAG_SHARE_READ) + && (0 == share_info->usr_info->x_user) + && (0 == share_info->usr_info->ws_user))) { + ret = -1; + goto out; + } + } + if (handleFlags & TEE_DATA_FLAG_ACCESS_WRITE) { + if (!((handleFlags & TEE_DATA_FLAG_SHARE_WRITE) + && (0 == share_info->usr_info->x_user) + && (0 == share_info->usr_info->rs_user))) { + ret = -1; + goto out; + } + } + if (handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META) { + if (!((0 == share_info->usr_info->x_user) + && (0 == share_info->usr_info->rs_user) + && (0 == share_info->usr_info->ws_user) + && (0 == share_info->usr_info->rws_user))) { + ret = -1; + } + } + out: return ret; +} + +int update_share_info(po_share_info* share_info, uint32_t handleFlags, + int b_open) { + if (NULL == share_info->usr_info) { + if (-1 == init_share_info(share_info)) { + return -1; + } + } + // lock + // TODO: Commented for debugging, to be uncommented + lock_po_share_info(share_info); + int ret = 0; + if (b_open) { + if (check_share_rule(share_info, handleFlags)) { + MSG("Access conflict!"); + ret = 1; + goto out; + } + } + handleFlags &= ~TEE_DATA_FLAG_ACCESS_READ; + handleFlags &= ~TEE_DATA_FLAG_ACCESS_WRITE; + handleFlags &= ~TEE_HANDLE_FLAG_PERSISTENT; + handleFlags &= ~TEE_HANDLE_FLAG_INITIALIZED; + + if ((handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META) + || (handleFlags & TEE_DATA_FLAG_EXCLUSIVE) || (0 == handleFlags)) { + b_open ? share_info->usr_info->x_user++ : share_info->usr_info->x_user--; + goto out; + } + if ((handleFlags & TEE_DATA_FLAG_SHARE_READ) + && (handleFlags & TEE_DATA_FLAG_SHARE_WRITE)) { + b_open ? share_info->usr_info->rws_user++ : + share_info->usr_info->rws_user--; + goto out; + } + if (handleFlags & TEE_DATA_FLAG_SHARE_READ) { + b_open ? share_info->usr_info->rs_user++ : share_info->usr_info->rs_user--; + goto out; + } + if (handleFlags & TEE_DATA_FLAG_SHARE_WRITE) { + b_open ? share_info->usr_info->ws_user++ : share_info->usr_info->ws_user--; + goto out; + } + out: + + if ((0 == share_info->usr_info->x_user) + && (0 == share_info->usr_info->rs_user) + && (0 == share_info->usr_info->ws_user) + && (0 == share_info->usr_info->rws_user)) { + release_share_info(share_info); + } + unlock_po_share_info(share_info); + return ret; +} + +int release_share_info(po_share_info* share_info) { +#if 0 + if ((NULL == share_info) || (0 > share_info->fd)) + { + MSG("Share info has been inited."); + return 0; + } + shm_unlink(share_info->name); +#endif + OsaFree(share_info->usr_info); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////////// +// misc operations +//////////////////////////////////////////////////////////////////////////////////// +void byte_to_hex(uint8_t* dest, const uint8_t* src, unsigned long src_len) { + char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f'}; + + unsigned long j; + for (j = 0; j < src_len; j++) { + dest[j * 2] = hexval[((src[j] >> 4) & 0xF)]; + dest[(j * 2) + 1] = hexval[(src[j]) & 0x0F]; + } +} + +void convert_TA_UUID(char* uuid, TEE_UUID TA_UUID) { + // In its canonical form, a UUID consists of 32 hexadecimal digits, displayed in 5 groups separated by hyphens, + // in the form 8-4-4-4-12 for a total of 36 characters(32 digits and 4 '-'). For example: + // 550e8400-e29b-41d4-a716-446655440000 + // Version 4 UUIDs use a scheme relying only on random numbers. This algorithm sets the version number as well + // as two reserved bits. All other bits are set using a random or pseudorandom data source. + // Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal digits x and hexadecimal + // digits 8, 9, A, or B for y. e.g. f47ac10b-58cc-4372-a567-0e02b2c3d479. + + char* tmp = uuid; + + snprintf(tmp, 9, "%08x", TA_UUID.timeLow); + tmp[8] = '-'; + tmp += 9; + snprintf(tmp, 5, "%04x", TA_UUID.timeMid); + tmp[4] = '-'; + tmp += 5; + snprintf(tmp, 5, "%04x", TA_UUID.timeHiAndVersion); + tmp[4] = '-'; + tmp += 5; + uint32_t i = 0; + for (; i < 2; ++i) { + snprintf(tmp, 3,"%02x", TA_UUID.clockSeqAndNode[i]); + tmp += 2; + } + tmp[0] = '-'; + + tmp += 1; + for (; i < 8; ++i) { + snprintf(tmp, 3, "%02x", TA_UUID.clockSeqAndNode[i]); + tmp += 2; + } + MSG("this_uuid : %s ", uuid); +} + +int gen_random(uint8_t* dest, uint8_t data_len) { + UCI_HANDLE uh = UCI_ERROR; + uh = uci_context_alloc(ID_UCI_X931, UCI_SW_CRYPTOCORE); + if (uh == UCI_ERROR || uh == UCI_MEM_ALLOR_ERROR) { + return -1; + } + unsigned char seed[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + int ret = uci_prng_seed(uh, seed); + if (ret != UCI_SUCCESS) { + goto out; + } + ret = uci_prng_get(uh, data_len * 8, dest); + if (ret != UCI_SUCCESS) { + goto out; + } + out: uci_context_free(uh); + return ret; +} + +// persistent object list operations +po_list_node g_po_list = {NULL, NULL, NULL}; + +void debug_list() { + po_list_node* node = g_po_list.next; + while (node != NULL) { + MSG("PO [%s] ==>", node->po->po_file.file_name); + node = node->next; + } +} + +void add_to_po_list(persistent_object* po) { + if (NULL == po) { + return; + } + po->po_list.po = po; + // first po + if (NULL == g_po_list.next) { + g_po_list.next = &po->po_list; + po->po_list.prev = &g_po_list; + po->po_list.next = NULL; + } else { + g_po_list.next->prev = &po->po_list; + po->po_list.next = g_po_list.next; + po->po_list.prev = &g_po_list; + g_po_list.next = &po->po_list; + } + MSG("=====PO %s added=====", po->po_file.file_name); + //debug_list(); +} + +void rem_from_po_list(persistent_object* po) { + if (NULL == po) { + return; + } + MSG("=====To remove PO %s=====", po->po_file.file_name); + //debug_list(); + if (po->po_list.prev) { + po->po_list.prev->next = po->po_list.next; + } + if (po->po_list.next) { + po->po_list.next->prev = po->po_list.prev; + } + MSG("======PO removed====="); + //debug_list(); +} + +void cleanup(void) { + po_list_node* node = g_po_list.next; + while (NULL != node) { + TEE_CloseObject((TEE_ObjectHandle)node->po); + node = node->next; + } +} + +void regist_clean_up() { + static int b_reg = 0; + if (b_reg) { + return; + } + if (0 == atexit(cleanup)) { + b_reg = 1; + } +} + +//////////////////////////////////////////////////////////////////////////////////// +// object general operations +//////////////////////////////////////////////////////////////////////////////////// +void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo* objectInfo) { + if (objectInfo) { + objectInfo->objectType = object->tr.info.objectType; + objectInfo->objectSize = object->tr.info.objectSize; + objectInfo->maxObjectSize = object->tr.info.maxObjectSize; + objectInfo->objectUsage = object->tr.info.objectUsage; + objectInfo->dataSize = object->tr.info.dataSize; + objectInfo->dataPosition = object->tr.info.dataPosition; + objectInfo->handleFlags = object->tr.info.handleFlags; + } +} + +// usage ?? +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage) { + object->tr.info.objectUsage &= objectUsage; +} + +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, void* buffer, size_t* size) { + uint32_t len; + int i, n = -1; + TransientObject * obj = &object->tr; + + if (!(obj->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + // search for attributeID in attr_array + for (i = 0; i < obj->attr.attr_number; i++) { + if (obj->attr.attr_array[i].attributeID == attributeID) { + n = i; + break; + } + } + if (n == -1) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + // bit[29] == 1 -> not a buffer attribute + if (attributeID & TEE_ATTR_FLAG_VALUE) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + // protected attribute + if (!(attributeID & TEE_ATTR_FLAG_PUBLIC) + && !(obj->info.objectUsage & TEE_USAGE_EXTRACTABLE)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + //len = ((obj->attr.attr_array[n].content.ref.length & 0x7FFFFFFF) + 7) >> 3 ; + len = (obj->attr.attr_array[n].content.ref.length + 7) >> 3; + + // out buffer is too small + if (len > *size) { + return TEE_ERROR_SHORT_BUFFER; + } + memcpy(buffer, obj->attr.attr_array[n].content.ref.buffer, len); + *size = len; + return TEE_SUCCESS; +} + +TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, + uint32_t attributeID, uint32_t* a, uint32_t* b) { + int i, n = -1; + TransientObject * obj = &object->tr; + + if (!(obj->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + // search for attributeID in attr_array + for (i = 0; i < obj->attr.attr_number; i++) { + if (obj->attr.attr_array[i].attributeID == attributeID) { + n = i; + break; + } + } + if (n == -1) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + // bit[29] == 0 -> not a value attribute + if (!(attributeID & TEE_ATTR_FLAG_VALUE)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + // protected attribute + if (!(attributeID & TEE_ATTR_FLAG_PUBLIC) + && !(obj->info.objectUsage & TEE_USAGE_EXTRACTABLE)) { + return TEE_ERROR_ACCESS_DENIED; + } + if (a) { + *a = obj->attr.attr_array[i].content.value.a; + } + if (b) { + *b = obj->attr.attr_array[i].content.value.b; + } + return TEE_SUCCESS; +} + +void TEE_CloseObject(TEE_ObjectHandle object) { + if (object == TEE_HANDLE_NULL) { + return; + } + if (object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) // persistent object + { + persistent_object *po = (persistent_object*)object; + close_po(po); + } else { + TEE_FreeTransientObject(object); + } +} + +//////////////////////////////////////////////////////////////////////////////////// +// Transient Object operations +//////////////////////////////////////////////////////////////////////////////////// +TEE_Result TEE_AllocateTransientObject(uint32_t objectType, + uint32_t maxObjectSize, TEE_ObjectHandle* object) { + TEE_Result rc; + + + TransientObject * tr = (TransientObject*)OsaMalloc(sizeof(TransientObject)); + if (!tr) { + OsaFree(tr); + return TEE_ERROR_OUT_OF_MEMORY; + } + memset(tr, 0, sizeof(TransientObject)); + rc = allocate_transient_object(tr, objectType, maxObjectSize); + if (rc != TEE_SUCCESS) { + OsaFree(tr); + return rc; + } + *object = (TEE_ObjectHandle)&tr->info; + OsaFree(tr); + return TEE_SUCCESS; +} + +void TEE_FreeTransientObject(TEE_ObjectHandle object) { + TransientObject * tr = NULL; + + if (object == TEE_HANDLE_NULL) { + return; + } + tr = &object->tr; + TEE_Attribute* attrs = tr->attr.attr_array; + int i; + for (i = 0; i < tr->attr.attr_number; ++i) { + free_attribute(&attrs[i]); + } + memset(&tr->attr, 0, sizeof(tr->attr)); + OsaFree(tr); +} + +void TEE_ResetTransientObject(TEE_ObjectHandle object) { + TransientObject* tr; + + if (object == TEE_HANDLE_NULL) { + return; + } + tr = &object->tr; + TEE_Attribute* attrs = tr->attr.attr_array; + int i; + for (i = 0; i < tr->attr.attr_number; ++i) { + free_attribute(&attrs[i]); + } + memset(tr->attr.attr_array, 0, sizeof(tr->attr.attr_array)); + tr->attr.attr_number = 0; + + tr->info.objectSize = 0; + tr->info.dataSize = 0; + tr->info.dataPosition = 0; + tr->info.handleFlags = 0; + tr->info.objectUsage = 0xffffffff; +} + +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + const TEE_Attribute* attrs, uint32_t attrCount) { + unsigned int i; + + TransientObject* tr = &object->tr; + if (tr->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + TEE_Attribute* curr_attr = &tr->attr.attr_array[tr->attr.attr_number]; + for (i = 0; i < attrCount; i++) { + + if (attrs[i].content.ref.length > tr->info.maxObjectSize) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + copy_attribute(&curr_attr[i], (TEE_Attribute*)&attrs[i]); + tr->attr.attr_number++; + tr->info.objectSize = + tr->info.objectSize > attrs[i].content.ref.length ? + tr->info.objectSize : attrs[i].content.ref.length; + } + + switch (tr->info.objectType) { + case TEE_TYPE_AES: + case TEE_TYPE_DES: + case TEE_TYPE_DES3: + case TEE_TYPE_HMAC_MD5: + case TEE_TYPE_HMAC_SHA1: + case TEE_TYPE_HMAC_SHA224: + case TEE_TYPE_HMAC_SHA256: + case TEE_TYPE_HMAC_SHA384: + case TEE_TYPE_HMAC_SHA512: + case TEE_TYPE_GENERIC_SECRET: + if (tr->attr.attr_number != 1) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + break; + case TEE_TYPE_RSA_PUBLIC_KEY: + case TEE_TYPE_RSA_KEYPAIR: { + // Krishna: Incorrect to check this condition + /*if ((tr->info.objectType == TEE_TYPE_RSA_KEYPAIR) + && (tr->attr.attr_number != 3) && (tr->attr.attr_number != 8)) { + TZ_ERROR("tr->attr.attr_number = %d\n", tr->attr.attr_number); + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + }*/ + if ((tr->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY) + && (tr->attr.attr_number != 2)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + } + break; + case TEE_TYPE_DSA_PUBLIC_KEY: + case TEE_TYPE_DSA_KEYPAIR: { + if ((tr->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY) + && (tr->attr.attr_number != 4)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } else if ((tr->info.objectType == TEE_TYPE_DSA_KEYPAIR) + && (tr->attr.attr_number != 5)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + } + break; + case TEE_TYPE_DH_KEYPAIR: { + if ((tr->attr.attr_number != 3) && (tr->attr.attr_number != 4)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + } + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + tr->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + return TEE_SUCCESS; +} + +void TEE_InitRefAttribute(TEE_Attribute* attr, uint32_t attributeID, + const void* buffer, size_t length) { + attr->attributeID = attributeID; + attr->content.ref.buffer = buffer; + attr->content.ref.length = length; +} + +void TEE_InitValueAttribute(TEE_Attribute* attr, uint32_t attributeID, + uint32_t a, uint32_t b) { + attr->attributeID = attributeID; + attr->content.value.a = a; + attr->content.value.b = b; +} + +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject) { + int attrCount, i; + //int offset = 0; + TEE_Attribute * attrs; + + TransientObject* src = &srcObject->tr; + TransientObject* dest = &destObject->tr; + + if (dest->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + dest->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + if (!(src->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + // check compatibility of source & destination + if (!((src->info.objectType == dest->info.objectType) + || ((dest->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY) + && (src->info.objectType == TEE_TYPE_RSA_KEYPAIR)) + || ((dest->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY) + && (src->info.objectType == TEE_TYPE_DSA_KEYPAIR)))) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (src->info.objectSize > dest->info.maxObjectSize) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + dest->info.objectUsage &= src->info.objectUsage; + // copy attributes + attrs = src->attr.attr_array; + attrCount = src->attr.attr_number; + //offset = 0; + for (i = 0; i < attrCount; i++) { + copy_attribute(&dest->attr.attr_array[i], &attrs[i]); + dest->attr.attr_number++; + } +} + +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + const TEE_Attribute* params, uint32_t paramCount) { + char key[256]; + TEE_Attribute attrs[MAX_ATTRIBUTE_NUMBER]; + unsigned int i, check = 0; + TransientObject* tr = &object->tr; + + if (tr->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (keySize > tr->info.maxObjectSize) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + tr->info.objectSize = keySize; + switch (tr->info.objectType) { + case TEE_TYPE_AES: + case TEE_TYPE_DES: + case TEE_TYPE_DES3: + case TEE_TYPE_HMAC_MD5: + case TEE_TYPE_HMAC_SHA1: + case TEE_TYPE_HMAC_SHA224: + case TEE_TYPE_HMAC_SHA256: + case TEE_TYPE_HMAC_SHA384: + case TEE_TYPE_HMAC_SHA512: + case TEE_TYPE_GENERIC_SECRET: + // generate 1 random key + gen_random((unsigned char*)key, (keySize + 7) / 8); + TEE_InitRefAttribute(&attrs[0], TEE_ATTR_SECRET_VALUE, key, keySize); + TEE_PopulateTransientObject(object, attrs, 1); + break; + case TEE_TYPE_RSA_KEYPAIR: { + uci_key_s uci_key; + int key_size = (keySize + 7) / 8; + uci_key.ucik_rsa_n = (unsigned char*)OsaMalloc(key_size); + uci_key.ucik_rsa_n_len = key_size; + uci_key.ucik_rsa_e = (unsigned char*)OsaMalloc(key_size); + uci_key.ucik_rsa_e_len = key_size; + uci_key.ucik_rsa_d = (unsigned char*)OsaMalloc(key_size); + uci_key.ucik_rsa_d_len = key_size; + uci_param_s up; + up.ucip_rsa_flag = RSA_GENKEYWITHNON; + up.ucip_rsa_padding = ID_UCI_RSAES_PKCS15; + //alg + int alg = ID_UCI_RSA; + if (512 == keySize) { + alg = ID_UCI_RSA512; + } else if (1024 == keySize) { + alg = ID_UCI_RSA1024; + } else if (2048 == keySize) { + alg = ID_UCI_RSA2048; + } else if (3072 == keySize) { + alg = ID_UCI_RSA3072; + } + UCI_HANDLE uh = uci_context_alloc(alg, UCI_SW); + uci_ae_gen_keypair(uh, &uci_key, &up); + uci_context_free(uh); + + TEE_InitRefAttribute(&attrs[0], TEE_ATTR_RSA_MODULUS, uci_key.ucik_rsa_n, + keySize); + TEE_InitRefAttribute(&attrs[1], TEE_ATTR_RSA_PUBLIC_EXPONENT, + uci_key.ucik_rsa_e, keySize); + TEE_InitRefAttribute(&attrs[2], TEE_ATTR_RSA_PRIVATE_EXPONENT, + uci_key.ucik_rsa_d, keySize); + TEE_PopulateTransientObject(object, attrs, 3); + + OsaFree(uci_key.ucik_rsa_n); + OsaFree(uci_key.ucik_rsa_e); + OsaFree(uci_key.ucik_rsa_d); + } + break; + + case TEE_TYPE_DSA_KEYPAIR: { + uci_key_s uci_key; + int key_size = (keySize + 7) / 8; + uci_key.ucik_dsa_pubk_len = key_size; + uci_key.ucik_dsa_pubkey = (unsigned char*)OsaMalloc(key_size); + uci_key.ucik_dsa_privk_len = key_size; + uci_key.ucik_dsa_privkey = (unsigned char*)OsaMalloc(key_size); + uci_param_s up; + up.ucip_dsa_tsize = 0; + + // check the mandatory attributes + for (i = 0; i < paramCount; i++) { + if (params[i].attributeID == TEE_ATTR_DSA_PRIME) { + up.ucip_dsa_p = (unsigned char*)params[i].content.ref.buffer; + up.ucip_dsa_p_len = (params[i].content.ref.length + 7) / 8; + check |= 0x01; + } else if (params[i].attributeID == TEE_ATTR_DSA_BASE) { + up.ucip_dsa_g = (unsigned char*)params[i].content.ref.buffer; + up.ucip_dsa_g_len = (params[i].content.ref.length + 7) / 8; + check |= 0x02; + } else if (params[i].attributeID == TEE_ATTR_DSA_SUBPRIME) { + up.ucip_dsa_q = (unsigned char*)params[i].content.ref.buffer; + up.ucip_dsa_q_len = (params[i].content.ref.length + 7) / 8; + check |= 0x04; + } + } + if (check != 0x07) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + // generate public & private keys. algorithm is the same as for DH + UCI_HANDLE handle = uci_context_alloc(ID_UCI_DSA, UCI_SW); + uci_ae_gen_keypair(handle, &uci_key, &up); + uci_context_free(handle); + for (i = 0; i < paramCount; i++) { + TEE_InitRefAttribute(&attrs[i], params[i].attributeID, + params[i].content.ref.buffer, params[i].content.ref.length); + } + TEE_InitRefAttribute(&attrs[3], TEE_ATTR_DSA_PUBLIC_VALUE, + uci_key.ucik_dsa_pubkey, uci_key.ucik_dsa_pubk_len * 8); + TEE_InitRefAttribute(&attrs[4], TEE_ATTR_DSA_PRIVATE_VALUE, + uci_key.ucik_dsa_privkey, uci_key.ucik_dsa_privk_len * 8); + TEE_PopulateTransientObject(object, attrs, 5); + OsaFree(uci_key.ucik_dsa_pubkey); + OsaFree(uci_key.ucik_dsa_privkey); + } + break; + + case TEE_TYPE_DH_KEYPAIR: { + int key_size = (keySize + 7) / 8; + uint8_t* privKey = (unsigned char*)OsaMalloc(key_size); + uint8_t* pubKey = (unsigned char*)OsaMalloc(key_size); + uci_param_s uciparam; + + for (i = 0; i < paramCount; i++) { + if (params[i].attributeID == TEE_ATTR_DH_PRIME) { + check |= 0x01; + uciparam.ucip_dh_prime = (unsigned char*)params[i].content.ref.buffer; + uciparam.ucip_dh_len = (params[i].content.ref.length + 7) / 8; + } else if (params[i].attributeID == TEE_ATTR_DH_BASE) { + check |= 0x02; + uciparam.ucip_dh_generator = (unsigned char*)params[i].content.ref + .buffer; + } + } + if (check != 0x03) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + UCI_HANDLE handle = uci_context_alloc(ID_UCI_DH, UCI_SW); + uci_dh_gen_phasekey(handle, privKey, pubKey, &uciparam); + uci_context_free(handle); + for (i = 0; i < paramCount; i++) { + TEE_InitRefAttribute(&attrs[i], params[i].attributeID, + params[i].content.ref.buffer, params[i].content.ref.length); + } + TEE_InitRefAttribute(&attrs[2], TEE_ATTR_DH_PRIVATE_VALUE, privKey, + keySize); + TEE_InitRefAttribute(&attrs[3], TEE_ATTR_DH_PUBLIC_VALUE, pubKey, + keySize); + TEE_PopulateTransientObject(object, attrs, 4); + + OsaFree(privKey); + OsaFree(pubKey); + } + break; + } + return TEE_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////////// +// Persistent object operations +//////////////////////////////////////////////////////////////////////////////////// + +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, const void* objectID, + size_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, + const void* initialData, size_t initialDataLen, TEE_ObjectHandle* object) { + persistent_object* po = NULL; + TEE_Result rc = allocate_persistent_object(&po, storageID, objectID, + objectIDLen, flags); + TransientObject* tr_obj = NULL; + if (TEE_HANDLE_NULL != attributes) { + tr_obj = &attributes->tr; + } + rc = exist_po(po); + // already exist + if (TEE_SUCCESS == rc) { + if (flags & TEE_DATA_FLAG_EXCLUSIVE) { + MSG("Persistent object already exist."); + FREE_PO(po); + return TEE_ERROR_ACCESS_CONFLICT; + } + if (!object) { + FREE_PO(po); + return TEE_SUCCESS; + } + rc = open_po(po); + } else { + rc = create_po(po, tr_obj, initialData, initialDataLen); + } + if (rc) { + FREE_PO(po); + return rc; + } + if (object) { + *object = (TEE_ObjectHandle)&po->attr.info; + } else { + close_po(po); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void* objectID, + size_t objectIDLen, uint32_t flags, TEE_ObjectHandle* object) { + persistent_object* po = NULL; + TEE_Result rc = allocate_persistent_object(&po, storageID, objectID, + objectIDLen, flags); + if (rc) { + return rc; + } + rc = open_po(po); + if (rc) { + FREE_PO(po); + return rc; + } + *object = (TEE_ObjectHandle)&po->attr.info; + return TEE_SUCCESS; +} + +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object) { + persistent_object* op; + if (object == TEE_HANDLE_NULL) { + return; + } + if (!(object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + op = (persistent_object*)object; + if (!(op->attr.info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + free_po(op); +} + +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void* newObjectID, size_t newObjectIDLen) { + if (object == TEE_HANDLE_NULL) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + // transient object + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + persistent_object* po; + po = (persistent_object*)object; + if (!(po->attr.info.handleFlags & TEE_DATA_FLAG_EXCLUSIVE)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(po->attr.info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (newObjectIDLen > TEE_OBJECT_ID_MAX_LEN) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + return rename_po(po, newObjectID, newObjectIDLen); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Persistent enumerator operations +//////////////////////////////////////////////////////////////////////////////////// +TEE_Result TEE_AllocatePersistentObjectEnumerator( + TEE_ObjectEnumHandle* objectEnumerator) { + struct __TEE_ObjectEnumHandle* eh; + eh = (__TEE_ObjectEnumHandle *)OsaMalloc( + sizeof(struct __TEE_ObjectEnumHandle)); + if (!eh) { + return TEE_ERROR_OUT_OF_MEMORY; + } + eh->po_info = NULL; + eh->po_num = 0; + eh->curr_position = 0; + eh->state = ENUM_STATE_INIT; + + *objectEnumerator = eh; + return TEE_SUCCESS; +} + +void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) { + if (TEE_HANDLE_NULL == objectEnumerator) { + return; + } + __FREE(objectEnumerator->po_info); + __FREE(objectEnumerator); +} + +void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) { + if (TEE_HANDLE_NULL == objectEnumerator) { + return; + } + objectEnumerator->curr_position = 0; + objectEnumerator->po_num = 0; + objectEnumerator->state = ENUM_STATE_INIT; + __FREE(objectEnumerator->po_info); + objectEnumerator->po_info = NULL; +} + +TEE_Result TEE_StartPersistentObjectEnumerator( + TEE_ObjectEnumHandle objectEnumerator, uint32_t storageID) { + if (TEE_HANDLE_NULL == objectEnumerator) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (storageID != TEE_STORAGE_PRIVATE) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + TEE_UUID uuid; + if (0 != get_uuid()) { + MSG("Failed to get UUID of TA."); + return -1; + } + uuid = this_uuid; + + if (objectEnumerator->state == ENUM_STATE_STARTED) { + TEE_ResetPersistentObjectEnumerator(objectEnumerator); + } + int ret = get_po_info(&g_po_info_file, &objectEnumerator->po_info, + &objectEnumerator->po_num); + if (ret || !objectEnumerator->po_num) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + objectEnumerator->state = ENUM_STATE_STARTED; + return TEE_SUCCESS; +} + +TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + TEE_ObjectInfo* objectInfo, void* objectID, size_t* objectIDLen) { + if (TEE_HANDLE_NULL == objectEnumerator) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if ((objectEnumerator->state != ENUM_STATE_STARTED) + || (objectEnumerator->state == ENUM_STATE_END)) { + return TEE_ERROR_ITEM_NOT_FOUND; + } + persistent_object_info* po_info = objectEnumerator->po_info; + int curr_pos = objectEnumerator->curr_position; + *objectInfo = po_info[curr_pos].info; + *objectIDLen = po_info[curr_pos].obj_id_len; + memcpy(objectID, po_info[curr_pos].object_id, po_info[curr_pos].obj_id_len); + + objectEnumerator->curr_position++; + if (objectEnumerator->curr_position >= objectEnumerator->po_num) { + objectEnumerator->state = ENUM_STATE_END; + } + return TEE_SUCCESS; +} + +//////////////////////////////////////////////////////////////////////////////////// +// Data stream access operations +//////////////////////////////////////////////////////////////////////////////////// + +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void* buffer, + size_t size, uint32_t* count) { + int num; + if (object == TEE_HANDLE_NULL) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + persistent_object* po = (persistent_object*)object; + if (!(po->attr.info.handleFlags & TEE_DATA_FLAG_ACCESS_READ)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (size == 0) { + num = 0; + } else { + TEE_Result rc = read_object_data(po, buffer, size, (uint32_t*)&num); + if (rc) { + return rc; + } + } + *count = num; + + MSG("Data read is:"); + printhex((unsigned char*)buffer, num); + return TEE_SUCCESS; +} + +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, const void* buffer, + size_t size) { + if (object == TEE_HANDLE_NULL) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + persistent_object* po = (persistent_object*)object; + if (!(po->attr.info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (size != 0) { + return write_object_data(po, buffer, size); + } + return TEE_SUCCESS; +} + +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size) { + if (object == TEE_HANDLE_NULL) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + persistent_object* po = (persistent_object*)object; + if (!(po->attr.info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + return truncate_object_data(po, size); +} + +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, + TEE_Whence whence) { + if (object == TEE_HANDLE_NULL) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + if (!(object->tr.info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + TZ_ERROR("operation error line = %d,%s\n", __LINE__, __func__); + TEE_Panic(0); + } + persistent_object* po = (persistent_object*)object; + return seek_object_data(po, offset, whence); +} diff --git a/ssflib/src/ssf_taentrypoint.c b/ssflib/src/ssf_taentrypoint.c new file mode 100755 index 0000000..c4695bc --- /dev/null +++ b/ssflib/src/ssf_taentrypoint.c @@ -0,0 +1,118 @@ +/* + * ===================================================================================== + * + * Filename: ssf_taentrypoint.c + * + * Description: SSF TA Internal functions + * + * Version: 1.0 + * Created: 20 April 2015 12:41:39 IST + * Revision: Original + * Compiler: gcc + * + * Author: krishna (Kr), k.devale@samsung.com + * Organization: Samsung Electronics + * + * ===================================================================================== + */ + +/*----------------------------------------------------------------------------- + * Include files + *-----------------------------------------------------------------------------*/ +#include "ssf_lib.h" +#include "ssf_client.h" +#include +#ifdef __DEBUG__ +#include +#endif + +/*----------------------------------------------------------------------------- + * TEE Internal API implementation + *-----------------------------------------------------------------------------*/ + +TEE_Result TEE_OpenTASession(const TEE_UUID* destination, + uint32_t cancellationRequestTimeout, uint32_t paramTypes, + TEE_Param params[4], TEE_TASessionHandle* session, uint32_t* returnOrigin) { + + IntTAOpenSessionData data; + data.destination = *destination; + data.cancelTimeOut = cancellationRequestTimeout; + data.operation.paramTypes = paramTypes; + + memcpy(data.operation.params, params, sizeof(TEE_Param[4])); + + pthread_mutex_lock(&socketLock); + sendCommand(socketSimulatorDaemonFD, OPEN_TA_SESSION, &data, + sizeof(IntTAOpenSessionData)); + pthread_mutex_unlock(&socketLock); +#if 0 + printf("Inside: %s \n", __FUNCTION__); + data.params[0].value.a = 1; + data.params[0].value.b = 1; + data.params[1].value.a = 2; + data.params[1].value.b = 2; + data.params[2].value.a = 3; + data.params[2].value.b = 3; + data.params[3].value.a = 4; + data.params[3].value.b = 4; + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; + data.returnValue = TEE_SUCCESS; +#endif + + // Return from the function call + // [inout] TEE_Param params[4], + // [out] TEE_TASessionHandle* session, + // [out] uint32_t* returnOrigin); + uint32_t* sessionData = (uint32_t*)OsaMalloc(sizeof(uint32_t)); + memcpy(params, data.operation.params, sizeof(TEE_Param[4])); + *sessionData = data.session; + *session = (TEE_TASessionHandle)sessionData; + *returnOrigin = data.returnOrigin; + return data.returnValue; +} + +void TEE_CloseTASession(TEE_TASessionHandle session) { + + IntTACloseSessionData data; + data.session = *(uint32_t*)session; + pthread_mutex_lock(&socketLock); + sendCommand(socketSimulatorDaemonFD, CLOSE_TA_SESSION, &data, + sizeof(IntTACloseSessionData)); + pthread_mutex_unlock(&socketLock); + OsaFree(session); +} + +TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, + uint32_t cancellationRequestTimeout, uint32_t commandID, + uint32_t paramTypes, TEE_Param params[4], uint32_t* returnOrigin) { + IntTAInvokeCommandData data; + data.session = *(uint32_t*)session; + data.cancelTimeOut = cancellationRequestTimeout; + data.commandID = commandID; + data.operation.paramTypes = paramTypes; + memcpy(data.operation.params, params, sizeof(TEE_Param[4])); + pthread_mutex_lock(&socketLock); + sendCommand(socketSimulatorDaemonFD, INVOKE_TA_COMMAND, &data, + sizeof(IntTAInvokeCommandData)); + pthread_mutex_unlock(&socketLock); +#if 0 + printf("Inside: %s \n", __FUNCTION__); + data.params[0].value.a = 1; + data.params[0].value.b = 1; + data.params[1].value.a = 2; + data.params[1].value.b = 2; + data.params[2].value.a = 3; + data.params[2].value.b = 3; + data.params[3].value.a = 4; + data.params[3].value.b = 4; + + data.returnOrigin = TEE_ORIGIN_TRUSTED_APP; + data.returnValue = TEE_SUCCESS; +#endif + // Return from the function call + // [inout] TEE_Param params[4], + // [out] uint32_t* returnOrigin); + memcpy(params, data.operation.params, sizeof(TEE_Param[4])); + *returnOrigin = data.returnOrigin; + return data.returnValue; +} -- 2.7.4