From: Sungjae Lim Date: Wed, 22 Aug 2012 12:36:29 +0000 (+0900) Subject: update the latest source X-Git-Tag: 2.0_alpha^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2F2.0alpha;p=framework%2Fsystem%2Fsmartcard-service.git update the latest source --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..728b215 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +MESSAGE("build smartcard-service") + +SET(CMAKE_VERBOSE_MAKEFILE OFF) + +ADD_SUBDIRECTORY(common) +ADD_SUBDIRECTORY(server) +ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(test-client) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ec68963 --- /dev/null +++ b/LICENSE @@ -0,0 +1,206 @@ +Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000..20c8782 --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,89 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(smartcard-service CXX) + +SET(LIB_NAME "smartcard-service") +SET(VERSION_MAJOR 1) +SET(VERSION ${VERSION_MAJOR}.0.0) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SRCS) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs_client REQUIRED gthread-2.0 dlog) + +MESSAGE("${LIB_NAME} ld flag : ${pkgs_client_LDFLAGS}") + +FOREACH(flag ${pkgs_client_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${pkgs_client_CFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + + +#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -finstrument-functions") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +#SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +#SET(CMAKE_C_FLAGS_RELEASE "-O2") + +#SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} -finstrument-functions") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") +#SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +#SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") +MESSAGE("CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DSLP_DEBUG") + +ADD_DEFINITIONS("-DLOG_TAG=\"SCARD_CLIENT\"") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${VERSION}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_client_LDFLAGS}) + +SET(EXPORT_HEADER + ../common/include/smartcard-types.h + ../common/include/ByteArray.h + ../common/include/Debug.h + ../common/include/Synchronous.h + ../common/include/APDUHelper.h + ../common/include/Channel.h + ../common/include/Serializable.h + ../common/include/SEServiceHelper.h + ../common/include/ReaderHelper.h + ../common/include/SessionHelper.h +# ../common/include/FCI.h +# ../common/include/ + include/SEServiceListener.h + include/SEService.h + include/Reader.h + include/Session.h + include/ClientChannel.h +# include/ +) + +#CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc DESTINATION lib/pkgconfig) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib) +FOREACH(hfile ${EXPORT_HEADER}) + INSTALL(FILES ${hfile} DESTINATION include/${LIB_NAME}) +ENDFOREACH(hfile) diff --git a/client/ClientChannel.cpp b/client/ClientChannel.cpp new file mode 100644 index 0000000..68680fe --- /dev/null +++ b/client/ClientChannel.cpp @@ -0,0 +1,352 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Message.h" +#include "ClientIPC.h" +#include "ClientChannel.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + ClientChannel::ClientChannel(void *context, Session *session, int channelNum, ByteArray selectResponse, void *handle):Channel(session) + { + this->channelNum = -1; + this->handle = NULL; + this->context = NULL; + + if (handle == NULL) + { + SCARD_DEBUG_ERR("ClientIPC::getInstance() failed"); + + return; + } + + this->channelNum = channelNum; + this->handle = handle; + this->selectResponse = selectResponse; + this->context = context; + } + + ClientChannel::~ClientChannel() + { + close(NULL, this); + } + + void ClientChannel::closeSync() + { + Message msg; + int rv; + + if (isClosed() == false) + { + /* send message to server */ + msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL; + msg.param1 = (int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv < 0) + { + SCARD_DEBUG_ERR("closeSync failed [%d]", rv); + } + + channelNum = -1; + } + } + + int ClientChannel::close(closeCallback callback, void *userParam) + { + Message msg; + + if (isClosed() == false) + { + channelNum = -1; + + /* send message to server */ + msg.message = Message::MSG_REQUEST_CLOSE_CHANNEL; + msg.param1 = (int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userParam; + + ClientIPC::getInstance().sendMessage(&msg); + } + + return 0; + } + + int ClientChannel::transmitSync(ByteArray command, ByteArray &result) + { + Message msg; + int rv; + + /* send message to server */ + msg.message = Message::MSG_REQUEST_TRANSMIT; + msg.param1 = (int)handle; + msg.param2 = 0; + msg.data = command; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv < 0) + { + SCARD_DEBUG_ERR("clientIPC is null"); + + return -1; + } + + result = response; + + return 0; + } + + int ClientChannel::transmit(ByteArray command, transmitCallback callback, void *userParam) + { + Message msg; + + /* send message to server */ + msg.message = Message::MSG_REQUEST_TRANSMIT; + msg.param1 = (int)handle; + msg.param2 = 0; + msg.data = command; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userParam; + + ClientIPC::getInstance().sendMessage(&msg); + + return 0; + } + + bool ClientChannel::dispatcherCallback(void *message) + { + Message *msg = (Message *)message; + ClientChannel *channel = NULL; + bool result = false; + + if (msg == NULL) + { + SCARD_DEBUG_ERR("message is null"); + return result; + } + + channel = (ClientChannel *)msg->caller; + + switch (msg->message) + { + case Message::MSG_REQUEST_TRANSMIT : + { + /* transmit result */ + SCARD_DEBUG("MSG_REQUEST_TRANSMIT"); + + if (msg->callback == (void *)channel) /* synchronized call */ + { + /* sync call */ + channel->syncLock(); + + /* copy result */ + channel->error = msg->error; + channel->response = msg->data; + + channel->signalCondition(); + channel->syncUnlock(); + } + else if (msg->callback != NULL) + { + transmitCallback cb = (transmitCallback)msg->callback; + + /* async call */ + cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam); + } + } + break; + + case Message::MSG_REQUEST_CLOSE_CHANNEL : + { + SCARD_DEBUG("MSG_REQUEST_CLOSE_CHANNEL"); + + if (msg->callback == (void *)channel) /* synchronized call */ + { + /* sync call */ + channel->syncLock(); + + channel->error = msg->error; + + channel->signalCondition(); + channel->syncUnlock(); + } + else if (msg->callback != NULL) + { + closeCallback cb = (closeCallback)msg->callback; + + /* async call */ + cb(msg->error, msg->userParam); + } + } + break; + + default: + SCARD_DEBUG("unknwon message : %s", msg->toString()); + break; + } + + delete msg; + + return result; + } +} /* namespace smartcard_service_api */ + +/* export C API */ +#define CHANNEL_EXTERN_BEGIN \ + if (handle != NULL) \ + { \ + ClientChannel *channel = (ClientChannel *)handle; + +#define CHANNEL_EXTERN_END \ + } \ + else \ + { \ + SCARD_DEBUG_ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam) +{ + int result = -1; + + CHANNEL_EXTERN_BEGIN; + result = channel->close((closeCallback)callback, userParam); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_transmit(channel_h handle, unsigned char *command, unsigned int length, channel_transmit_cb callback, void *userParam) +{ + int result = -1; + + CHANNEL_EXTERN_BEGIN; + ByteArray temp; + + temp.setBuffer(command, length); + result = channel->transmit(temp, (transmitCallback)callback, userParam); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API bool channel_is_basic_channel(channel_h handle) +{ + bool result = false; + + CHANNEL_EXTERN_BEGIN; + result = channel->isBasicChannel(); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API bool channel_is_closed(channel_h handle) +{ + bool result = false; + + CHANNEL_EXTERN_BEGIN; + result = channel->isClosed(); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API unsigned int channel_get_select_response_length(channel_h handle) +{ + unsigned int result = 0; + + CHANNEL_EXTERN_BEGIN; + result = channel->getSelectResponse().getLength(); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API bool channel_get_select_response(channel_h handle, unsigned char *buffer, unsigned int length) +{ + bool result = false; + + if (buffer == NULL || length == 0) + { + return result; + } + + CHANNEL_EXTERN_BEGIN; + ByteArray response; + + response = channel->getSelectResponse(); + if (response.getLength() > 0) + { + memcpy(buffer, response.getBuffer(), MIN(length, response.getLength())); + result = true; + } + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API session_h channel_get_session(channel_h handle) +{ + session_h session = NULL; + + CHANNEL_EXTERN_BEGIN; + session = channel->getSession(); + CHANNEL_EXTERN_END; + + return session; +} + +EXTERN_API void channel_destroy_instance(channel_h handle) +{ + CHANNEL_EXTERN_BEGIN; + delete channel; + CHANNEL_EXTERN_END; +} diff --git a/client/ClientDispatcher.cpp b/client/ClientDispatcher.cpp new file mode 100644 index 0000000..84bbf4f --- /dev/null +++ b/client/ClientDispatcher.cpp @@ -0,0 +1,180 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ClientDispatcher.h" +#include "SEService.h" +#include "Reader.h" +#include "Session.h" +#include "ClientChannel.h" + +namespace smartcard_service_api +{ + ClientDispatcher::ClientDispatcher() + { + } + + ClientDispatcher::~ClientDispatcher() + { + mapSESerivces.clear(); + } + + ClientDispatcher &ClientDispatcher::getInstance() + { + static ClientDispatcher clientDispatcher; + + return clientDispatcher; + } + + bool ClientDispatcher::addSEService(void *context, SEService *service) + { + bool result = true; + map::iterator item; + + SCARD_BEGIN(); + + if ((item = mapSESerivces.find(context)) == mapSESerivces.end()) + { + mapSESerivces.insert(make_pair(context, service)); + } + else + { + SCARD_DEBUG("SEService [%p] exists", context); + } + + SCARD_END(); + + return result; + } + + void ClientDispatcher::removeSEService(void *context) + { + map::iterator item; + + SCARD_BEGIN(); + + if ((item = mapSESerivces.find(context)) != mapSESerivces.end()) + { + mapSESerivces.erase(item); + } + else + { + SCARD_DEBUG("SEService doesn't exist"); + } + + SCARD_END(); + } + + void *ClientDispatcher::dispatcherThreadFunc(DispatcherMsg *msg, void *data) + { + SCARD_BEGIN(); + + if (msg == NULL) + return NULL; + + /* this messages are response from server */ + switch (msg->message) + { + /* SE Service requests */ + case Message::MSG_REQUEST_READERS : + { + DispatcherMsg *tempMsg = new DispatcherMsg(msg); + + g_idle_add((GSourceFunc)&SEService::dispatcherCallback, (gpointer)tempMsg); + } + break; + + /* Reader requests */ + case Message::MSG_REQUEST_OPEN_SESSION : + { + DispatcherMsg *tempMsg = new DispatcherMsg(msg); + + g_idle_add((GSourceFunc)&Reader::dispatcherCallback, (gpointer)tempMsg); + } + break; + + /* Session requests */ + case Message::MSG_REQUEST_OPEN_CHANNEL : + case Message::MSG_REQUEST_GET_ATR : + case Message::MSG_REQUEST_CLOSE_SESSION : + case Message::MSG_REQUEST_GET_CHANNEL_COUNT : + { + DispatcherMsg *tempMsg = new DispatcherMsg(msg); + + g_idle_add((GSourceFunc)&Session::dispatcherCallback, (gpointer)tempMsg); + } + break; + + /* ClientChannel requests */ + case Message::MSG_REQUEST_TRANSMIT : + case Message::MSG_REQUEST_CLOSE_CHANNEL : + { + DispatcherMsg *tempMsg = new DispatcherMsg(msg); + + g_idle_add((GSourceFunc)&ClientChannel::dispatcherCallback, (gpointer)tempMsg); + } + break; + + case Message::MSG_NOTIFY_SE_INSERTED : + case Message::MSG_NOTIFY_SE_REMOVED : + { + map::iterator item; + + for (item = mapSESerivces.begin(); item != mapSESerivces.end(); item++) + { + DispatcherMsg *tempMsg = new DispatcherMsg(msg); + + tempMsg->caller = item->second; + + g_idle_add((GSourceFunc)&SEService::dispatcherCallback, (gpointer)tempMsg); + } + } + break; + + case Message::MSG_OPERATION_RELEASE_CLIENT : + { + map::iterator item; + + for (item = mapSESerivces.begin(); item != mapSESerivces.end(); item++) + { + DispatcherMsg *tempMsg = new DispatcherMsg(msg); + + tempMsg->caller = item->second; + tempMsg->error = -1; + + g_idle_add((GSourceFunc)&SEService::dispatcherCallback, (gpointer)tempMsg); + } + } + break; + + default : + break; + } + + SCARD_END(); + + return NULL; + } + +} /* namespace open_mobile_api */ + diff --git a/client/ClientIPC.cpp b/client/ClientIPC.cpp new file mode 100644 index 0000000..314d987 --- /dev/null +++ b/client/ClientIPC.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ClientIPC.h" +#include "DispatcherMsg.h" + +namespace smartcard_service_api +{ + ClientIPC::ClientIPC():IPCHelper() + { + } + + ClientIPC::~ClientIPC() + { + } + + ClientIPC &ClientIPC::getInstance() + { + static ClientIPC clientIPC; + + return clientIPC; + } + + int ClientIPC::handleIOErrorCondition(void *channel, GIOCondition condition) + { + SCARD_BEGIN(); + + /* finalize context */ + if (watchId != 0) + { + g_source_remove(watchId); + watchId = 0; + } + + if (ioChannel != NULL) + { + g_io_channel_unref(ioChannel); + ioChannel = NULL; + } + + if (ipcSocket != -1) + { + shutdown(ipcSocket, SHUT_RDWR); + close(ipcSocket); + + ipcSocket = -1; + } + + /* push disconnect message */ + DispatcherMsg *dispMsg = new DispatcherMsg(); + + dispMsg->message = Message::MSG_OPERATION_RELEASE_CLIENT; + dispMsg->error = -1; + + if (dispatcher != NULL) + dispatcher->pushMessage(dispMsg); + + SCARD_END(); + + return FALSE; + } + + int ClientIPC::handleInvalidSocketCondition(void *channel, GIOCondition condition) + { + SCARD_BEGIN(); + + /* finalize context */ + + SCARD_END(); + + return FALSE; + } + + int ClientIPC::handleIncomingCondition(void *channel, GIOCondition condition) + { + int result = FALSE; + + SCARD_BEGIN(); + + if (channel == ioChannel) + { + Message *msg = NULL; + + SCARD_DEBUG("message from server to client socket"); + + /* read message */ + msg = retrieveMessage(); + if (msg != NULL) + { + DispatcherMsg *dispMsg = new DispatcherMsg(msg); + + /* set peer socket */ + dispMsg->setPeerSocket(ipcSocket); + + /* push to dispatcher */ + if (dispatcher != NULL) + dispatcher->pushMessage(dispMsg); + + result = TRUE; + } + else + { + /* clear client connection */ + } + + delete msg; + } + else + { + SCARD_DEBUG_ERR("Unknown channel event [%p]", channel); + } + + SCARD_END(); + + return result; + } + +} /* namespace open_mobile_api */ diff --git a/client/Reader.cpp b/client/Reader.cpp new file mode 100644 index 0000000..aca37ed --- /dev/null +++ b/client/Reader.cpp @@ -0,0 +1,281 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Message.h" +#include "ClientIPC.h" +#include "Reader.h" +#include "Session.h" +#include "SignatureHelper.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + Reader::Reader(void *context, char *name, void *handle):ReaderHelper() + { + unsigned int length = 0; + + SCARD_BEGIN(); + + this->context = NULL; + this->handle = NULL; + + if (context == NULL || name == NULL || strlen(name) == 0 || handle == NULL) + { + SCARD_DEBUG_ERR("invalid param"); + + return; + } + + this->handle = handle; + this->context = context; + + length = strlen(name); + length = (length < sizeof(this->name)) ? length : sizeof(this->name); + memcpy(this->name, name, length); + + getPackageCert(); + + SCARD_END(); + } + + Reader::~Reader() + { + closeSessions(); + } + + void Reader::closeSessions() + { + size_t i; + + for (i = 0; i < sessions.size(); i++) + { + sessions[i]->close(NULL, this); + } + + sessions.clear(); + } + + void Reader::getPackageCert() + { + packageCert = SignatureHelper::getCertificationHash(getpid()); + } + + SessionHelper *Reader::openSessionSync() + { + Message msg; + int rv; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_OPEN_SESSION; + msg.param1 = (unsigned int)handle; + msg.data = packageCert; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv != 0) + { + SCARD_DEBUG_ERR("time over"); + + return NULL; + } + + return (Session *)openedSession; + } + + int Reader::openSession(openSessionCallback callback, void *userData) + { + Message msg; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_OPEN_SESSION; + msg.param1 = (unsigned int)handle; + msg.data = packageCert; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userData; + + ClientIPC::getInstance().sendMessage(&msg); + + return 0; + } + + bool Reader::dispatcherCallback(void *message) + { + Message *msg = (Message *)message; + Reader *reader = NULL; + bool result = false; + + SCARD_BEGIN(); + + if (msg == NULL) + { + SCARD_DEBUG_ERR("message is null"); + return result; + } + + reader = (Reader *)msg->caller; + + switch (msg->message) + { + case Message::MSG_REQUEST_OPEN_SESSION : + { + Session *session = NULL; + + SCARD_DEBUG("MSG_REQUEST_OPEN_SESSION"); + + if (msg->param1 != 0) + { + /* create new instance of channel */ + session = new Session(reader->context, reader, (void *)msg->param1); + if (session == NULL) + { + SCARD_DEBUG_ERR("Session creating instance failed"); + + return session; + } + + reader->sessions.push_back(session); + } + + if (msg->callback == (void *)reader) /* synchronized call */ + { + /* sync call */ + reader->syncLock(); + + /* copy result */ + reader->error = msg->error; + reader->openedSession = session; + reader->signalCondition(); + + reader->syncUnlock(); + } + else if (msg->callback != NULL) + { + openSessionCallback cb = (openSessionCallback)msg->callback; + + /* async call */ + cb(session, msg->error, msg->userParam); + } + } + break; + + default: + SCARD_DEBUG("unknown [%s]", msg->toString()); + break; + } + + delete msg; + + SCARD_END(); + + return result; + } + +} /* namespace smartcard_service_api */ + +/* export C API */ +#define READER_EXTERN_BEGIN \ + if (handle != NULL) \ + { \ + Reader *reader = (Reader *)handle; + +#define READER_EXTERN_END \ + } \ + else \ + { \ + SCARD_DEBUG_ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API const char *reader_get_name(reader_h handle) +{ + const char *name = NULL; + + READER_EXTERN_BEGIN; + name = reader->getName(); + READER_EXTERN_END; + + return name; +} + +EXTERN_API se_service_h reader_get_se_service(reader_h handle) +{ + se_service_h service = NULL; + + READER_EXTERN_BEGIN; + service = (se_service_h)reader->getSEService(); + READER_EXTERN_END; + + return service; +} + +EXTERN_API bool reader_is_secure_element_present(reader_h handle) +{ + bool result = false; + + READER_EXTERN_BEGIN; + result = reader->isSecureElementPresent(); + READER_EXTERN_END; + + return result; +} + +EXTERN_API int reader_open_session(reader_h handle, reader_open_session_cb callback, void *userData) +{ + int result = -1; + + READER_EXTERN_BEGIN; + result = reader->openSession((openSessionCallback)callback, userData); + READER_EXTERN_END; + + return result; +} + +EXTERN_API void reader_close_sessions(reader_h handle) +{ + READER_EXTERN_BEGIN; + reader->closeSessions(); + READER_EXTERN_END; +} + +EXTERN_API void reader_destroy_instance(reader_h handle) +{ + READER_EXTERN_BEGIN; + delete reader; + READER_EXTERN_END; +} diff --git a/client/SEService.cpp b/client/SEService.cpp new file mode 100644 index 0000000..52c6642 --- /dev/null +++ b/client/SEService.cpp @@ -0,0 +1,407 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ClientIPC.h" +#include "ClientDispatcher.h" +#include "SEService.h" +#include "Reader.h" +#include "Message.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + SEService::SEService():SEServiceHelper() + { + pid = -1; + this->context = NULL; + this->handler = NULL; + this->listener = NULL; + connected = false; + + pid = getpid(); + } + + SEService::SEService(void *user_data, serviceConnected handler):SEServiceHelper() + { + pid = -1; + this->context = NULL; + this->handler = NULL; + this->listener = NULL; + connected = false; + + pid = getpid(); + + initialize(user_data, handler); + } + + SEService::SEService(void *user_data, SEServiceListener *listener):SEServiceHelper() + { + pid = -1; + this->context = NULL; + this->handler = NULL; + this->listener = NULL; + connected = false; + + pid = getpid(); + + initialize(user_data, listener); + } + + SEService::~SEService() + { + } + + void SEService::shutdown() + { + ClientDispatcher::getInstance().removeSEService(context); + } + + bool SEService::_initialize() + { + bool result = false; +#ifdef SECURITY_SERVER + int cookies_size; + char *cookies = NULL; +#endif + ClientIPC *clientIPC = NULL; + ClientDispatcher *clientDispatcher = NULL; + + SCARD_BEGIN(); + + /* initialize client */ + if (!g_thread_supported()) + { + g_thread_init(NULL); + } + +#ifdef SECURITY_SERVER + if ((cookies_size = security_server_get_cookie_size()) != 0) + { + _net_nfc_client_util_alloc_mem(cookies, cookies_size); + int error = 0; + if ((error = security_server_request_cookie(cookies, cookies_size)) != SECURITY_SERVER_API_SUCCESS) + { + DEBUG_CLIENT_MSG("security server request cookies error = [%d]", error); + _net_nfc_client_util_free_mem(cookies); + } + else + { + char printf_buff[BUFFER_LENGTH_MAX] = { 0, }; + int buff_count = BUFFER_LENGTH_MAX; + int i = 0; + + for (; i < cookies_size; i++) + { + buff_count -= snprintf((char *)(printf_buff + BUFFER_LENGTH_MAX - buff_count), buff_count, " %02X", cookies[i]); + } + DEBUG_CLIENT_MSG("client send cookies >>>> %s \n", printf_buff); + + _net_nfc_client_set_cookies(cookies, cookies_size); + } + } +#endif + + clientDispatcher = &ClientDispatcher::getInstance(); + clientIPC = &ClientIPC::getInstance(); + + clientIPC->setDispatcher(clientDispatcher); + + if (clientDispatcher->runDispatcherThread() == false) + { + SCARD_DEBUG_ERR("clientDispatcher->runDispatcherThread() failed"); + + return result; + } + + if (clientIPC->createConnectSocket() == false) + { + SCARD_DEBUG_ERR("clientIPC->createConnectSocket() failed"); + + return result; + } + + clientDispatcher->addSEService(context, this); + + { + /* send message to load se */ + Message msg; + + msg.message = Message::MSG_REQUEST_READERS; + msg.error = pid; /* using error to pid */ + msg.caller = (void *)this; + msg.userParam = context; + + result = clientIPC->sendMessage(&msg); + } + + SCARD_END(); + + return result; + } + + bool SEService::initialize(void *context, serviceConnected handler) + { + if (context == NULL) + { + SCARD_DEBUG_ERR("invalid param"); + return false; + } + + this->context = context; + this->handler = handler; + + return _initialize(); + } + + bool SEService::initialize(void *context, SEServiceListener *listener) + { + if (context == NULL) + { + SCARD_DEBUG_ERR("invalid param"); + return false; + } + + this->context = context; + this->listener = listener; + + return _initialize(); + } + + bool SEService::parseReaderInformation(unsigned int count, ByteArray data) + { + size_t i; + unsigned int offset = 0; + unsigned int len = 0; + void *handle = NULL; + Reader *reader = NULL; + char name[100]; + + for (i = 0; i < count && offset < data.getLength(); i++) + { + memset(name, 0, sizeof(name)); + + memcpy(&len, data.getBuffer(offset), sizeof(len)); + offset += sizeof(len); + + memcpy(name, data.getBuffer(offset), len); + offset += len; + + memcpy(&handle, data.getBuffer(offset), sizeof(handle)); + offset += sizeof(handle); + + SCARD_DEBUG("Reader [%d] : name [%s], handle [%p]", i, name, handle); + + /* add readers */ + reader = new Reader(context, name, handle); + if (reader == NULL) + { + SCARD_DEBUG_ERR("alloc failed"); + continue; + } + + readers.push_back(reader); + } + + return true; + } + + bool SEService::dispatcherCallback(void *message) + { + Message *msg = (Message *)message; + SEService *service = NULL; + bool result = false; + + SCARD_BEGIN(); + + if (msg == NULL) + { + SCARD_DEBUG_ERR("message is null"); + return result; + } + + service = (SEService *)msg->caller; + + switch (msg->message) + { + case Message::MSG_REQUEST_READERS : + SCARD_DEBUG("[MSG_REQUEST_READERS]"); + + /* parse message data */ + service->parseReaderInformation(msg->param1, msg->data); + + /* call callback function */ + if (service->listener != NULL) + { + service->listener->serviceConnected(service, service->context); + } + else if (service->handler != NULL) + { + service->handler(service, service->context); + } + break; + + case Message::MSG_NOTIFY_SE_INSERTED : + SCARD_DEBUG("[MSG_NOTIFY_SE_INSERTED]"); + + if (service->listener != NULL) + { + service->listener->eventHandler(service, (char *)msg->data.getBuffer(), 1, service->context); + } + else + { + SCARD_DEBUG_ERR("service->listener is null"); + } + break; + + case Message::MSG_NOTIFY_SE_REMOVED : + SCARD_DEBUG("[MSG_NOTIFY_SE_REMOVED]"); + + if (service->listener != NULL) + { + service->listener->eventHandler(service, (char *)msg->data.getBuffer(), 2, service->context); + } + else + { + SCARD_DEBUG_ERR("service->listener is null"); + } + break; + + case Message::MSG_OPERATION_RELEASE_CLIENT : + SCARD_DEBUG("[MSG_OPERATION_RELEASE_CLIENT]"); + + if (service->listener != NULL) + { + service->listener->errorHandler(service, msg->error, service->context); + } + else + { + SCARD_DEBUG_ERR("service->listener is null"); + } + break; + + default: + SCARD_DEBUG("unknown message [%s]", msg->toString()); + break; + } + + delete msg; + + SCARD_END(); + + return result; + } + +} /* namespace smartcard_service_api */ + +/* export C API */ +#define SE_SERVICE_EXTERN_BEGIN \ + if (handle != NULL) \ + { \ + SEService *service = (SEService *)handle; + +#define SE_SERVICE_EXTERN_END \ + } \ + else \ + { \ + SCARD_DEBUG_ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback) +{ + SEService *service = new SEService(user_data, (serviceConnected)callback); + + return (se_service_h)service; +} + +EXTERN_API se_service_h se_service_create_instance_with_event_callback(void *user_data, se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error) +{ + SEService *service = new SEService(user_data, (serviceConnected)connected); + + return (se_service_h)service; +} + +EXTERN_API int se_service_get_readers_count(se_service_h handle) +{ + int count = 0; + + SE_SERVICE_EXTERN_BEGIN; + vector temp_readers; + + temp_readers = service->getReaders(); + count = temp_readers.size(); + SE_SERVICE_EXTERN_END; + + return count; +} + +EXTERN_API bool se_service_get_readers(se_service_h handle, reader_h *readers, int count) +{ + bool result = false; + + SE_SERVICE_EXTERN_BEGIN; + vector temp_readers; + size_t i; + + temp_readers = service->getReaders(); + + for (i = 0; i < temp_readers.size() && i < (size_t)count; i++) + { + readers[i] = (reader_h)temp_readers[i]; + } + SE_SERVICE_EXTERN_END; + + return result; +} + +EXTERN_API bool se_service_is_connected(se_service_h handle) +{ + bool result = false; + + SE_SERVICE_EXTERN_BEGIN; + result = service->isConnected(); + SE_SERVICE_EXTERN_END; + + return result; +} + +EXTERN_API void se_service_shutdown(se_service_h handle) +{ + SE_SERVICE_EXTERN_BEGIN; + service->shutdown(); + SE_SERVICE_EXTERN_END; +} + +EXTERN_API void se_service_destroy_instance(se_service_h handle) +{ + SE_SERVICE_EXTERN_BEGIN; + delete service; + SE_SERVICE_EXTERN_END; +} diff --git a/client/Session.cpp b/client/Session.cpp new file mode 100644 index 0000000..79531b1 --- /dev/null +++ b/client/Session.cpp @@ -0,0 +1,550 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Session.h" +#include "Reader.h" +#include "ClientChannel.h" +#include "ClientIPC.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + Session::Session(void *context, Reader *reader, void *handle):SessionHelper(reader) + { + this->context = NULL; + + if (context == NULL || handle == NULL) + { + SCARD_DEBUG_ERR("handle is null"); + + return; + } + + this->context = context; + this->handle = handle; + closed = false; + } + + Session::~Session() + { + close(NULL, this); + } + + void Session::closeChannels() + { + size_t i; + + for (i = 0; i < channels.size(); i++) + { + channels[i]->close(NULL, this); + } + + channels.clear(); + } + + ByteArray Session::getATRSync() + { + Message msg; + int rv; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_GET_ATR; + msg.param1 = (unsigned int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv != 0) + { + SCARD_DEBUG_ERR("time over"); + + atr.releaseBuffer(); + } + + return atr; + } + + int Session::getATR(getATRCallback callback, void *userData) + { + Message msg; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_GET_ATR; + msg.param1 = (unsigned int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userData; + + ClientIPC::getInstance().sendMessage(&msg); + + return 0; + } + + void Session::closeSync() + { + Message msg; + int rv; + + if (isClosed() == false) + { + closed = true; + closeChannels(); + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_CLOSE_SESSION; + msg.param1 = (unsigned int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv != 0) + { + SCARD_DEBUG_ERR("time over"); + } + } + } + + int Session::close(closeSessionCallback callback, void *userData) + { + Message msg; + + if (isClosed() == false) + { + closed = true; + closeChannels(); + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_CLOSE_SESSION; + msg.param1 = (unsigned int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userData; + + ClientIPC::getInstance().sendMessage(&msg); + } + + return 0; + } + + unsigned int Session::getChannelCount(getChannelCountCallback callback, void *userData) + { + Message msg; + + msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT; + msg.param1 = (unsigned int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userData; + + ClientIPC::getInstance().sendMessage(&msg); + + return 0; + } + + unsigned int Session::getChannelCountSync() + { + Message msg; + int rv; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_GET_CHANNEL_COUNT; + msg.param1 = (unsigned int)handle; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv != 0) + { + SCARD_DEBUG_ERR("time over"); + + return -1; + } + + return channelCount; + } + + Channel *Session::openChannelSync(int id, ByteArray aid) + { + Message msg; + int rv; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_OPEN_CHANNEL; + msg.param1 = id; + msg.param2 = (unsigned int)handle; + msg.data = aid; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)this; /* if callback is class instance, it means synchronized call */ + + ClientIPC::getInstance().sendMessage(&msg); + + syncLock(); + rv = waitTimedCondition(0); + syncUnlock(); + + if (rv != 0) + { + SCARD_DEBUG_ERR("time over"); + + return NULL; + } + + return (Channel *)openedChannel; + } + + int Session::openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData) + { + Message msg; + + /* request channel handle from server */ + msg.message = Message::MSG_REQUEST_OPEN_CHANNEL; + msg.param1 = id; + msg.param2 = (unsigned int)handle; + msg.data = aid; + msg.error = (unsigned int)context; /* using error to context */ + msg.caller = (void *)this; + msg.callback = (void *)callback; + msg.userParam = userData; + + ClientIPC::getInstance().sendMessage(&msg); + + return 0; + } + + Channel *Session::openBasicChannelSync(ByteArray aid) + { + return openChannelSync(0, aid); + } + + Channel *Session::openBasicChannelSync(unsigned char *aid, unsigned int length) + { + return openBasicChannelSync(ByteArray(aid, length)); + } + + int Session::openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData) + { + return openChannel(0, aid, callback, userData); + } + + int Session::openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData) + { + return openBasicChannel(ByteArray(aid, length), callback, userData); + } + + Channel *Session::openLogicalChannelSync(ByteArray aid) + { + return openChannelSync(1, aid); + } + + Channel *Session::openLogicalChannelSync(unsigned char *aid, unsigned int length) + { + return openLogicalChannelSync(ByteArray(aid, length)); + } + + int Session::openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData) + { + return openChannel(1, aid, callback, userData); + } + + int Session::openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData) + { + return openLogicalChannel(ByteArray(aid, length), callback, userData); + } + + bool Session::dispatcherCallback(void *message) + { + Message *msg = (Message *)message; + Session *session = NULL; + bool result = false; + + if (msg == NULL) + { + SCARD_DEBUG_ERR("message is null"); + return result; + } + + session = (Session *)msg->caller; + + switch (msg->message) + { + case Message::MSG_REQUEST_OPEN_CHANNEL : + { + Channel *channel = NULL; + + SCARD_DEBUG("MSG_REQUEST_OPEN_CHANNEL"); + + if (msg->param1 != 0) + { + /* create new instance of channel */ + channel = new ClientChannel(session->context, session, msg->param2, msg->data, (void *)msg->param1); + if (channel != NULL) + { + session->channels.push_back(channel); + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + + msg->error = -1; + } + } + + if (msg->callback == (void *)session) /* synchronized call */ + { + /* sync call */ + session->syncLock(); + + /* copy result */ + session->error = msg->error; + session->openedChannel = channel; + + session->signalCondition(); + session->syncUnlock(); + } + else if (msg->callback != NULL) + { + openChannelCallback cb = (openChannelCallback)msg->callback; + + /* async call */ + cb(channel, msg->error, msg->userParam); + } + } + break; + + case Message::MSG_REQUEST_GET_ATR : + { + SCARD_DEBUG("MSG_REQUEST_GET_ATR"); + + if (msg->callback == (void *)session) /* synchronized call */ + { + /* sync call */ + session->syncLock(); + + session->error = msg->error; + session->atr = msg->data; + + session->signalCondition(); + session->syncUnlock(); + } + else if (msg->callback != NULL) + { + getATRCallback cb = (getATRCallback)msg->callback; + + /* async call */ + cb(msg->data.getBuffer(), msg->data.getLength(), msg->error, msg->userParam); + } + } + break; + + case Message::MSG_REQUEST_CLOSE_SESSION : + { + SCARD_DEBUG("MSG_REQUEST_CLOSE_SESSION"); + + if (msg->callback == (void *)session) /* synchronized call */ + { + /* sync call */ + session->syncLock(); + + session->error = msg->error; + + session->signalCondition(); + session->syncUnlock(); + } + else if (msg->callback != NULL) + { + closeSessionCallback cb = (closeSessionCallback)msg->callback; + + /* async call */ + cb(msg->error, msg->userParam); + } + } + break; + + case Message::MSG_REQUEST_GET_CHANNEL_COUNT : + { + SCARD_DEBUG("MSG_REQUEST_GET_CHANNEL_COUNT"); + + if (msg->callback == (void *)session) /* synchronized call */ + { + /* sync call */ + session->syncLock(); + + session->error = msg->error; + session->channelCount = msg->param1; + + session->signalCondition(); + session->syncUnlock(); + } + else if (msg->callback != NULL) + { + getChannelCountCallback cb = (getChannelCountCallback)msg->callback; + + /* async call */ + cb(msg->param1, msg->error, msg->userParam); + } + } + break; + + default: + SCARD_DEBUG("unknown message : %s", msg->toString()); + break; + } + + delete msg; + + return result; + } +} /* namespace smartcard_service_api */ + +/* export C API */ +#define SESSION_EXTERN_BEGIN \ + if (handle != NULL) \ + { \ + Session *session = (Session *)handle; + +#define SESSION_EXTERN_END \ + } \ + else \ + { \ + SCARD_DEBUG_ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API reader_h session_get_reader(session_h handle) +{ + reader_h reader = NULL; + + SESSION_EXTERN_BEGIN; + reader = session->getReader(); + SESSION_EXTERN_END; + + return reader; +} + +EXTERN_API int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData) +{ + int result = -1; + + SESSION_EXTERN_BEGIN; + result = session->getATR((getATRCallback)callback, userData); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_close(session_h handle, session_close_session_cb callback, void *userData) +{ + int result = -1; + + SESSION_EXTERN_BEGIN; + result = session->close((closeSessionCallback)callback, userData); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API bool session_is_closed(session_h handle) +{ + bool result = false; + + SESSION_EXTERN_BEGIN; + result = session->isClosed(); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API void session_close_channels(session_h handle) +{ + SESSION_EXTERN_BEGIN; + session->closeChannels(); + SESSION_EXTERN_END; +} + +EXTERN_API int session_open_basic_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData) +{ + int result = -1; + + SESSION_EXTERN_BEGIN; + result = session->openBasicChannel(aid, length, (openChannelCallback)callback, userData); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_open_logical_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData) +{ + int result = -1; + + SESSION_EXTERN_BEGIN; + result = session->openLogicalChannel(aid, length, (openChannelCallback)callback, userData); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API unsigned int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData) +{ + unsigned int result = 0; + + SESSION_EXTERN_BEGIN; + result = session->getChannelCount((getChannelCountCallback)callback, userData); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API void session_destroy_instance(session_h handle) +{ + SESSION_EXTERN_BEGIN; + delete session; + SESSION_EXTERN_END; +} diff --git a/client/include/ClientChannel.h b/client/include/ClientChannel.h new file mode 100644 index 0000000..902265c --- /dev/null +++ b/client/include/ClientChannel.h @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2012 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 CLIENTCHANNEL_H_ +#define CLIENTCHANNEL_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "Channel.h" +#include "Session.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class ClientChannel: public Channel + { + private: + void *context; + void *handle; + /* temporary data for sync function */ + int error; + ByteArray response; + + ClientChannel(void *context, Session *session, int channelNum, ByteArray selectResponse, void *handle); + + static bool dispatcherCallback(void *message); + + void closeSync(); + int transmitSync(ByteArray command, ByteArray &result); + + public: + ~ClientChannel(); + + int close(closeCallback callback, void *userParam); + int transmit(ByteArray command, transmitCallback callback, void *userParam); + + friend class ClientDispatcher; + friend class Session; + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int channel_close(channel_h handle, channel_close_cb callback, void *userParam); +int channel_transmit(channel_h handle, unsigned char *command, unsigned int length, channel_transmit_cb callback, void *userParam); +bool channel_is_basic_channel(channel_h handle); +bool channel_is_closed(channel_h handle); + +unsigned int channel_get_select_response_length(channel_h handle); +bool channel_get_select_response(channel_h handle, unsigned char *buffer, unsigned int length); +session_h channel_get_session(channel_h handle); +void channel_destroy_instance(channel_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CLIENTCHANNEL_H_ */ diff --git a/client/include/ClientDispatcher.h b/client/include/ClientDispatcher.h new file mode 100644 index 0000000..7dc42c5 --- /dev/null +++ b/client/include/ClientDispatcher.h @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2012 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 CLIENTDISPATCHER_H_ +#define CLIENTDISPATCHER_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "DispatcherHelper.h" + +using namespace std; + +namespace smartcard_service_api +{ + class SEService; + + class ClientDispatcher: public DispatcherHelper + { + private: + map mapSESerivces; + + ClientDispatcher(); + ~ClientDispatcher(); + + void *dispatcherThreadFunc(DispatcherMsg *msg, void *data); + + public: + static ClientDispatcher &getInstance(); + + bool addSEService(void *context, SEService *service); + void removeSEService(void *context); + }; + +} /* namespace open_mobile_api */ +#endif /* CLIENTDISPATCHER_H_ */ diff --git a/client/include/ClientIPC.h b/client/include/ClientIPC.h new file mode 100644 index 0000000..5635897 --- /dev/null +++ b/client/include/ClientIPC.h @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2012 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 CLIENTIPC_H_ +#define CLIENTIPC_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "IPCHelper.h" +#include "SEServiceListener.h" + +namespace smartcard_service_api +{ + class ClientIPC: public IPCHelper + { + private: + ClientIPC(); + ~ClientIPC(); + + int handleIOErrorCondition(void *channel, GIOCondition condition); + int handleInvalidSocketCondition(void *channel, GIOCondition condition); + int handleIncomingCondition(void *channel, GIOCondition condition); + + public: + static ClientIPC &getInstance(); + }; + +} /* namespace open_mobile_api */ +#endif /* CLIENTIPC_H_ */ diff --git a/client/include/Reader.h b/client/include/Reader.h new file mode 100644 index 0000000..fc7306e --- /dev/null +++ b/client/include/Reader.h @@ -0,0 +1,81 @@ +/* +* Copyright (c) 2012 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 READER_H_ +#define READER_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "ReaderHelper.h" +#include "Session.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class Reader: public ReaderHelper + { + private: + void *context; + void *handle; + ByteArray packageCert; + /* temporary data for sync function */ + int error; + Session *openedSession; + + Reader(void *context, char *name, void *handle); + + SessionHelper *openSessionSync(); + static bool dispatcherCallback(void *message); + void getPackageCert(); + + public: + ~Reader(); + + int openSession(openSessionCallback callback, void *userData); + void closeSessions(); + + friend class SEService; + friend class ClientDispatcher; + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +const char *reader_get_name(reader_h handle); +se_service_h reader_get_se_service(reader_h handle); +bool reader_is_secure_element_present(reader_h handle); +int reader_open_session(reader_h handle, reader_open_session_cb callback, void *userData); +void reader_close_sessions(reader_h handle); +void reader_destroy_instance(reader_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* READER_H_ */ diff --git a/client/include/SEService.h b/client/include/SEService.h new file mode 100644 index 0000000..2a6989e --- /dev/null +++ b/client/include/SEService.h @@ -0,0 +1,88 @@ +/* +* Copyright (c) 2012 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 SESERVICE_H_ +#define SESERVICE_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "SEServiceListener.h" +#include "SEServiceHelper.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +using namespace std; + +namespace smartcard_service_api +{ + typedef void (*serviceConnected)(SEServiceHelper *service, void *context); + + class SEService: public SEServiceHelper + { + private: + int pid; + void *context; + serviceConnected handler; + SEServiceListener *listener; + + SEService(); + + static bool dispatcherCallback(void *message); + bool parseReaderInformation(unsigned int count, ByteArray data); + + bool _initialize(); + bool initialize(void *context, serviceConnected handler); + bool initialize(void *context, SEServiceListener *listener); + SEService *initializeSync(void *context, serviceConnected handler); + + public: + SEService(void *user_data, serviceConnected handler); + SEService(void *user_data, SEServiceListener *listener); + ~SEService(); + + void shutdown(); + + friend class ClientDispatcher; + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +se_service_h se_service_create_instance(void *user_data, se_service_connected_cb callback); +se_service_h se_service_create_instance_with_event_callback(void *user_data, se_service_connected_cb connected, se_service_event_cb event, se_sesrvice_error_cb error); +int se_service_get_readers_count(se_service_h handle); +bool se_service_get_readers(se_service_h handle, reader_h *readers, int count); +bool se_service_is_connected(se_service_h handle); +void se_service_shutdown(se_service_h handle); +void se_service_destroy_instance(se_service_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SESERVICE_H_ */ diff --git a/client/include/SEServiceListener.h b/client/include/SEServiceListener.h new file mode 100644 index 0000000..3f40165 --- /dev/null +++ b/client/include/SEServiceListener.h @@ -0,0 +1,39 @@ +/* +* Copyright (c) 2012 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 SESERVICELISTENER_H_ +#define SESERVICELISTENER_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ + +namespace smartcard_service_api +{ + class SEServiceHelper; + + class SEServiceListener + { + public: + virtual void serviceConnected(SEServiceHelper *service, void *context) = 0; + virtual void eventHandler(SEServiceHelper *service, char *seName, int event, void *context) = 0; + virtual void errorHandler(SEServiceHelper *service, int error, void *context) = 0; + }; + +} /* namespace open_mobile_api */ +#endif /* SESERVICELISTENER_H_ */ diff --git a/client/include/Session.h b/client/include/Session.h new file mode 100644 index 0000000..9ec499e --- /dev/null +++ b/client/include/Session.h @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2012 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 SESSION_H_ +#define SESSION_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "SessionHelper.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class Reader; + + class Session: public SessionHelper + { + private: + void *context; + void *handle; + /* temporary data for sync function */ + int error; + Channel *openedChannel; + unsigned int channelCount; + + Session(void *context, Reader *reader, void *handle); + + int openChannel(int id, ByteArray aid, openChannelCallback callback, void *userData); + static bool dispatcherCallback(void *message); + + Channel *openChannelSync(int id, ByteArray aid); + + ByteArray getATRSync(); + void closeSync(); + + Channel *openBasicChannelSync(ByteArray aid); + Channel *openBasicChannelSync(unsigned char *aid, unsigned int length); + Channel *openLogicalChannelSync(ByteArray aid); + Channel *openLogicalChannelSync(unsigned char *aid, unsigned int length); + unsigned int getChannelCountSync(); + + public: + ~Session(); + + int getATR(getATRCallback callback, void *userData); + int close(closeSessionCallback callback, void *userData); + + void closeChannels(); + + int openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData); + int openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData); + int openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData); + int openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData); + unsigned int getChannelCount(getChannelCountCallback callback, void * userData); + + friend class ClientDispatcher; + friend class Reader; + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +reader_h session_get_reader(session_h handle); +int session_get_atr(session_h handle, session_get_atr_cb callback, void *userData); +int session_close(session_h handle, session_close_session_cb callback, void *userData); +bool session_is_closed(session_h handle); +void session_close_channels(session_h handle); + +int session_open_basic_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData); +int session_open_logical_channel(session_h handle, unsigned char *aid, unsigned int length, session_open_channel_cb callback, void *userData); +unsigned int session_get_channel_count(session_h handle, session_get_channel_count_cb callback, void * userData); +void session_destroy_instance(session_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SESSION_H_ */ diff --git a/client/smartcard-service.pc b/client/smartcard-service.pc new file mode 100644 index 0000000..a58f2e7 --- /dev/null +++ b/client/smartcard-service.pc @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=/usr +exec_prefix=${prefix}/bin +includedir=${prefix}/include +libdir=${prefix}/lib + +Name: smartcard-service +Description: Make flags of Common library of Smartcard service +Version: 1.0 +Requires: +Libs: -L${libdir} -lsmartcard-service +Cflags: -I${includedir}/smartcard-service \ No newline at end of file diff --git a/common/APDUHelper.cpp b/common/APDUHelper.cpp new file mode 100644 index 0000000..8dc2b41 --- /dev/null +++ b/common/APDUHelper.cpp @@ -0,0 +1,519 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "APDUHelper.h" + +namespace smartcard_service_api +{ + /* ResponseHelper class */ + ResponseHelper::ResponseHelper() + { + } + + ResponseHelper::ResponseHelper(const ByteArray &response) + { + setResponse(response); + } + + ResponseHelper::~ResponseHelper() + { + } + + bool ResponseHelper::setResponse(const ByteArray &response) + { + bool result = false; + status = 0; + dataField.releaseBuffer(); + + this->response = response; + + if (response.getLength() >= 2) + { + sw[0] = response.getReverseAt(1); + sw[1] = response.getReverseAt(0); + + status = parseStatusWord(sw); + + if (response.getLength() > 2) + { + dataField.setBuffer(response.getBuffer(), response.getLength() - 2); + } + + result = true; + } + + return result; + } + + int ResponseHelper::parseStatusWord(unsigned char *sw) + { + int result = 0; + + switch (sw[0]) + { + /* Normal processing */ + case (unsigned char)0x90 : /* SW2:00, No further qulification */ + break; + + case (unsigned char)0x91 : /* extra information */ + break; + + case (unsigned char)0x61 : /* SW2 encodes the number of data bytes still available */ + break; + + /* Warning processing */ + case (unsigned char)0x62 : /* State of non-volatile memory is unchanged (further qualification in SW2) */ + break; + + case (unsigned char)0x63 : /* State of non-volatile memory has changed (further qualification in SW2) */ + break; + + /* Execution error */ + case (unsigned char)0x64 : /* State of non-volatile memory is unchanged (further qualification in SW2) */ + result = -1; + break; + + case (unsigned char)0x65 : /* State of non-volatile memory has changed (further qualification in SW2) */ + result = -1; + break; + + case (unsigned char)0x66 : /* Security-related issues */ + result = -1; + break; + + /* Checking error */ + case (unsigned char)0x67 : /* SW2:00, Wrong length; no further indication */ + result = -1; + break; + + case (unsigned char)0x68 : /* Functions in CLA not supported (further qualification in SW2) */ + result = -1; + break; + + case (unsigned char)0x69 : /* Command not allowed (further qualification in SW2) */ + result = -1; + break; + + case (unsigned char)0x6A : /* Wrong parameters P1-P2 (further qualification in SW2) */ + result = -1; + break; + + case (unsigned char)0x6B : /* SW2:00, Wrong parameters P1-P2 */ + result = -1; + break; + + case (unsigned char)0x6C : /* Wrong Le field; SW2 encodes the exact number of available data bytes */ + result = -1; + break; + + case (unsigned char)0x6D : /* SW2:00, Instruction code not supported or invalid */ + result = -1; + break; + + case (unsigned char)0x6E : /* SW2:00, Class not supported */ + result = -1; + break; + + case (unsigned char)0x6F : /* SW2:00, No precise diagnosis */ + result = -1; + break; + + default : + result = -1; + break; + } + + return result; + } + + int ResponseHelper::getStatus() + { + return status; + } + + int ResponseHelper::getStatus(const ByteArray &response) + { + int status = 0; + + if (response.getLength() >= 2) + { + status = ResponseHelper::parseStatusWord(response.getBuffer((response.getLength() - 2))); + } + + return status; + } + + ByteArray ResponseHelper::getDataField() + { + return dataField; + } + + ByteArray ResponseHelper::getDataField(const ByteArray &response) + { + ByteArray result; + + if (response.getLength() > 2) + { + result.setBuffer(response.getBuffer(), response.getLength() - 2); + } + + return result; + } + + /* APDUCommand class */ + APDUCommand::APDUCommand() + { + maxResponseSize = 0; + isExtendedLength = false; + memset(&header, 0, sizeof(header)); + } + + APDUCommand::~APDUCommand() + { + } + + bool APDUCommand::setCommand(unsigned char cla, unsigned char ins, unsigned char p1, unsigned char p2, ByteArray commandData, unsigned int maxResponseSize) + { + setCLA(cla); + setINS(ins); + setP1(p1); + setP2(p2); + setCommandData(commandData); + setMaxResponseSize(maxResponseSize); + + return true; + } + + bool APDUCommand::setCommand(const ByteArray &command) + { + bool result = false; + uint32_t offset = 0; + uint32_t lengthSize = 1; + + if (command.getLength() < sizeof(header)) + { + return false; + } + + memcpy(&header, command.getBuffer(offset), sizeof(header)); + offset += sizeof(header); + + if (isExtendedLength) + { + lengthSize = 2; + } + + if (command.getLength() - offset > lengthSize) + { + unsigned int length = 0; + + /* data exist */ + if (isExtendedLength) + { + /* TODO */ + offset += 2; + } + else + { + length = command.getAt(offset); + offset += 1; + } + + setCommandData(ByteArray(command.getBuffer(offset), length)); + offset += length; + } + + if (command.getLength() - offset == lengthSize) + { + if (isExtendedLength) + { + /* TODO */ + offset += 2; + } + else + { + setMaxResponseSize(command.getAt(offset)); + offset += 1; + } + } + + if (command.getLength() == offset) + { + result = true; + } + else + { + SCARD_DEBUG_ERR("command stream is not correct, command.getLength() [%d], offset [%d]", command.getLength(), offset); + } + + return result; + } + + bool APDUCommand::setChannel(int type, int channelNum) + { + bool result = false; + + if (channelNum != 0) + { + switch (type) + { + case 0 : + if (channelNum > 0 && channelNum < 4) + { + unsigned char temp; + + temp = getCLA(); + temp &= ~0x03; + temp |= (channelNum & 0x03); + setCLA(temp); + + result = true; + } + break; + + default : + break; + } + } + + return result; + } + + void APDUCommand::setCLA(unsigned char cla) + { + /* check criteria */ + if (cla == 0xFF) + return; + + header.cla = cla; + } + + unsigned char APDUCommand::getCLA() + { + return header.cla; + } + + void APDUCommand::setINS(unsigned char ins) + { + /* check criteria */ + if ((ins & 0xF0) == 0x60 || (ins & 0xF0) == 0x90) + return; + + header.ins = ins; + } + + unsigned char APDUCommand::getINS() + { + return header.ins; + } + + void APDUCommand::setP1(unsigned char p1) + { + /* check criteria */ + header.param[0] = p1; + } + + unsigned char APDUCommand::getP1() + { + return header.param[0]; + } + + void APDUCommand::setP2(unsigned char p2) + { + /* check criteria */ + header.param[1] = p2; + } + + unsigned char APDUCommand::getP2() + { + return header.param[1]; + } + + void APDUCommand::setCommandData(const ByteArray &data) + { + commandData = data; + } + + ByteArray APDUCommand::getCommandData() + { + return commandData; + } + + void APDUCommand::setMaxResponseSize(unsigned int maxResponseSize) + { + this->maxResponseSize = maxResponseSize; + } + + unsigned int APDUCommand::setMaxResponseSize() + { + return maxResponseSize; + } + + bool APDUCommand::getBuffer(ByteArray &array) + { + unsigned char *temp_buffer = NULL; + unsigned int temp_len = 0; + unsigned char lc[3] = { 0, }; + unsigned int lc_len = 0; + unsigned char le[3] = { 0, }; + unsigned int le_len = 0; + unsigned int offset = 0; + + /* */ + temp_len += sizeof(header); + + /* calculate lc length */ + if (commandData.getLength() > 0) + { + if (isExtendedLength/*commandData.getLength() > 255*/) + { + lc[1] = (commandData.getLength() >> 8) & 0x000000FF; + lc[2] = commandData.getLength() & 0x000000FF; + + lc_len = 3; + } + else + { + lc[0] = commandData.getLength() & 0x000000FF; + + lc_len = 1; + } + } + + temp_len += lc_len; + + /* add command data length */ + temp_len += commandData.getLength(); + + /* calculate le length */ + if (maxResponseSize > 0) + { + if (isExtendedLength/*commandData.getLength() > 255*/) + { + if (maxResponseSize < 65536) + { + le[1] = (maxResponseSize >> 8) & 0x000000FF; + le[2] = maxResponseSize & 0x000000FF; + + le_len = 3; + } + else if (maxResponseSize == 65536) + { + le_len = 2; + } + } + else + { + if (maxResponseSize != 256) + le[0] = maxResponseSize & 0x000000FF; + + le_len = 1; + } + } + + temp_len += le_len; + + temp_buffer = new unsigned char[temp_len]; + if (temp_buffer == NULL) + return false; + + /* fill data */ + offset = 0; + + memcpy(temp_buffer + offset, &header, sizeof(header)); + offset += sizeof(header); + + if (commandData.getLength() > 0) + { + memcpy(temp_buffer + offset, &lc, lc_len); + offset += lc_len; + + memcpy(temp_buffer + offset, commandData.getBuffer(), commandData.getLength()); + offset += commandData.getLength(); + } + + if (maxResponseSize > 0) + { + memcpy(temp_buffer + offset, &le, le_len); + offset += le_len; + } + + array.setBuffer(temp_buffer, temp_len); + delete []temp_buffer; + + return true; + } + + /* APDUHelper class */ + ByteArray APDUHelper::generateAPDU(int command, int channel, ByteArray data) + { + ByteArray result; + APDUCommand apdu; + + switch (command) + { + case COMMAND_OPEN_LOGICAL_CHANNEL : + apdu.setCommand(0, APDUCommand::INS_MANAGE_CHANNEL, 0, 0, ByteArray::EMPTY, 1); + apdu.getBuffer(result); + break; + + case COMMAND_CLOSE_LOGICAL_CHANNEL : + apdu.setCommand(0, APDUCommand::INS_MANAGE_CHANNEL, 0x80, channel, ByteArray::EMPTY, 0); + apdu.getBuffer(result); + break; + + case COMMAND_SELECT_BY_ID : + apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_ID, APDUCommand::P2_SELECT_GET_FCP, data, 0); + apdu.getBuffer(result); + break; + + case COMMAND_SELECT_PARENT_DF : + apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_PARENT_DF, APDUCommand::P2_SELECT_GET_FCP, data, 0); + apdu.getBuffer(result); + break; + + case COMMAND_SELECT_BY_DF_NAME : + apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_DF_NAME, APDUCommand::P2_SELECT_GET_FCP, data, 0); + apdu.getBuffer(result); + break; + + case COMMAND_SELECT_BY_PATH : + apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_PATH, APDUCommand::P2_SELECT_GET_FCP, data, 0); + apdu.getBuffer(result); + break; + + case COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF : + apdu.setCommand(0, APDUCommand::INS_SELECT_FILE, APDUCommand::P1_SELECT_BY_PATH_FROM_CURRENT_DF, APDUCommand::P2_SELECT_GET_FCP, data, 0); + apdu.getBuffer(result); + break; + + default : + break; + } + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/common/AccessCondition.cpp b/common/AccessCondition.cpp new file mode 100644 index 0000000..b6e2c4f --- /dev/null +++ b/common/AccessCondition.cpp @@ -0,0 +1,276 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "SimpleTLV.h" +#include "AccessCondition.h" + +namespace smartcard_service_api +{ + void APDUAccessRule::loadAPDUAccessRule(const ByteArray &data) + { + SimpleTLV tlv(data); + + if (tlv.decodeTLV() == true) + { + switch (tlv.getTag()) + { + case 0xA0 : /* CHOICE 0 : APDUPermission */ + permission = SimpleTLV::getBoolean(tlv.getValue()); + break; + + case 0xA1 : /* CHOICE 1 : APDUFilters */ + tlv.enterToValueTLV(); + while (tlv.decodeTLV() == true) + { + if (tlv.getTag() == 0x04) /* OCTET STRING */ + { + ByteArray apdu, mask, value; + + value = tlv.getValue(); + + SCARD_DEBUG("APDU rule : %s", value.toString()); + + if (value.getLength() == 8) /* apdu 4 bytes + mask 4 bytes */ + { + apdu.setBuffer(value.getBuffer(), 4); + mask.setBuffer(value.getBuffer(4), 4); + + pair newItem(apdu, mask); + + mapApduFilters.insert(newItem); + } + else + { + SCARD_DEBUG_ERR("Invalid APDU rule : %s", value.toString()); + } + } + else + { + SCARD_DEBUG_ERR("Unknown tag : 0x%02X", tlv.getTag()); + } + } + tlv.returnToParentTLV(); + break; + + default : + SCARD_DEBUG_ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + } + + bool APDUAccessRule::isAuthorizedAccess(const ByteArray &command) + { + bool result = false; + + if (mapApduFilters.size() > 0) + { + /* TODO : search command and check validity */ + } + else + { + /* no filter entry. if permission is true, all access will be granted, if not, all access will be denied */ + result = permission; + } + + return result; + } + + void APDUAccessRule::printAPDUAccessRules() + { + SCARD_DEBUG(" +-- APDU Access Rule"); + + if (mapApduFilters.size() > 0) + { + map::iterator iterMap; + + for (iterMap = mapApduFilters.begin(); iterMap != mapApduFilters.end(); iterMap++) + { + SCARD_DEBUG(" +--- APDU : %s, Mask : %s", ((ByteArray)(iterMap->first)).toString(), iterMap->second.toString()); + } + } + else + { + SCARD_DEBUG(" +--- permission : %s", permission ? "granted all" : "denied all"); + } + } + + void NFCAccessRule::loadNFCAccessRule(const ByteArray &data) + { + permission = SimpleTLV::getBoolean(data); + } + + bool NFCAccessRule::isAuthorizedAccess(void) + { + bool result = false; + + result = permission; + + return result; + } + + void NFCAccessRule::printNFCAccessRules() + { + SCARD_DEBUG(" +-- NFC Access Rule"); + SCARD_DEBUG(" +--- permission : %s", permission ? "granted all" : "denied all"); + } + + void AccessCondition::loadAccessCondition(ByteArray &aid, ByteArray &data) + { + if (data.getLength() > 0) + { + SimpleTLV tlv(data); + + while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */ + { + if (tlv.getLength() > 0) + { + /* access granted for specific applications */ + tlv.enterToValueTLV(); + if (tlv.decodeTLV()) + { + switch (tlv.getTag()) + { + case 0x04 : /* OCTET STRING : CertHash */ + SCARD_DEBUG("aid : %s, hash : %s", aid.toString(), tlv.getValue().toString()); + + hashes.push_back(tlv.getValue()); + break; + + case 0xA0 : /* CHOICE 0 : AccessRules */ + tlv.enterToValueTLV(); + if (tlv.decodeTLV()) + { + switch (tlv.getTag()) + { + case 0xA0 : /* CHOICE 0 : APDUAccessRule */ + apduRule.loadAPDUAccessRule(tlv.getValue()); + break; + + case 0xA1 : /* CHOICE 1 : NFCAccessRule */ + nfcRule.loadNFCAccessRule(tlv.getValue()); + break; + + default : + SCARD_DEBUG_ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + else + { + SCARD_DEBUG_ERR("tlv.decodeTLV failed"); + } + tlv.returnToParentTLV(); + break; + + default : + SCARD_DEBUG_ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + else + { + SCARD_DEBUG_ERR("tlv.decodeTLV failed"); + } + tlv.returnToParentTLV(); + } + else + { + SCARD_DEBUG("access granted for all applications, aid : %s", aid.toString()); + + permission = true; + break; + } + } + } + else + { + SCARD_DEBUG("access denied for all applications, aid : %s", aid.toString()); + + permission = false; + } + } + + bool AccessCondition::isAuthorizedAccess(ByteArray &certHash) + { + bool result = false; + + if (hashes.size() > 0) + { + size_t i; + + for (i = 0; i < hashes.size(); i++) + { + if (certHash == hashes[i]) + { + result = true; + break; + } + } + } + else + { + result = permission; + } + + return result; + } + + bool AccessCondition::isAuthorizedAPDUAccess(ByteArray &command) + { + bool result = false; + + result = apduRule.isAuthorizedAccess(command); + + return result; + } + + bool AccessCondition::isAuthorizedNFCAccess() + { + bool result = false; + + result = nfcRule.isAuthorizedAccess(); + + return result; + } + + void AccessCondition::printAccessConditions() + { + SCARD_DEBUG(" +-- Access Condition"); + + if (hashes.size() > 0) + { + size_t i; + + for (i = 0; i < hashes.size(); i++) + { + SCARD_DEBUG(" +--- hash : %s", hashes[i].toString()); + } + } + else + { + SCARD_DEBUG(" +--- permission : %s", permission ? "granted all" : "denied all"); + } + } +} /* namespace smartcard_service_api */ diff --git a/common/AccessControlList.cpp b/common/AccessControlList.cpp new file mode 100644 index 0000000..6cd2540 --- /dev/null +++ b/common/AccessControlList.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "AccessControlList.h" +#include "PKCS15.h" +#include "AccessCondition.h" + +namespace smartcard_service_api +{ + const unsigned char aid_all[] = { 0x00, 0x00 }; + const unsigned char aid_default[] = { 0x00, 0x01 }; + + ByteArray AccessControlList::AID_ALL(ARRAY_AND_SIZE(aid_all)); + ByteArray AccessControlList::AID_DEFAULT(ARRAY_AND_SIZE(aid_default)); + + AccessControlList::AccessControlList() + { + channel = NULL; + terminal = NULL; + } + + AccessControlList::AccessControlList(Channel *channel) + { + channel = NULL; + terminal = NULL; + + setChannel(channel); + } + + AccessControlList::AccessControlList(Terminal *terminal) + { + channel = NULL; + terminal = NULL; + + setTerminal(terminal); + } + + AccessControlList::~AccessControlList() + { + releaseACL(); + + if (terminal != NULL && channel != NULL) + { + delete channel; + } + } + + int AccessControlList::setChannel(Channel *channel) + { + this->channel = channel; + + return 0; + } + + int AccessControlList::updateACL() + { + releaseACL(); + + return loadACL(); + } + + void AccessControlList::releaseACL() + { + mapConditions.clear(); + } + + bool AccessControlList::isAuthorizedAccess(ByteArray aid, ByteArray certHash) + { + bool result = false; + map::iterator iterMap; + + SCARD_DEBUG("aid : %s", aid.toString()); + SCARD_DEBUG("hash : %s", certHash.toString()); + + /* null aid means default applet */ + if (aid.isEmpty() == true) + { + aid = AID_DEFAULT; + } + + /* first.. find hashes matched with aid */ + if ((iterMap = mapConditions.find(aid)) != mapConditions.end()) + { + result = iterMap->second.isAuthorizedAccess(certHash); + } + /* finally.. find hashes in 'all' list */ + else if ((iterMap = mapConditions.find(AID_ALL)) != mapConditions.end()) + { + result = iterMap->second.isAuthorizedAccess(certHash); + } + + return result; + } + + bool AccessControlList::isAuthorizedAccess(unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength) + { + return isAuthorizedAccess(ByteArray(aidBuffer, aidLength), ByteArray(certHashBuffer, certHashLength)); + } + + void AccessControlList::printAccessControlList() + { + ByteArray temp; + + /* release map and vector */ + map::iterator iterMap; + + SCARD_DEBUG("================ Certification Hashes =================="); + for (iterMap = mapConditions.begin(); iterMap != mapConditions.end(); iterMap++) + { + temp = iterMap->first; + + SCARD_DEBUG("+ aid : %s", (temp == AID_DEFAULT) ? "DEFAULT" : (temp == AID_ALL) ? "ALL" : temp.toString()); + + iterMap->second.printAccessConditions(); + } + SCARD_DEBUG("========================================================"); + } + +} /* namespace smartcard_service_api */ diff --git a/common/ByteArray.cpp b/common/ByteArray.cpp new file mode 100644 index 0000000..ee2acf0 --- /dev/null +++ b/common/ByteArray.cpp @@ -0,0 +1,323 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ByteArray.h" + +namespace smartcard_service_api +{ + ByteArray ByteArray::EMPTY = ByteArray(); + + ByteArray::ByteArray() + { + buffer = NULL; + length = 0; + } + + ByteArray::ByteArray(uint8_t *array, uint32_t bufferLen) + { + buffer = NULL; + length = 0; + + setBuffer(array, bufferLen); + } + + ByteArray::ByteArray(const ByteArray &T) + { + buffer = NULL; + length = 0; + + setBuffer(T.buffer, T.length); + } + + ByteArray::~ByteArray() + { + releaseBuffer(); + } + + bool ByteArray::setBuffer(uint8_t *array, uint32_t bufferLen) + { + if (array == NULL || bufferLen == 0) + { + return false; + } + + releaseBuffer(); + + buffer = new uint8_t[bufferLen]; + if (buffer == NULL) + { + SCARD_DEBUG_ERR("alloc failed"); + return false; + } + + memcpy(buffer, array, bufferLen); + length = bufferLen; + + return true; + } + + bool ByteArray::_setBuffer(uint8_t *array, uint32_t bufferLen) + { + if (array == NULL || bufferLen == 0) + { + return false; + } + + releaseBuffer(); + + buffer = array; + length = bufferLen; + + return true; + } + + uint32_t ByteArray::getLength() const + { + return length; + } + + uint8_t *ByteArray::getBuffer() const + { + return getBuffer(0); + } + + uint8_t *ByteArray::getBuffer(uint32_t offset) const + { + if (length == 0) + return NULL; + + if (offset >= length) + { + SCARD_DEBUG_ERR("buffer overflow, offset [%d], length [%d]", offset, length); + return NULL; + } + + return buffer + offset; + } + + uint8_t ByteArray::getAt(uint32_t index) const + { + if (index >= length) + { + SCARD_DEBUG_ERR("buffer overflow, index [%d], length [%d]", index, length); + return buffer[length -1]; + } + + return buffer[index]; + } + + uint8_t ByteArray::getReverseAt(uint32_t index) const + { + if (index >= length) + { + SCARD_DEBUG_ERR("buffer underflow, index [%d], length [%d]", index, length); + return buffer[0]; + } + + return buffer[length - index - 1]; + } + + uint32_t ByteArray::copyFromArray(uint8_t *array, uint32_t bufferLen) const + { + uint32_t min_len = 0; + + if (array == NULL || bufferLen == 0) + { + SCARD_DEBUG_ERR("invaild param"); + return false; + } + + min_len = (bufferLen < length) ? bufferLen : length; + + memcpy(array, buffer, min_len); + + return min_len; + } + + void ByteArray::releaseBuffer() + { + if (buffer != NULL) + { + delete []buffer; + buffer = NULL; + } + length = 0; + } + + /* operator overloading */ + ByteArray ByteArray::operator +(const ByteArray &T) + { + uint32_t newLen; + uint8_t *newBuffer; + ByteArray newArray; + + if (length == 0) + { + SCARD_DEBUG("length is zero"); + + return T; + } + + newLen = T.length; + + if (newLen == 0) + return *this; + + newLen += length; + + newBuffer = new uint8_t[newLen]; + if (newBuffer == NULL) + { + /* assert.... */ + SCARD_DEBUG_ERR("alloc failed"); + + return *this; + } + + memcpy(newBuffer, buffer, length); + memcpy(newBuffer + length, T.buffer, T.length); + + newArray._setBuffer(newBuffer, newLen); + + return newArray; + } + + ByteArray &ByteArray::operator =(const ByteArray &T) + { + if (this != &T) + { + setBuffer(T.buffer, T.length); + } + + return *this; + } + + ByteArray &ByteArray::operator +=(const ByteArray &T) + { + *this = *this + T; + + return *this; + } + + bool ByteArray::operator ==(const ByteArray &T) const + { + if (length != T.length) + return false; + + return (memcmp(buffer, T.buffer, length) == 0); + } + + bool ByteArray::operator !=(const ByteArray &T) const + { + return !(*this == T); + } + + bool ByteArray::operator <(const ByteArray &T) const + { + return (memcmp(buffer, T.buffer, (length < T.length) ? length : T.length) < 0); + } + + bool ByteArray::operator >(const ByteArray &T) const + { + return (memcmp(buffer, T.buffer, (length < T.length) ? length : T.length) > 0); + } + + uint8_t &ByteArray::operator [](uint32_t index) const + { + if (index >= length) + { + SCARD_DEBUG_ERR("buffer overflow, index [%d], length [%d]", index, length); + return buffer[length -1]; + } + + return buffer[index]; + } + + const char *ByteArray::toString() + { + memset(strBuffer, 0, sizeof(strBuffer)); + + if (length == 0) + { + snprintf(strBuffer, sizeof(strBuffer), "buffer is empty"); + } + else + { + int count; + int i, offset = 0; + bool ellipsis = false; + + count = length; + if (count > 20) + { + count = 20; + ellipsis = true; + } + + snprintf(strBuffer + offset, sizeof(strBuffer) - offset, "{ "); + offset += 2; + + for (i = 0; i < count; i++) + { + snprintf(strBuffer + offset, sizeof(strBuffer) - offset, "%02X ", buffer[i]); + offset += 3; + } + + if (ellipsis) + { + snprintf(strBuffer + offset, sizeof(strBuffer) - offset, "... }"); + } + else + { + snprintf(strBuffer + offset, sizeof(strBuffer) - offset, "}"); + } + } + + return (const char *)strBuffer; + } + + void ByteArray::save(const char *filePath) + { + FILE *file = NULL; + + if (filePath == NULL || buffer == NULL || length == 0) + return; + + if ((file = fopen(filePath, "w")) != NULL) + { + fwrite(buffer, 1, length, file); + fflush(file); + + fclose(file); + SCARD_DEBUG("file has written, file [%s], length[%d]", filePath, length); + } + else + { + SCARD_DEBUG_ERR("file open failed, [%d]", errno); + } + } + +} /* namespace smartcard_service_api */ + diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000..a32d420 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,84 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(smartcard-service-common CXX) + +SET(LIB_NAME "smartcard-service-common") +SET(VERSION_MAJOR 1) +SET(VERSION ${VERSION_MAJOR}.0.0) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SRCS) + +#IF("${CMAKE_BUILD_TYPE}" STREQUAL "") +# SET(CMAKE_BUILD_TYPE "Debug") +#ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +#MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs_common REQUIRED dlog glib-2.0 gthread-2.0 dpl-wrt-dao-ro aul libssl) + +MESSAGE("${LIB_NAME} ld flag : ${pkgs_common_LDFLAGS}") + +FOREACH(flag ${pkgs_common_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +FOREACH(flag ${pkgs_common_CFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -finstrument-functions") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +#SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +#SET(CMAKE_C_FLAGS_RELEASE "-O2") + +#SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} -finstrument-functions") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") +#SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +#SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +MESSAGE("CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DSLP_DEBUG") +ADD_DEFINITIONS("-DUSE_UNIX_DOMAIN") + +ADD_DEFINITIONS("-DLOG_TAG=\"SCARD_COMMON\"") + +# Temporary add ############# +ADD_DEFINITIONS("-std=c++0x") +############################# + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) + +SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES VERSION ${VERSION}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_common_LDFLAGS}) + +SET(EXPORT_HEADER + include/Debug.h + include/ByteArray.h + include/Lock.h + include/Synchronous.h + include/TerminalInterface.h + include/Terminal.h + include/SignatureHelper.h + include/GPSEACL.h +) + +#CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${LIB_NAME}.pc DESTINATION lib/pkgconfig) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib) +FOREACH(hfile ${EXPORT_HEADER}) + INSTALL(FILES ${hfile} DESTINATION include/${LIB_NAME}) +ENDFOREACH(hfile) diff --git a/common/DispatcherHelper.cpp b/common/DispatcherHelper.cpp new file mode 100644 index 0000000..8c955f2 --- /dev/null +++ b/common/DispatcherHelper.cpp @@ -0,0 +1,138 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "DispatcherHelper.h" + +namespace smartcard_service_api +{ + DispatcherHelper::DispatcherHelper() + { + dispatcherThread = 0; + } + + DispatcherHelper::~DispatcherHelper() + { + stopDispatcherThread(); + } + + DispatcherMsg *DispatcherHelper::fetchMessage() + { + DispatcherMsg *result = NULL; + + if (messageQ.size() > 0) + { + result = messageQ.front(); + messageQ.pop(); + } + + return result; + } + + void DispatcherHelper::clearQueue() + { + DispatcherMsg *temp = NULL; + + while (messageQ.size() > 0) + { + temp = fetchMessage(); + delete temp; + } + } + + void DispatcherHelper::pushMessage(DispatcherMsg *msg) + { + syncLock(); + + messageQ.push(msg); + + signalCondition(); + syncUnlock(); + } + + void *DispatcherHelper::_dispatcherThreadFunc(void *data) + { + DispatcherMsg *msg = NULL; + DispatcherHelper *helper = (DispatcherHelper *)data; + + while (1) + { + helper->syncLock(); + if ((msg = helper->fetchMessage()) == NULL) + { + helper->waitTimedCondition(0); + helper->syncUnlock(); + continue; + } + helper->syncUnlock(); + + /* process message */ + helper->dispatcherThreadFunc(msg, data); + + delete msg; + } + + return (void *)NULL; + } + + bool DispatcherHelper::runDispatcherThread() + { + bool result = false; + pthread_attr_t attr; + + if (dispatcherThread == 0) + { + int ret; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if ((ret = pthread_create(&dispatcherThread, &attr, &DispatcherHelper::_dispatcherThreadFunc, this)) != 0) + { + SCARD_DEBUG_ERR("pthread_create failed [%d]", ret); + } + else + { + SCARD_DEBUG("pthread_create success"); + result = true; + } + } + else + { + SCARD_DEBUG("thread already start"); + result = true; + } + + return result; + } + + void DispatcherHelper::stopDispatcherThread() + { + if (dispatcherThread != 0) + { + pthread_cancel(dispatcherThread); + dispatcherThread = 0; + } + } + +} /* namespace smartcard_service_api */ diff --git a/common/FCI.cpp b/common/FCI.cpp new file mode 100644 index 0000000..5093f2c --- /dev/null +++ b/common/FCI.cpp @@ -0,0 +1,381 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "FCI.h" +#include "SimpleTLV.h" +//#include "ISO7816BERTLV.h" +#include "NumberStream.h" + +namespace smartcard_service_api +{ + /* FCP class method */ + FCP::FCP() + { + resetMemberVar(); + } + + FCP::FCP(ByteArray &array) + { + resetMemberVar(); + + setFCP(array); + } + + FCP::~FCP() + { + } + + void FCP::resetMemberVar() + { + fileSize = FCI::INFO_NOT_AVAILABLE; + totalFileSize = FCI::INFO_NOT_AVAILABLE; + fid = FCI::INFO_NOT_AVAILABLE; + sfi = FCI::INFO_NOT_AVAILABLE; + maxRecordSize = FCI::INFO_NOT_AVAILABLE; + numberOfRecord = FCI::INFO_NOT_AVAILABLE; + fileType = FCI::INFO_NOT_AVAILABLE; + fileStructure = FCI::INFO_NOT_AVAILABLE; + lcs = FCI::INFO_NOT_AVAILABLE; + } + + bool FCP::setFCP(ByteArray array) + { + bool result = false; + SimpleTLV tlv; + + SCARD_BEGIN(); + + releaseFCP(); + + if (array.getLength() == 0) + return false; + + fcpBuffer = array; + + if (fcpBuffer[0] != 0x62) + { + SCARD_DEBUG_ERR("it is not FCP response [%02X]", fcpBuffer[0]); + return false; + } + + /* parse... */ + tlv.setTLVBuffer(fcpBuffer.getBuffer(), fcpBuffer.getLength()); + + if (tlv.decodeTLV()) + { + tlv.enterToValueTLV(); + + while (tlv.decodeTLV()) + { + switch (tlv.getTag()) + { + case 0x80 : /* file length without sturctural inforamtion */ + { + SCARD_DEBUG("0x%02X : file length without sturctural inforamtion : %s", tlv.getTag(), tlv.getValue().toString()); + if (tlv.getLength() > 0) + { + fileSize = NumberStream::getBigEndianNumber(tlv.getValue()); + } + } + break; + + case 0x81 : /* file length with sturctural inforamtion */ + { + SCARD_DEBUG("0x%02X : file length with sturctural inforamtion : %s", tlv.getTag(), tlv.getValue().toString()); + if (tlv.getLength() > 0) + { + maxRecordSize = NumberStream::getBigEndianNumber(tlv.getValue()); + } + } + break; + + case 0x82 : /* file descriptor bytes */ + { + SCARD_DEBUG("0x%02X : file descriptor bytes : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x83 : /* file identifier */ + { + SCARD_DEBUG("0x%02X : file identifier : %s", tlv.getTag(), tlv.getValue().toString()); + if (tlv.getLength() > 0) + { + ByteArray value = tlv.getValue(); + + fid = 0; + + memcpy(&fid, value.getBuffer(), value.getLength()); + } + } + break; + + case 0x84 : /* DF name */ + { + SCARD_DEBUG("0x%02X : DF name : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x85 : /* proprietary information not encoded in BER-TLV */ + { + SCARD_DEBUG("0x%02X : proprietary information not encoded in BER-TLV : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x86 : /* Security attribute in proprietary format */ + { + SCARD_DEBUG("0x%02X : Security attribute in proprietary format : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x87 : /* Identifier of an EF containing an extension of the file control information */ + { + SCARD_DEBUG("0x%02X : Identifier of an EF containing an extension of the file control information : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x88 : /* Short EF identifier */ + { + SCARD_DEBUG("0x%02X : Short EF identifier : %s", tlv.getTag(), tlv.getValue().toString()); + + if (tlv.getLength() > 0) + { + ByteArray value = tlv.getValue(); + + sfi = 0; + + memcpy(&sfi, value.getBuffer(), value.getLength()); + } + } + break; + + case 0x8A : /* life cycle status byte */ + { + SCARD_DEBUG("0x%02X : life cycle status byte : %s", tlv.getTag(), tlv.getValue().toString()); + if (tlv.getLength() > 0) + { + ByteArray value = tlv.getValue(); + + lcs = 0; + + memcpy(&lcs, value.getBuffer(), value.getLength()); + } + } + break; + + case 0x8B : /* Security attribute referencing the expanded format */ + { + SCARD_DEBUG("0x%02X : Security attribute referencing the expanded format : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x8C : /* Security attribute in compact format */ + { + SCARD_DEBUG("0x%02X : Security attribute in compact format : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x8D : /* Identifier of an EF containing security environment templates */ + { + SCARD_DEBUG("0x%02X : Identifier of an EF containing security environment templates : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0x8E : /* Channel security attribute */ + { + SCARD_DEBUG("0x%02X : Channel security attribute : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xA0 : /* Security attribute template for data objects */ + { + SCARD_DEBUG("0x%02X : Security attribute template for data objects : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xA1 : /* Security attribute template in proprietary format */ + { + SCARD_DEBUG("0x%02X : Security attribute template in proprietary format : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xA2 : /* Template consisting of one or more pairs of data objects */ + { + SCARD_DEBUG("0x%02X : Template consisting of one or more pairs of data objects : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xA5 : /* proprietary information encoded in BER-TLV */ + { + SCARD_DEBUG("0x%02X : proprietary information encoded in BER-TLV : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xAB : /* Security attribute template in expanded format */ + { + SCARD_DEBUG("0x%02X : Security attribute template in expanded format : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xAC : /* Cryptographic mechanism identifier template */ + { + SCARD_DEBUG("0x%02X : Cryptographic mechanism identifier template : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + case 0xC6 : /* PIN status template DO */ + { + SCARD_DEBUG("0x%02X : PIN status template DO : %s", tlv.getTag(), tlv.getValue().toString()); + // ByteArray value = tlv.getValue(); + } + break; + + default : + { + SCARD_DEBUG("0x%02X : unknown : %s", tlv.getTag(), tlv.getValue().toString()); + } + break; + } + } + tlv.returnToParentTLV(); + } + else + { + SCARD_DEBUG_ERR("tlv.decodeTLV failed"); + } + + SCARD_END(); + + return result; + } + + ByteArray FCP::getFCP() + { + return fcpBuffer; + } + + void FCP::releaseFCP() + { + fcpBuffer.releaseBuffer(); + + resetMemberVar(); + } + + unsigned int FCP::getFileSize() + { + return fileSize; + } + + unsigned int FCP::getTotalFileSize() + { + return totalFileSize; + } + + unsigned int FCP::getFID() + { + return fid; + } + + unsigned int FCP::getSFI() + { + return sfi; + } + + unsigned int FCP::getMaxRecordSize() + { + return maxRecordSize; + } + + unsigned int FCP::getNumberOfRecord() + { + return numberOfRecord; + } + + unsigned int FCP::getFileType() + { + return fileType; + } + + unsigned int FCP::getFileStructure() + { + return fileStructure; + } + + unsigned int FCP::getLCS() + { + return lcs; + } + + const char *FCP::toString() + { + memset(strBuffer, 0, sizeof(strBuffer)); + + snprintf(strBuffer, sizeof(strBuffer), "size [%d], total size [%d], fid [%x], sfi [%x], max rec [%d], n of rec [%d], type [%d], struct [%d], lcs [%d]", + getFileSize(), getTotalFileSize(), getFID(), getSFI(), getMaxRecordSize(), getNumberOfRecord(), getFileType(), getFileStructure(), getLCS()); + + return (const char *)strBuffer; + } + + + /* FCM class method */ + FCM::FCM() + { + } + + FCM::~FCM() + { + } + + + /* FCI class method */ + FCI::FCI() + { + } + + FCI::~FCI() + { + } + + bool FCI::setFCIBuffer(ByteArray array) + { + bool result = false; + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/common/FileObject.cpp b/common/FileObject.cpp new file mode 100644 index 0000000..204808b --- /dev/null +++ b/common/FileObject.cpp @@ -0,0 +1,402 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "FileObject.h" +#include "APDUHelper.h" + +namespace smartcard_service_api +{ + FileObject::FileObject(Channel *channel):ProviderHelper(channel) + { + } + + FileObject::FileObject(Channel *channel, ByteArray selectResponse):ProviderHelper(channel) + { + setSelectResponse(selectResponse); + } + + FileObject::~FileObject() + { + } + + bool FileObject::setSelectResponse(ByteArray response) + { + bool result = false; + + selectResponse = response; + + if (selectResponse.getLength() > 2) + { + ResponseHelper resp(selectResponse); + + fcp.setFCP(resp.getDataField()); + + result = true; + } + else + { + SCARD_DEBUG_ERR("invalid response : %s", selectResponse.toString()); + } + + return result; + } + + int FileObject::select(ByteArray aid) + { + int ret = ERROR_ILLEGAL_STATE; + ByteArray command, result; + APDUHelper apdu; + + if (channel == NULL || channel->isClosed()) + { + SCARD_DEBUG_ERR("channel is not open"); + + return ret; + } + + /* make apdu command */ + command = apdu.generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, 0, aid); + SCARD_DEBUG("command : %s", command.toString()); + ret = channel->transmitSync(command, result); + + if (ret == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + this->selectResponse = result; + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", result.getLength(), result.toString()); + + fcp.releaseFCP(); + + if (result.getLength() > 2) + { + fcp.setFCP(resp.getDataField()); + + SCARD_DEBUG("FCP : %s", fcp.toString()); + } + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, result.getLength()); + } + + return ret; + } + + int FileObject::select(ByteArray path, bool fromCurrentDF) + { + int ret = ERROR_ILLEGAL_STATE; + ByteArray command, result; + APDUHelper apdu; + + if (channel == NULL || channel->isClosed()) + { + SCARD_DEBUG_ERR("channel is not open"); + + return ret; + } + + /* make apdu command */ + if (fromCurrentDF == true) + { + command = apdu.generateAPDU(APDUHelper::COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF, 0, path); + } + else + { + command = apdu.generateAPDU(APDUHelper::COMMAND_SELECT_BY_PATH, 0, path); + } + SCARD_DEBUG("command : %s", command.toString()); + + ret = channel->transmitSync(command, result); + + if (ret == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + this->selectResponse = result; + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", result.getLength(), result.toString()); + + fcp.releaseFCP(); + + if (result.getLength() > 2) + { + fcp.setFCP(resp.getDataField()); + + SCARD_DEBUG("FCP : %s", fcp.toString()); + } + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, result.getLength()); + } + + return ret; + } + + int FileObject::select(unsigned int fid) + { + int ret = ERROR_ILLEGAL_STATE; + ByteArray command, result, fidData((unsigned char *)&fid, 2); + + if (channel == NULL || channel->isClosed()) + { + SCARD_DEBUG_ERR("channel is not open"); + + return ret; + } + + /* make apdu command */ + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_ID, 0, fidData); + ret = channel->transmitSync(command, result); + + if (ret == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + this->selectResponse = result; + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", result.getLength(), result.toString()); + + fcp.releaseFCP(); + + if (result.getLength() > 2) + { + fcp.setFCP(resp.getDataField()); + + SCARD_DEBUG("FCP : %s", fcp.toString()); + } + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, result.getLength()); + } + + return ret; + } + + int FileObject::selectParent() + { + int ret = ERROR_ILLEGAL_STATE; + ByteArray command, result; + APDUHelper apdu; + + if (channel == NULL || channel->isClosed()) + { + SCARD_DEBUG_ERR("channel is not open"); + + return ret; + } + + /* make apdu command */ + command = apdu.generateAPDU(APDUHelper::COMMAND_SELECT_PARENT_DF, 0, ByteArray::EMPTY); + SCARD_DEBUG("command : %s", command.toString()); + + ret = channel->transmitSync(command, result); + + if (ret == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + this->selectResponse = result; + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", result.getLength(), result.toString()); + + fcp.releaseFCP(); + + if (result.getLength() > 2) + { + fcp.setFCP(resp.getDataField()); + + SCARD_DEBUG("FCP : %s", fcp.toString()); + } + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, result.getLength()); + } + + return ret; + } + + FCI *FileObject::getFCI() + { + return NULL; + } + + FCP *FileObject::getFCP() + { + return &fcp; + } + + int FileObject::readRecord(unsigned int sfi, unsigned int recordId, Record &result) + { + ByteArray command, response; + APDUCommand apdu; + int ret; + + apdu.setCommand(0, APDUCommand::INS_READ_RECORD, recordId, 4, ByteArray::EMPTY, 0); + apdu.getBuffer(command); + SCARD_DEBUG("command : %s", command.toString()); + + ret = channel->transmitSync(command, response); + if (ret == 0 && response.getLength() >= 2) + { + ResponseHelper resp(response); + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", response.getLength(), response.toString()); + +// result = resp.getDataField(); + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), response[response.getLength() - 2], response[response.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, response.getLength()); + } + + return ret; + } + + int FileObject::writeRecord(unsigned int sfi, Record record) + { + return 0; + } + + int FileObject::searchRecord(unsigned int sfi, ByteArray searchParam, vector &result) + { + return 0; + } + + int FileObject::readBinary(unsigned int sfi, unsigned int offset, unsigned int length, ByteArray &result) + { + ByteArray command, response; + APDUCommand apdu; + int ret; + + apdu.setCommand(0, APDUCommand::INS_READ_BINARY, offset, 0, ByteArray::EMPTY, length); + apdu.getBuffer(command); + SCARD_DEBUG("command : %s", command.toString()); + + ret = channel->transmitSync(command, response); + if (ret == 0 && response.getLength() >= 2) + { + ResponseHelper resp(response); + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", response.getLength(), response.toString()); + + result = resp.getDataField(); + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), response[response.getLength() - 2], response[response.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, response.getLength()); + } + + return ret; + } + + int FileObject::writeBinary(unsigned int sfi, ByteArray data, unsigned int offset, unsigned int length) + { + ByteArray command, response; + APDUCommand apdu; + int ret; + + apdu.setCommand(0, APDUCommand::INS_WRITE_BINARY, offset, 0, data, 0); + apdu.getBuffer(command); + SCARD_DEBUG("command : %s", command.toString()); + + ret = channel->transmitSync(command, response); + if (ret == 0 && response.getLength() >= 2) + { + ResponseHelper resp(response); + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("response [%d] : %s", response.getLength(), response.toString()); + + ret = SUCCESS; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), response[response.getLength() - 2], response[response.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", ret, response.getLength()); + } + + return ret; + } + +} /* namespace smartcard_service_api */ diff --git a/common/GPSEACL.cpp b/common/GPSEACL.cpp new file mode 100644 index 0000000..775d88e --- /dev/null +++ b/common/GPSEACL.cpp @@ -0,0 +1,318 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "GPSEACL.h" +#include "PKCS15ODF.h" +#include "PKCS15DODF.h" +#include "NumberStream.h" +#include "SimpleTLV.h" +#include "AccessCondition.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + static unsigned char oid_globalplatform[] = { 0x2A, 0x86, 0x48, 0x86, 0xFC, 0x6B, 0x81, 0x48, 0x01, 0x01 }; + ByteArray GPSEACL::OID_GLOBALPLATFORM(ARRAY_AND_SIZE(oid_globalplatform)); + + GPSEACL::GPSEACL(Channel *channel):AccessControlList(channel) + { + this->channel = channel; + + if (channel->getSelectResponse().isEmpty() == true) + { + pkcs15 = new PKCS15(channel); + } + else + { + pkcs15 = new PKCS15(channel, channel->getSelectResponse()); + } + } + + GPSEACL::~GPSEACL() + { + if (pkcs15 != NULL) + { + delete pkcs15; + } + } + + int GPSEACL::loadACL() + { + ByteArray aid, certHash; + PKCS15ODF *odf; + + if ((odf = pkcs15->getODF()) != NULL) + { + PKCS15DODF *dodf; + + if ((dodf = odf->getDODF()) != NULL) + { + loadAccessControl(dodf); + + printAccessControlList(); + } + else + { + SCARD_DEBUG_ERR("dodf null"); + } + } + else + { + SCARD_DEBUG_ERR("odf null"); + } + + return 0; + } + + int GPSEACL::loadAccessControl(PKCS15DODF *dodf) + { + ByteArray path; + + if (dodf->searchOID(OID_GLOBALPLATFORM, path) == 0) + { + ByteArray data; + FileObject file(channel); + + SCARD_DEBUG("oid path : %s", path.toString()); + + file.select(NumberStream::getLittleEndianNumber(path)); + file.readBinary(0, 0, file.getFCP()->getFileSize(), data); + + SCARD_DEBUG("data : %s", data.toString()); + + SimpleTLV tlv(data); + + if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : AccessControlMainFile */ + { + tlv.enterToValueTLV(); + + /* refresh Tag */ + ByteArray refreshTag; + + refreshTag = SimpleTLV::getOctetString(tlv); + SCARD_DEBUG("current refresh tag : %s", refreshTag.toString()); + + if (this->refreshTag != refreshTag) /* need to update access control list */ + { + this->refreshTag = refreshTag; + + releaseACL(); + + /* access control rule path */ + if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ + { + /* TODO : parse path */ + ByteArray path; + + /* OCTET STRING */ + path = SimpleTLV::getOctetString(tlv.getValue()); + SCARD_DEBUG("access control rule path : %s", path.toString()); + + if (loadRules(path) == 0) + { + SCARD_DEBUG("loadRules success"); + } + else + { + SCARD_DEBUG_ERR("loadRules failed"); + } + } + } + tlv.returnToParentTLV(); + } + else + { + SCARD_DEBUG_ERR("tlv.decodeTLV failed"); + } + } + else + { + SCARD_DEBUG_ERR("search failed"); + } + + return 0; + } + + int GPSEACL::loadRules(ByteArray path) + { + FileObject file(channel); + ByteArray data, aid; + + file.select(NumberStream::getLittleEndianNumber(path)); + file.readBinary(0, 0, file.getFCP()->getFileSize(), data); + + SCARD_DEBUG("data : %s", data.toString()); + + SimpleTLV tlv(data); + + while (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Rule */ + { + tlv.enterToValueTLV(); + if (tlv.decodeTLV() == true) + { + /* target */ + switch (tlv.getTag()) + { + case 0xA0 : /* CHOICE 0 : EXPLICIT AID */ + /* OCTET STRING */ + aid = SimpleTLV::getOctetString(tlv.getValue()); + break; + + case 0x81 : /* CHOICE 1?? : default */ + aid = AccessControlList::AID_DEFAULT; + break; + + case 0x82 : /* CHOICE 2?? : any application */ + aid = AccessControlList::AID_ALL; + break; + } + + SCARD_DEBUG("aid : %s", aid.toString()); + + /* access condition path */ + if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE : Path */ + { + ByteArray path; + + /* OCTET STRING */ + path = SimpleTLV::getOctetString(tlv.getValue()); + SCARD_DEBUG("path : %s", path.toString()); + + if (loadAccessConditions(aid, path) == 0) + { + SCARD_DEBUG("loadCertHashes success"); + } + else + { + SCARD_DEBUG_ERR("loadCertHashes failed"); + } + } + else + { + SCARD_DEBUG_ERR("decodeTLV failed"); + } + } + else + { + SCARD_DEBUG_ERR("decodeTLV failed"); + } + tlv.returnToParentTLV(); + } + + return 0; + } + + int GPSEACL::loadAccessConditions(ByteArray aid, ByteArray path) + { + FileObject file(channel); + ByteArray data; + + file.select(NumberStream::getLittleEndianNumber(path)); + file.readBinary(0, 0, file.getFCP()->getFileSize(), data); + + SCARD_DEBUG("data : %s", data.toString()); + + AccessCondition condition; + + condition.loadAccessCondition(aid, data); + + pair newItem(aid, condition); + + mapConditions.insert(newItem); + + return 0; + } + +} /* namespace smartcard_service_api */ + +/* export C API */ +#define GP_SE_ACL_EXTERN_BEGIN \ + if (handle != NULL) \ + { \ + GPSEACL *acl = (GPSEACL *)handle; + +#define GP_SE_ACL_EXTERN_END \ + } \ + else \ + { \ + SCARD_DEBUG_ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API gp_se_acl_h gp_se_acl_create_instance(channel_h channel) +{ + GPSEACL *acl = new GPSEACL((Channel *)channel); + + return (gp_se_acl_h)acl; +} + +EXTERN_API int gp_se_acl_load_acl(gp_se_acl_h handle) +{ + int result = -1; + + GP_SE_ACL_EXTERN_BEGIN; + result = acl->loadACL(); + GP_SE_ACL_EXTERN_END; + + return result; +} + +EXTERN_API int gp_se_acl_update_acl(gp_se_acl_h handle) +{ + int result = -1; + + GP_SE_ACL_EXTERN_BEGIN; + acl->updateACL(); + GP_SE_ACL_EXTERN_END; + + return result; +} + +EXTERN_API void gp_se_acl_release_acl(gp_se_acl_h handle) +{ + GP_SE_ACL_EXTERN_BEGIN; + acl->releaseACL(); + GP_SE_ACL_EXTERN_END; +} + +EXTERN_API bool gp_se_acl_is_authorized_access(gp_se_acl_h handle, unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength) +{ + bool result = false; + + GP_SE_ACL_EXTERN_BEGIN; + result = acl->isAuthorizedAccess(aidBuffer, aidLength, certHashBuffer, certHashLength); + GP_SE_ACL_EXTERN_END; + + return result; +} + +EXTERN_API void gp_se_acl_destroy_instance(gp_se_acl_h handle) +{ + GP_SE_ACL_EXTERN_BEGIN; + delete acl; + GP_SE_ACL_EXTERN_END; +} diff --git a/common/IPCHelper.cpp b/common/IPCHelper.cpp new file mode 100644 index 0000000..e006b29 --- /dev/null +++ b/common/IPCHelper.cpp @@ -0,0 +1,430 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include +#include +#include +#ifdef USE_UNIX_DOMAIN +#include +#include +#else /* USE_UNIX_DOMAIN */ +#include +#endif /* USE_UNIX_DOMAIN */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "IPCHelper.h" + +#ifdef USE_UNIX_DOMAIN +#define OMAPI_SERVER_DOMAIN "/tmp/omapi-server-domain" +#endif /* USE_UNIX_DOMAIN */ + +static void setNonBlockSocket(int socket) +{ + int flags; + + flags = fcntl(socket, F_GETFL); + + flags |= O_NONBLOCK; + + if (fcntl(socket, F_SETFL, flags) < 0) + { + /* SCARD_DEBUG_ERR("fcntl, executing nonblock error"); */ + } +} + +namespace smartcard_service_api +{ + IPCHelper::IPCHelper() + { + ipcSocket = -1; + ioChannel = NULL; + watchId = 0; + memset(&ipcLock, 0, sizeof(ipcLock)); + dispatcher = NULL; + } + + IPCHelper::~IPCHelper() + { + } + + gboolean IPCHelper::channelCallbackFunc(GIOChannel* channel, GIOCondition condition, gpointer data) + { + IPCHelper *helper = (IPCHelper *)data; + gboolean result = FALSE; + + SCARD_DEBUG("channel [%p], condition [%d], data [%p]", channel, condition, data); + + if (helper == NULL) + { + SCARD_DEBUG_ERR("ipchelper is null"); + return result; + } + + if ((G_IO_ERR & condition) || (G_IO_HUP & condition)) + { + result = helper->handleIOErrorCondition(channel, condition); + } + else if (G_IO_NVAL & condition) + { + result = helper->handleInvalidSocketCondition(channel, condition); + } + else if (G_IO_IN & condition) + { + result = helper->handleIncomingCondition(channel, condition); + } + + return result; + } + + bool IPCHelper::createListenSocket() + { + GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN); + struct sockaddr_un saddrun_rv; + + if (ipcSocket >= 0) + return true; + + memset(&saddrun_rv, 0, sizeof(struct sockaddr_un)); + + unlink(OMAPI_SERVER_DOMAIN); + + ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0); + if (ipcSocket == -1) + { + SCARD_DEBUG_ERR("get socket is failed"); + return false; + } + + ::setNonBlockSocket(ipcSocket); + + saddrun_rv.sun_family = AF_UNIX; + strncpy(saddrun_rv.sun_path, OMAPI_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1); + + if (bind(ipcSocket, (struct sockaddr *)&saddrun_rv, sizeof(saddrun_rv)) < 0) + { + SCARD_DEBUG_ERR("bind is failed \n"); + goto ERROR; + } + + if (chmod(OMAPI_SERVER_DOMAIN, 0777) < 0) + { + SCARD_DEBUG_ERR("can not change permission of UNIX DOMAIN file"); + goto ERROR; + } + + if (listen(ipcSocket, IPC_SERVER_MAX_CLIENT) < 0) + { + SCARD_DEBUG_ERR("listen is failed \n"); + goto ERROR; + } + + if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL) + { + if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1) + { + SCARD_DEBUG_ERR(" g_io_add_watch is failed \n"); + goto ERROR; + } + } + else + { + SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed \n"); + goto ERROR; + } + +#ifdef SECURITY_SERVER + gid = security_server_get_gid(NET_NFC_MANAGER_OBJECT); + if(gid == 0) + { + SCARD_DEBUG("get gid from security server is failed. this object is not allowed by security server"); + goto ERROR; + } + + if((cookies_size = security_server_get_cookie_size()) != 0) + { + if((cookies = (char *)calloc(1, cookies_size)) == NULL) + { + goto ERROR; + } + } +#endif + + SCARD_DEBUG("server ipc is initialized"); + + return true; +ERROR : + if (watchId != (uint32_t)-1) + { + g_source_remove(watchId); + watchId = -1; + } + + if (ioChannel != NULL) + { + g_io_channel_unref(ioChannel); + ioChannel = NULL; + } + + if (ipcSocket != -1) + { + shutdown(ipcSocket, SHUT_RDWR); + close(ipcSocket); + + ipcSocket = -1; + } + + return false; + } + + bool IPCHelper::createConnectSocket() + { + GIOCondition condition = (GIOCondition) (G_IO_ERR | G_IO_HUP | G_IO_IN); + + SCARD_BEGIN(); + + if (ipcSocket >= 0) + return true; + + pthread_mutex_lock(&ipcLock); + + struct sockaddr_un saddrun_rv; + socklen_t len_saddr = 0; + + memset(&saddrun_rv, 0, sizeof(struct sockaddr_un)); + + ipcSocket = socket(AF_UNIX, SOCK_STREAM, 0); + if (ipcSocket == -1) + { + SCARD_DEBUG_ERR("get socket is failed \n"); + pthread_mutex_unlock(&ipcLock); + + SCARD_END(); + + return false; + } + + SCARD_DEBUG("socket is created"); + + ::setNonBlockSocket(ipcSocket); + + saddrun_rv.sun_family = AF_UNIX; + strncpy(saddrun_rv.sun_path, OMAPI_SERVER_DOMAIN, sizeof(saddrun_rv.sun_path) - 1); + + len_saddr = sizeof(saddrun_rv.sun_family) + strlen(OMAPI_SERVER_DOMAIN); + + if ((connect(ipcSocket, (struct sockaddr *)&saddrun_rv, len_saddr)) < 0) + { + SCARD_DEBUG_ERR("error is occured"); + pthread_mutex_unlock(&ipcLock); + goto ERROR; + } + + pthread_mutex_unlock(&ipcLock); + + if ((ioChannel = g_io_channel_unix_new(ipcSocket)) != NULL) + { + if ((watchId = g_io_add_watch(ioChannel, condition, &IPCHelper::channelCallbackFunc, this)) < 1) + { + SCARD_DEBUG_ERR(" g_io_add_watch is failed \n"); + goto ERROR; + } + } + else + { + SCARD_DEBUG_ERR(" g_io_channel_unix_new is failed \n"); + goto ERROR; + } + + SCARD_DEBUG("socket and g io channel is binded"); + + SCARD_END(); + + return true; + +ERROR : + SCARD_DEBUG_ERR("error while initializing client ipc"); + + if(watchId != 0) + { + g_source_remove(watchId); + watchId = 0; + } + + if(ioChannel != NULL) + { + g_io_channel_unref(ioChannel); + ioChannel = NULL; + } + + if (ipcSocket != -1) + { + shutdown(ipcSocket, SHUT_RDWR); + close(ipcSocket); + ipcSocket = -1; + } + + SCARD_END(); + + return false; + } + + bool IPCHelper::sendMessage(Message *msg) + { + if (ipcSocket == -1) + return false; + + return sendMessage(ipcSocket, msg); + } + + bool IPCHelper::sendMessage(int socket, Message *msg) + { + bool result = false; + ByteArray stream; + unsigned int length = 0; + + stream = msg->serialize(); + length = stream.getLength(); + + SCARD_DEBUG(">>>[SEND]>>> socket [%d], msg [%d], length [%d]", socket, msg->message, length); + + if (length > 0) + { + int sentBytes = 0; + + /* send 4 bytes (length) */ + pthread_mutex_lock(&ipcLock); + sentBytes = send(socket, &length, sizeof(length), 0); + pthread_mutex_unlock(&ipcLock); + if (sentBytes == sizeof(length)) + { + unsigned int current = 0; + + /* send message */ + pthread_mutex_lock(&ipcLock); + do + { + sentBytes = send(socket, stream.getBuffer(current), length - current, 0); + if (sentBytes > 0) + current += sentBytes; + } + while (current < length); + pthread_mutex_unlock(&ipcLock); + + result = true; + } + else + { + SCARD_DEBUG_ERR("send failed, sentBytes [%d]", sentBytes); + } + } + else + { + SCARD_DEBUG_ERR("stream length is zero"); + } + + return result; + } + + Message *IPCHelper::retrieveMessage() + { + return retrieveMessage(ipcSocket); + } + + Message *IPCHelper::retrieveMessage(int socket) + { + Message *msg = NULL; + unsigned int length = 0; + int readBytes = 0; + + SCARD_BEGIN(); + + /* read 4 bytes (length) */ + pthread_mutex_lock(&ipcLock); + readBytes = recv(socket, &length, sizeof(length), 0); + pthread_mutex_unlock(&ipcLock); + if (readBytes == sizeof(length)) + { + if (length > 0) + { + unsigned char *buffer = NULL; + + /* prepare buffer */ + buffer = new unsigned char[length]; + if (buffer != NULL) + { + int retry = 0; + unsigned int current = 0; + + /* read message */ + pthread_mutex_lock(&ipcLock); + do + { + readBytes = recv(socket, buffer + current, length - current, 0); + if (readBytes > 0) + current += readBytes; + retry++; + } + while (current < length); + pthread_mutex_unlock(&ipcLock); + + msg = new Message(); + if (msg != NULL) + { + msg->deserialize(buffer, length); + + SCARD_DEBUG("<<<[RETRIEVE]<<< socket [%d], msg_length [%d]", socket, length); + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + + delete []buffer; + } + else + { + SCARD_DEBUG_ERR("allocation failed"); + } + } + else + { + SCARD_DEBUG_ERR("invalid length, socket = [%d], msg_length = [%d]", socket, length); + } + } + else + { + SCARD_DEBUG_ERR("failed to recv length, socket = [%d], readBytes [%d]", socket, readBytes); + } + + + SCARD_END(); + + return msg; + } + + void IPCHelper::setDispatcher(DispatcherHelper *dispatcher) + { + this->dispatcher = dispatcher; + } + +} /* namespace smartcard_service_api */ diff --git a/common/ISO7816BERTLV.cpp b/common/ISO7816BERTLV.cpp new file mode 100644 index 0000000..eb60ab6 --- /dev/null +++ b/common/ISO7816BERTLV.cpp @@ -0,0 +1,281 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "ISO7816BERTLV.h" + +namespace smartcard_service_api +{ + ISO7816BERTLV::ISO7816BERTLV():TLVHelper() + { + tagClass = 0; + encoding = 0; + } + + ISO7816BERTLV::ISO7816BERTLV(TLVHelper *parent):TLVHelper(parent) + { + parentTLV = parent; + + tagClass = 0; + encoding = 0; + } + + ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array):TLVHelper(array) + { + tagClass = 0; + encoding = 0; + } + + ISO7816BERTLV::ISO7816BERTLV(const ByteArray &array, TLVHelper *parent):TLVHelper(array, parent) + { + parentTLV = parent; + + tagClass = 0; + encoding = 0; + } + + ISO7816BERTLV::~ISO7816BERTLV() + { + if (childTLV != NULL) + { + delete childTLV; + childTLV = NULL; + } + } + + int ISO7816BERTLV::decodeTag(unsigned char *buffer) + { + /* 0x00 is invalid tag value */ + if (buffer[0] == 0x00) + { + return -1; + } + + /* first byte */ + tagClass = (buffer[0] & 0xE0) >> 6; + encoding = (buffer[0] & 0x20) >> 5; + + currentT = buffer[0]; + + if ((buffer[0] & 0x1F) < 0x1F) + { + return 1; + } + + /* second byte */ + currentT = (currentT << 8) | buffer[1]; + if (buffer[1] & 0x80) + { + /* third byte */ + if (buffer[2] & 0x80) + { + return -1; + } + + currentT = (currentT << 8) | buffer[2]; + + return 3; + } + + return 2; + } + + int ISO7816BERTLV::decodeLength(unsigned char *buffer) + { + if (buffer[0] & 0x80) + { + uint8_t count = (buffer[0] & 0x7F); + uint8_t i; + + /* count will be less than 5 */ + if (count > 4) + return -1; + + count++; /* increse count and increase i value, too */ + + for (i = 1; i < count; i++) + { + /* if big endian */ + currentL = (currentL << 8) | buffer[i]; + + /* if little endian */ + /* currentL = currentL | (buffer[i] << (8 * (i - 1))); */ + } + + return count; + } + else + { + currentL = buffer[0]; + + return 1; + } + } + + int ISO7816BERTLV::decodeValue(unsigned char *buffer) + { + if (currentL == 0) + return 0; + + currentV.setBuffer(buffer, currentL); + + return currentL; + } + + unsigned int ISO7816BERTLV::getClass() + { + return tagClass; + } + + unsigned int ISO7816BERTLV::getEncoding() + { + return encoding; + } + + ByteArray ISO7816BERTLV::encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, ByteArray buffer) + { + unsigned char temp_tag[3] = { 0, }; + unsigned char temp_tag_len = 0; + unsigned char temp_len[5] = { 0, }; + unsigned char temp_len_len = 0; + ByteArray result; + unsigned int total_len = 0; + unsigned int current = 0; + unsigned char *temp_buffer = NULL; + + /* add tag's length */ + if (tag > 0x7FFF) + return result; + + temp_tag[0] = (tagClass << 6) | (encoding << 5); + + if (tag < 0x1F) + { + temp_tag[0] |= tag; + temp_tag_len = 1; + } + else + { + temp_tag[0] |= 0x1F; + + if (tag < 0x80) + { + temp_tag[1] = tag; + + temp_tag_len = 2; + } + else + { + temp_tag[1] = (tag & 0x000000FF); + temp_tag[2] = (tag & 0x0000FF00); + + temp_tag_len = 3; + } + } + + total_len += temp_tag_len; + + /* add length's length */ + if (buffer.getLength() < 128) + { + temp_len[0] = buffer.getLength(); + + temp_len_len = 1; + } + else + { + temp_len[0] = 0x80; + temp_len_len = 1; + + if (buffer.getLength() > 0x00FFFFFF) + { + temp_len[4] = (buffer.getLength() & 0xFF000000) >> 24; + temp_len_len++; + } + + if (buffer.getLength() > 0x0000FFFF) + { + temp_len[3] = (buffer.getLength() & 0x00FF0000) >> 16; + temp_len_len++; + } + + if (buffer.getLength() > 0x000000FF) + { + temp_len[2] = (buffer.getLength() & 0x0000FF00) >> 8; + temp_len_len++; + } + + temp_len[1] = buffer.getLength() & 0x000000FF; + temp_len_len++; + + temp_len[0] |= temp_len_len; + } + + /* add buffer's length */ + total_len += buffer.getLength(); + + /* alloc new buffer */ + temp_buffer = new unsigned char[total_len]; + if (temp_buffer == NULL) + { + return result; + } + memset(temp_buffer, 0, total_len); + + /* fill tag */ + memcpy(temp_buffer + current, temp_tag, temp_tag_len); + current += temp_tag_len; + + /* fill length */ + memcpy(temp_buffer + current, temp_len, temp_len_len); + current += temp_len_len; + + /* fill value */ + if (buffer.getLength() > 0) + memcpy(temp_buffer + current, buffer.getBuffer(), buffer.getLength()); + + result.setBuffer(temp_buffer, total_len); + + delete []temp_buffer; + + return result; + } + + ByteArray ISO7816BERTLV::encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, unsigned char *buffer, unsigned int length) + { + return encode(tagClass, encoding, tag, ByteArray(buffer, length)); + } + + TLVHelper *ISO7816BERTLV::getChildTLV(ByteArray data) + { + if (childTLV != NULL) + { + delete childTLV; + childTLV = NULL; + } + childTLV = new ISO7816BERTLV(data, this); + + return (TLVHelper *)childTLV; + } + +} /* namespace smartcard_service_api */ diff --git a/common/Message.cpp b/common/Message.cpp new file mode 100644 index 0000000..f54fbbf --- /dev/null +++ b/common/Message.cpp @@ -0,0 +1,215 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Message.h" + +namespace smartcard_service_api +{ + Message::Message() + { + message = 0; + param1 = 0; + param2 = 0; + error = 0; + caller = NULL; + callback = NULL; + userParam = NULL; + } + + Message::~Message() + { + } + + ByteArray Message::serialize() + { + ByteArray result; + unsigned int length = 0; + unsigned int dataLength = 0; + unsigned char *buffer = NULL; + + length = sizeof(message) + sizeof(param1) + sizeof(param2) + sizeof(error) + sizeof(caller) + sizeof(callback) + sizeof(userParam); + if (data.getLength() > 0) + { + dataLength = data.getLength(); + length += sizeof(dataLength) + data.getLength(); + } + + buffer = new unsigned char[length]; + if (buffer != NULL) + { + unsigned int current = 0; + + memset(buffer, 0, length); + + memcpy(buffer + current, &message, sizeof(message)); + current += sizeof(message); + + memcpy(buffer + current, ¶m1, sizeof(param1)); + current += sizeof(param1); + + memcpy(buffer + current, ¶m2, sizeof(param2)); + current += sizeof(param2); + + memcpy(buffer + current, &error, sizeof(error)); + current += sizeof(error); + + memcpy(buffer + current, &caller, sizeof(caller)); + current += sizeof(caller); + + memcpy(buffer + current, &callback, sizeof(callback)); + current += sizeof(callback); + + memcpy(buffer + current, &userParam, sizeof(userParam)); + current += sizeof(userParam); + + if (data.getLength() > 0) + { + memcpy(buffer + current, &dataLength, sizeof(dataLength)); + current += sizeof(dataLength); + + memcpy(buffer + current, data.getBuffer(), dataLength); + current += data.getLength(); + } + + result.setBuffer(buffer, length); + + delete []buffer; + } + else + { + SCARD_DEBUG_ERR("allocation failed"); + } + + return result; + } + + void Message::deserialize(ByteArray buffer) + { + deserialize(buffer.getBuffer(), buffer.getLength()); + } + + void Message::deserialize(unsigned char *buffer, unsigned int length) + { + unsigned int current = 0; + unsigned int dataLength = 0; + +// SCARD_DEBUG("buffer [%p], length [%d]", buffer, length); + + memcpy(&message, buffer + current, sizeof(message)); + current += sizeof(message); + +// SCARD_DEBUG("message [%d]", message); + + memcpy(¶m1, buffer + current, sizeof(param1)); + current += sizeof(param1); + +// SCARD_DEBUG("param1 [%d]", param1); + + memcpy(¶m2, buffer + current, sizeof(param2)); + current += sizeof(param2); + +// SCARD_DEBUG("param2 [%d]", param2); + + memcpy(&error, buffer + current, sizeof(error)); + current += sizeof(error); + + memcpy(&caller, buffer + current, sizeof(caller)); + current += sizeof(caller); + + memcpy(&callback, buffer + current, sizeof(callback)); + current += sizeof(callback); + + memcpy(&userParam, buffer + current, sizeof(userParam)); + current += sizeof(userParam); + +// SCARD_DEBUG("userContext [%p]", userContext); + + if (current + sizeof(dataLength) < length) + { + memcpy(&dataLength, buffer + current, sizeof(dataLength)); + current += sizeof(dataLength); + +// SCARD_DEBUG("dataLength [%d]", dataLength); + + data.setBuffer(buffer + current, dataLength); + current += dataLength; + } + } + + const char *Message::toString() + { + const char *msg = NULL; + + memset(&text, 0, sizeof(text)); + + switch (message) + { + case MSG_REQUEST_READERS : + msg = "MSG_REQUEST_READERS"; + break; + +// case MSG_REQUEST_READER_NAME : +// msg = "MSG_REQUEST_READER_NAME"; +// break; +// + case MSG_REQUEST_OPEN_SESSION : + msg = "MSG_REQUEST_OPEN_SESSION"; + break; + + case MSG_REQUEST_CLOSE_SESSION : + msg = "MSG_REQUEST_CLOSE_CHANNEL"; + break; + + case MSG_REQUEST_OPEN_CHANNEL : + msg = "MSG_REQUEST_OPEN_CHANNEL"; + break; + + case MSG_REQUEST_CLOSE_CHANNEL : + msg = "MSG_REQUEST_CLOSE_CHANNEL"; + break; + + case MSG_REQUEST_GET_ATR : + msg = "MSG_REQUEST_GET_ATR"; + break; + + case MSG_REQUEST_TRANSMIT : + msg = "MSG_REQUEST_TRANSMIT"; + break; + + case MSG_REQUEST_GET_CHANNEL_COUNT : + msg = "MSG_REQUEST_GET_CHANNEL_COUNT"; + break; + + default : + msg = "Unknown"; + break; + } + + snprintf(text, sizeof(text), "Message [%s, %d], param1 [%d], param2 [%d], error [%d], caller [%p], callback [%p], userParam [%p], data length [%d]", msg, message, param1, param2, error, caller, callback, userParam, data.getLength()); + + return (const char *)text; + } + +} /* namespace smartcard_service_api */ diff --git a/common/NumberStream.cpp b/common/NumberStream.cpp new file mode 100644 index 0000000..3246b15 --- /dev/null +++ b/common/NumberStream.cpp @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2012 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 "NumberStream.h" + +namespace smartcard_service_api +{ + NumberStream::NumberStream(const ByteArray &T) + { + setBuffer(T.getBuffer(), T.getLength()); + } + + unsigned int NumberStream::getBigEndianNumber() + { + return getBigEndianNumber(*this); + } + + unsigned int NumberStream::getLittleEndianNumber() + { + return getLittleEndianNumber(*this); + } + + NumberStream &NumberStream::operator =(const ByteArray &T) + { + if (this != &T) + { + setBuffer(T.getBuffer(), T.getLength()); + } + + return *this; + } + + NumberStream &NumberStream::operator =(const NumberStream &T) + { + if (this != &T) + { + setBuffer(T.getBuffer(), T.getLength()); + } + + return *this; + } + + unsigned int NumberStream::getBigEndianNumber(const ByteArray &T) + { + int i, len; + unsigned int result = 0; + + len = (T.getLength() < 4) ? T.getLength() : 4; + + for (i = 0; i < len; i++) + { + result = (result << 8) | T.getAt(i); + } + + return result; + } + + unsigned int NumberStream::getLittleEndianNumber(const ByteArray &T) + { + int i, len; + unsigned int result = 0; + + len = (T.getLength() < 4) ? T.getLength() : 4; + + for (i = 0; i < len; i++) + { + result = result | (T.getAt(i) << (i * 8)); + } + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/common/OpensslHelper.cpp b/common/OpensslHelper.cpp new file mode 100644 index 0000000..5241bad --- /dev/null +++ b/common/OpensslHelper.cpp @@ -0,0 +1,171 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ByteArray.h" +#include "OpensslHelper.h" + +namespace smartcard_service_api +{ + bool OpensslHelper::encodeBase64String(const ByteArray &buffer, ByteArray &result, bool newLineChar) + { + bool ret = false; + BUF_MEM *bptr; + BIO *b64, *bmem; + + if (buffer.getLength() == 0) + { + return ret; + } + + b64 = BIO_new(BIO_f_base64()); + bmem = BIO_new(BIO_s_mem()); + + if (newLineChar == false) + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + b64 = BIO_push(b64, bmem); + + BIO_write(b64, buffer.getBuffer(), buffer.getLength()); + BIO_flush(b64); + BIO_get_mem_ptr(b64, &bptr); + + result.setBuffer((unsigned char *)bptr->data, bptr->length); + + BIO_free_all(b64); + + ret = true; + + return ret; + } + + bool OpensslHelper::decodeBase64String(const char *buffer, ByteArray &result, bool newLineChar) + { + ByteArray temp; + + temp.setBuffer((unsigned char *)buffer, strlen(buffer)); + + return decodeBase64String(temp, result, newLineChar); + } + + bool OpensslHelper::decodeBase64String(const ByteArray &buffer, ByteArray &result, bool newLineChar) + { + bool ret = false; + unsigned int length = 0; + char *temp; + + if (buffer.getBuffer() == NULL || buffer.getLength() == 0) + { + return ret; + } + + length = buffer.getLength(); + + temp = new char[length]; + if (temp != NULL) + { + BIO *b64, *bmem; + + memset(temp, 0, length); + + b64 = BIO_new(BIO_f_base64()); + bmem = BIO_new_mem_buf(buffer.getBuffer(), length); + if (newLineChar == false) + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + bmem = BIO_push(b64, bmem); + + length = BIO_read(bmem, temp, length); + + BIO_free_all(bmem); + + result.setBuffer((unsigned char *)temp, length); + + delete []temp; + + ret = true; + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + + return ret; + } + + bool OpensslHelper::digestBuffer(const char *algorithm, const uint8_t *buffer, const uint32_t length, ByteArray &result) + { + ByteArray temp((uint8_t *)buffer, (uint32_t)length); + + return digestBuffer(algorithm, temp, result); + } + + bool OpensslHelper::digestBuffer(const char *algorithm, const ByteArray &buffer, ByteArray &result) + { + const EVP_MD *md; + unsigned char *temp; + bool ret = false; + + if (algorithm == NULL || buffer.getLength() == 0) + { + return ret; + } + + OpenSSL_add_all_digests(); + + if ((md = EVP_get_digestbyname(algorithm)) != NULL) + { + temp = new unsigned char[EVP_MAX_MD_SIZE]; + if (temp != NULL) + { + EVP_MD_CTX mdCtx; + unsigned int resultLen = 0; + + memset(temp, 0, EVP_MAX_MD_SIZE); + + EVP_DigestInit(&mdCtx, md); + EVP_DigestUpdate(&mdCtx, buffer.getBuffer(), buffer.getLength()); + EVP_DigestFinal(&mdCtx, temp, &resultLen); + + result.setBuffer(temp, resultLen); + + delete []temp; + + ret = true; + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + else + { + SCARD_DEBUG_ERR("EVP_get_digestbyname(\"%s\") returns NULL", algorithm); + } + + return ret; + } + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15.cpp b/common/PKCS15.cpp new file mode 100644 index 0000000..ae13de5 --- /dev/null +++ b/common/PKCS15.cpp @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "PKCS15.h" + +namespace smartcard_service_api +{ + static unsigned char aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x63, 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; + ByteArray PKCS15::PKCS15_AID(ARRAY_AND_SIZE(aid)); + + PKCS15::PKCS15(Channel *channel):PKCS15Object(channel), odf(NULL) + { + int ret = 0; + + if ((ret = select(PKCS15::PKCS15_AID)) == 0) + { + SCARD_DEBUG("response : %s", selectResponse.toString()); + } + else + { + SCARD_DEBUG_ERR("select failed, [%d]", ret); + } + } + + PKCS15::PKCS15(Channel *channel, ByteArray selectResponse):PKCS15Object(channel, selectResponse), odf(NULL) + { + } + + PKCS15::~PKCS15() + { + if (odf != NULL) + { + delete odf; + odf = NULL; + } + } + + PKCS15ODF *PKCS15::getODF() + { + if (odf == NULL) + { + odf = new PKCS15ODF(channel); + } + + SCARD_DEBUG("odf [%p]", odf); + + return odf; + } + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15DODF.cpp b/common/PKCS15DODF.cpp new file mode 100644 index 0000000..61af800 --- /dev/null +++ b/common/PKCS15DODF.cpp @@ -0,0 +1,138 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "PKCS15DODF.h" +#include "SimpleTLV.h" + +namespace smartcard_service_api +{ +// PKCS15DODF::PKCS15DODF():PKCS15Object() +// { +// +// } + + PKCS15DODF::PKCS15DODF(unsigned int fid, Channel *channel):PKCS15Object(channel) + { + int ret = 0; + + if ((ret = select(fid)) == 0) + { + ByteArray dodfData, extra; + + SCARD_DEBUG("response : %s", selectResponse.toString()); + + if ((ret = readBinary(0, 0, getFCP()->getFileSize(), dodfData)) == 0) + { + SCARD_DEBUG("odfData : %s", dodfData.toString()); + + parseData(dodfData); + } + else + { + SCARD_DEBUG_ERR("readBinary failed, [%d]", ret); + } + } + else + { + SCARD_DEBUG_ERR("select failed, [%d]", ret); + } + } + + PKCS15DODF::PKCS15DODF(ByteArray path, Channel *channel):PKCS15Object(channel) + { + int ret = 0; + + if ((ret = select(path)) == 0) + { + ByteArray dodfData, extra; + + SCARD_DEBUG("response : %s", selectResponse.toString()); + + if ((ret = readBinary(0, 0, getFCP()->getFileSize(), dodfData)) == 0) + { + SCARD_DEBUG("dodfData : %s", dodfData.toString()); + + parseData(dodfData); + } + else + { + SCARD_DEBUG_ERR("readBinary failed, [%d]", ret); + } + } + else + { + SCARD_DEBUG_ERR("select failed, [%d]", ret); + } + } + + PKCS15DODF::~PKCS15DODF() + { + } + + bool PKCS15DODF::parseData(ByteArray data) + { + bool result = false; + SimpleTLV tlv(data); + + while (tlv.decodeTLV()) + { + switch (tlv.getTag()) + { + case (unsigned int)0xA1 : /* CHOICE 1 : OidDO */ + { + PKCS15OID oid(tlv.getValue()); + + SCARD_DEBUG("OID DataObject"); + + pair newPair(oid.getOID(), oid); + mapOID.insert(newPair); + } + break; + + default : + SCARD_DEBUG("Unknown tlv : t [%X], l [%d], v %s", tlv.getTag(), tlv.getLength(), tlv.getValue().toString()); + break; + } + } + + SCARD_DEBUG("dataList.size() = %d", mapOID.size()); + + return result; + } + + int PKCS15DODF::searchOID(ByteArray oid, ByteArray &data) + { + int result = -1; + map::iterator item; + + item = mapOID.find(oid); + if (item != mapOID.end()) + { + data = item->second.getPath(); + result = 0; + } + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15ODF.cpp b/common/PKCS15ODF.cpp new file mode 100644 index 0000000..0710e65 --- /dev/null +++ b/common/PKCS15ODF.cpp @@ -0,0 +1,166 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "PKCS15ODF.h" +#include "SimpleTLV.h" +#include "NumberStream.h" + +namespace smartcard_service_api +{ +// PKCS15ODF::PKCS15ODF():PKCS15Object() +// { +// +// } + + PKCS15ODF::PKCS15ODF(Channel *channel):PKCS15Object(channel), dodf(NULL) + { + int ret = 0; + + if ((ret = select(PKCS15ODF::ODF_FID)) == 0) + { + ByteArray odfData, extra; + + SCARD_DEBUG("response : %s", selectResponse.toString()); + + if ((ret = readBinary(0, 0, getFCP()->getFileSize(), odfData)) == 0) + { + SCARD_DEBUG("odfData : %s", odfData.toString()); + + parseData(odfData); + } + else + { + SCARD_DEBUG_ERR("readBinary failed, [%d]", ret); + } + } + else + { + SCARD_DEBUG_ERR("select failed, [%d]", ret); + } + } + + PKCS15ODF::PKCS15ODF(Channel *channel, ByteArray selectResponse):PKCS15Object(channel, selectResponse), dodf(NULL) + { + int ret = 0; + ByteArray odfData; + + if ((ret = readBinary(0, 0, 0, odfData)) == 0) + { + SCARD_DEBUG("odfData : %s", odfData.toString()); + + parseData(odfData); + } + else + { + SCARD_DEBUG_ERR("readBinary failed, [%d]", ret); + } + } + + PKCS15ODF::~PKCS15ODF() + { + if (dodf != NULL) + { + delete dodf; + dodf = NULL; + } + } + + bool PKCS15ODF::parseData(ByteArray data) + { + bool result = false; + SimpleTLV tlv(data); + + while (tlv.decodeTLV()) + { + switch (tlv.getTag()) + { + case (unsigned int)0xA7 ://PKCS15ODF::TAG_DODF : + { + ByteArray dodf; + + SCARD_DEBUG("TAG_DODF"); + + dodf = PKCS15Object::getOctetStream(tlv.getValue()); + + SCARD_DEBUG("path : %s", dodf.toString()); + + pair newPair(tlv.getTag(), dodf); + dataList.insert(newPair); + } + break; + + case (unsigned int)0xA5 ://PKCS15ODF::TAG_TOKENINFO : + { + ByteArray tokeninfo; + + SCARD_DEBUG("TAG_TOKENINFO"); + + tokeninfo = PKCS15Object::getOctetStream(tlv.getValue()); + + SCARD_DEBUG("path : %s", tokeninfo.toString()); + + pair newPair(tlv.getTag(), tokeninfo); + dataList.insert(newPair); + } + break; + + default : + SCARD_DEBUG("Unknown tlv : t [%X], l [%d], v %s", tlv.getTag(), tlv.getLength(), tlv.getValue().toString()); + break; + } + + } + + SCARD_DEBUG("dataList.size() = %d", dataList.size()); + + return result; + } + + PKCS15DODF *PKCS15ODF::getDODF() + { + map::iterator item; + + if (dodf == NULL) + { + item = dataList.find((unsigned int)0xA7/*PKCS15ODF::TAG_DODF*/); + if (item != dataList.end()) + { + NumberStream num(item->second); + unsigned int fid = num.getLittleEndianNumber(); + + SCARD_DEBUG("fid [%X]", fid); + + dodf = new PKCS15DODF(fid, channel); + } + else + { + SCARD_DEBUG_ERR("[%02X] is not found. total [%d]", TAG_DODF, dataList.size()); + } + } + + SCARD_DEBUG("dodf [%p]", dodf); + + return dodf; + } + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15OID.cpp b/common/PKCS15OID.cpp new file mode 100644 index 0000000..645796f --- /dev/null +++ b/common/PKCS15OID.cpp @@ -0,0 +1,144 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "PKCS15.h" +#include "PKCS15OID.h" +#include "SimpleTLV.h" + +namespace smartcard_service_api +{ + PKCS15OID::PKCS15OID(ByteArray data) + { + parseOID(data); + } + + PKCS15OID::~PKCS15OID() + { + } + + bool PKCS15OID::parseOID(ByteArray data) + { + bool result = false; + SimpleTLV tlv(data); + + SCARD_BEGIN(); + + while (tlv.decodeTLV() == true) + { + switch (tlv.getTag()) + { + case PKCS15::TAG_SEQUENCE : + if (tlv.getLength() > 0) + { + /* common object attribute */ + tlv.enterToValueTLV(); + if (tlv.decodeTLV() == true && tlv.getTag() == 0x0C) /* ?? */ + { + name = tlv.getValue(); + SCARD_DEBUG("name : %s", name.toString()); + } + tlv.returnToParentTLV(); + } + else + { + /* common object attribute */ + /* if you want to use this value, add member variable and parse here */ +// SCARD_DEBUG_ERR("common object attribute is empty"); + } + break; + + case 0xA0 : /* CHOICE 0 : External Oid??? */ + SCARD_DEBUG_ERR("oid doesn't exist"); + break; + + case 0xA1 : /* CHOICE 1 : OidDO */ + tlv.enterToValueTLV(); + + /* attribute */ + if (tlv.decodeTLV() == true && tlv.getTag() == PKCS15::TAG_SEQUENCE) + { + tlv.enterToValueTLV(); + + /* oid */ + if (tlv.decodeTLV() == true && tlv.getTag() == (unsigned int)0x06) /* ?? */ + { + oid = tlv.getValue(); + + SCARD_DEBUG("oid : %s", oid.toString()); + } + else + { + SCARD_DEBUG_ERR("oid is empty"); + } + + /* path */ + if (tlv.decodeTLV() == true && tlv.getTag() == PKCS15::TAG_SEQUENCE) + { + path = SimpleTLV::getOctetString(tlv.getValue()); + + SCARD_DEBUG("path : %s", path.toString()); + + result = true; + } + else + { + SCARD_DEBUG_ERR("sequence is empty"); + } + + tlv.returnToParentTLV(); + } + else + { + SCARD_DEBUG_ERR("common dataobject attribute is empty"); + } + tlv.returnToParentTLV(); + + break; + + default : + SCARD_DEBUG_ERR("Unknown tag : 0x%02X", tlv.getTag()); + break; + } + } + + SCARD_END(); + + return result; + } + + ByteArray PKCS15OID::getOID() + { + return oid; + } + + ByteArray PKCS15OID::getName() + { + return name; + } + + ByteArray PKCS15OID::getPath() + { + return path; + } + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15Object.cpp b/common/PKCS15Object.cpp new file mode 100644 index 0000000..ee2d57e --- /dev/null +++ b/common/PKCS15Object.cpp @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "SimpleTLV.h" +#include "PKCS15Object.h" + +namespace smartcard_service_api +{ +// PKCS15Object::PKCS15Object():FileObject() +// { +// } + + PKCS15Object::PKCS15Object(Channel *channel):FileObject(channel) + { + } + + PKCS15Object::PKCS15Object(Channel *channel, ByteArray selectResponse):FileObject(channel, selectResponse) + { + } + + PKCS15Object::~PKCS15Object() + { + } + + ByteArray PKCS15Object::getOctetStream(const ByteArray &data) + { + ByteArray result; + SimpleTLV tlv(data); + + if (tlv.decodeTLV() && tlv.getTag() == TAG_SEQUENCE) + { + tlv.enterToValueTLV(); + + if (tlv.decodeTLV() && tlv.getTag() == TAG_OCTET_STREAM) + { + result = tlv.getValue(); + } + else + { + SCARD_DEBUG_ERR("TAG_OCTET_STREAM not found"); + } + tlv.returnToParentTLV(); + } + else + { + SCARD_DEBUG_ERR("TAG_SEQUENCE not found"); + } + + return result; + } + + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15Path.cpp b/common/PKCS15Path.cpp new file mode 100644 index 0000000..4ee65a1 --- /dev/null +++ b/common/PKCS15Path.cpp @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "PKCS15Path.h" + +namespace smartcard_service_api +{ + PKCS15Path::PKCS15Path() + { + } + + PKCS15Path::~PKCS15Path() + { + } + +// PKCS15Path(ByteArray &data); +// PKCS15Path(ByteArray path, int index); +// PKCS15Path(unsigned char *path, unsigned int length, int index); +// ~PKCS15Path(); +// +// bool PKCS15Path::parseData(ByteArray &data) +// { +// SimpleTLV tlv(data); +// +// if (tlv.decodeTLV() == true && tlv.getTag() == 0x30) /* SEQUENCE */ +// { +// /* get path */ +// path = tlv.getOctetString(); +// +// if (tlv.decodeTLV()) +// index = t +// +// } +// } +// +// int getPath(ByteArray &path); +// bool hasIndexLength(); +// int getIndex(); +// unsigned int getLength(); +// int encode(ByteArray &result); + +} /* namespace smartcard_service_api */ diff --git a/common/PKCS15TokenInfo.cpp b/common/PKCS15TokenInfo.cpp new file mode 100644 index 0000000..1022347 --- /dev/null +++ b/common/PKCS15TokenInfo.cpp @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "PKCS15TokenInfo.h" + +namespace smartcard_service_api +{ + PKCS15TokenInfo::PKCS15TokenInfo(Channel *channel):PKCS15Object(channel) + { + } + + PKCS15TokenInfo::~PKCS15TokenInfo() + { + } + +} /* namespace smartcard_service_api */ diff --git a/common/ProviderHelper.cpp b/common/ProviderHelper.cpp new file mode 100644 index 0000000..61161eb --- /dev/null +++ b/common/ProviderHelper.cpp @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ProviderHelper.h" + +namespace smartcard_service_api +{ +// ProviderHelper::ProviderHelper() +// { +// } + + ProviderHelper::ProviderHelper(Channel *channel) + { + this->channel = NULL; + + if (channel == NULL) + { + SCARD_DEBUG_ERR("invalid channel"); + return; + } + + this->channel = channel; + } + + ProviderHelper::~ProviderHelper() + { + } + + Channel *ProviderHelper::getChannel() + { + return channel; + } + +} /* namespace smartcard_service_api */ diff --git a/common/ReaderHelper.cpp b/common/ReaderHelper.cpp new file mode 100644 index 0000000..aed14c3 --- /dev/null +++ b/common/ReaderHelper.cpp @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ReaderHelper.h" + +namespace smartcard_service_api +{ + ReaderHelper::ReaderHelper() + { + memset(name, 0, sizeof(name)); + seService = NULL; + } + + ReaderHelper::~ReaderHelper() + { + } + + const char *ReaderHelper::getName() + { + return (const char *)name; + } + + SEServiceHelper *ReaderHelper::getSEService() + { + return seService; + } + + bool ReaderHelper::isSecureElementPresent() + { + /* get checkse() symbol of se library (dlsym) */ + /* invoke checkse() and return result */ + + return true /* checkse() */; + } + +} /* namespace smartcard_service_api */ diff --git a/common/Record.cpp b/common/Record.cpp new file mode 100644 index 0000000..e31cd98 --- /dev/null +++ b/common/Record.cpp @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Record.h" + +namespace smartcard_service_api +{ + Record::Record() + { + } + + Record::~Record() + { + } + +} /* namespace smartcard_service_api */ diff --git a/common/SEServiceHelper.cpp b/common/SEServiceHelper.cpp new file mode 100644 index 0000000..9bab511 --- /dev/null +++ b/common/SEServiceHelper.cpp @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "SEServiceHelper.h" + +namespace smartcard_service_api +{ + SEServiceHelper::SEServiceHelper() + { + connected = false; + } + + SEServiceHelper::~SEServiceHelper() + { + shutdown(); + } + + vector SEServiceHelper::getReaders() + { + return readers; + } + + bool SEServiceHelper::isConnected() + { + return (readers.size() > 0); + } + + void SEServiceHelper::shutdown() + { + uint32_t i; + + for (i = 0; i < readers.size(); i++) + { + readers[i]->closeSessions(); + } + + readers.clear(); + } + +} /* namespace smartcard_service_api */ diff --git a/common/Serializable.cpp b/common/Serializable.cpp new file mode 100644 index 0000000..2920264 --- /dev/null +++ b/common/Serializable.cpp @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Serializable.h" + +namespace smartcard_service_api +{ +} /* namespace smartcard_service_api */ diff --git a/common/SessionHelper.cpp b/common/SessionHelper.cpp new file mode 100644 index 0000000..08fb34d --- /dev/null +++ b/common/SessionHelper.cpp @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "SessionHelper.h" +#include "ReaderHelper.h" + +namespace smartcard_service_api +{ + SessionHelper::SessionHelper(ReaderHelper *reader) + { + closed = true; + + if (reader == NULL) + return; + + this->reader = reader; + } + + SessionHelper::~SessionHelper() + { + } + + ReaderHelper *SessionHelper::getReader() + { + return reader; + } + +// ByteArray SessionHelper::getATR() +// { +// return atr; +// } + + bool SessionHelper::isClosed() + { + return closed; + } + +} /* namespace smartcard_service_api */ diff --git a/common/SignatureHelper.cpp b/common/SignatureHelper.cpp new file mode 100644 index 0000000..58262b6 --- /dev/null +++ b/common/SignatureHelper.cpp @@ -0,0 +1,266 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ +#include "dpl/wrt-dao-ro/WrtDatabase.h" +#include "dpl/wrt-dao-ro/widget_dao_read_only.h" +#include "dpl/wrt-dao-ro/wrt_db_types.h" +#include "dpl/db/sql_connection.h" +#include "aul.h" + +/* local header */ +#include "Debug.h" +#include "SignatureHelper.h" +#include "OpensslHelper.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +using namespace WrtDB; +using namespace std; + +namespace smartcard_service_api +{ + int SignatureHelper::getProcessName(int pid, char *processName, uint32_t length) + { + int ret = -1; + FILE *file = NULL; + char filename[1024] = { 0, }; + + if (pid < 0 || processName == NULL || length == 0) + return ret; + + snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid); + SCARD_DEBUG("pid : %d, file name : %s", pid, filename); + + if ((file = fopen(filename, "r")) != NULL) + { + char *name = NULL; + ByteArray hash, result; + size_t len; + + memset(filename, 0, sizeof(filename)); + len = fread(filename, 1, sizeof(filename) - 1, file); + fclose(file); + + name = basename(filename); + SCARD_DEBUG("file name : %s", name); + + OpensslHelper::digestBuffer("sha256", (uint8_t *)name, strlen(name), hash); + SCARD_DEBUG("digest [%d] : %s", hash.getLength(), hash.toString()); + + OpensslHelper::encodeBase64String(hash, result, false); + + memset(processName, 0, length); + memcpy(processName, result.getBuffer(), (result.getLength() < length - 1) ? result.getLength() : length - 1); + + ret = 0; + } + else + { + + } + + return ret; + } + + ByteArray SignatureHelper::getCertificationHash(const char *packageName) + { + ByteArray result; + list::iterator item; + CertificateChainList certList; + + SCARD_DEBUG("package name : %s", packageName); + + try + { + WrtDatabase::attachToThreadRO(); + + int handle = WidgetDAOReadOnly::getHandle(DPL::FromUTF8String(packageName)); + WidgetDAOReadOnly widget(handle); + certList = widget.getWidgetCertificate(); + + SCARD_DEBUG("certList.size [%d]", certList.size()); + + WrtDatabase::detachFromThread(); + } + catch(...) + { + SCARD_DEBUG_ERR("exception occurs!!!"); + return result; + } + + if (certList.size() > 0) + { + string certString; + ByteArray certArray; + +#if 0 + for (item = certList.begin(); item != certList.end(); item++) + { + SCARD_DEBUG("certList : %s", item->data()); + } +#endif + certString = certList.back(); + SCARD_DEBUG("certString[%d] :\n%s", certString.size(), certString.data()); + + /* base64 decoding */ + if (OpensslHelper::decodeBase64String(certString.data(), certArray) == true) + { + int count = 0, offset = 0, length; +// int i; + ByteArray cert; + + SCARD_DEBUG("decoded[%d] : %s", certArray.getLength(), certArray.toString()); + + /* get count */ + count = *(int *)certArray.getBuffer(); + offset += sizeof(int); + SCARD_DEBUG("certificate count [%d]", count); + +// for (i = 0; i < count; i++) + if (count > 0) + { + /* certificate length */ + length = *(int *)certArray.getBuffer(offset); + offset += sizeof(int); + SCARD_DEBUG("certificate length [%d]", length); + + /* certificate byte stream */ + cert.setBuffer(certArray.getBuffer(offset), length); + offset += length; + + SCARD_DEBUG("certificate buffer [%d] : %s", cert.getLength(), cert.toString()); + + /* sha1 digest */ + if (OpensslHelper::digestBuffer("sha1", cert, result) == true) + { + SCARD_DEBUG("digest[%d] : %s", result.getLength(), result.toString()); + } + else + { + SCARD_DEBUG_ERR("digestBuffer failed"); + } + } + else + { + SCARD_DEBUG_ERR("invalid certificate count [%d]", count); + } + } + else + { + SCARD_DEBUG_ERR("decodeBase64String failed"); + } + } + else + { + SCARD_DEBUG_ERR("certList.size is zero"); + } + + return result; + } + + ByteArray SignatureHelper::getCertificationHash(int pid) + { + ByteArray result; + int error = 0; + char pkgName[256] = { 0, }; + + if ((error = aul_app_get_pkgname_bypid(pid, pkgName, sizeof(pkgName))) == 0) + { + result = getCertificationHash(pkgName); + } + else + { + SCARD_DEBUG_ERR("aul_app_get_pkgname_bypid failed [%d]", error); + } + + return result; + } + +} /* namespace smartcard_service_api */ + +/* export C API */ +using namespace smartcard_service_api; + +EXTERN_API int signature_helper_get_certificate_hash(const char *packageName, uint8_t *hash, uint32_t *length) +{ + int ret = -1; + ByteArray result; + + if (packageName == NULL || strlen(packageName) == 0 || hash == NULL || length == NULL || *length < 20) + return ret; + + result = SignatureHelper::getCertificationHash(packageName); + + if (result.isEmpty() == false) + { + memcpy(hash, result.getBuffer(), (result.getLength() < *length) ? result.getLength() : *length); + *length = result.getLength(); + + ret = 0; + } + else + { + ret = -1; + } + + return ret; +} + +EXTERN_API int signature_helper_get_certificate_hash_by_pid(int pid, uint8_t *hash, uint32_t *length) +{ + int ret = -1; + ByteArray result; + + if (pid < 0 || hash == NULL || length == NULL || *length < 20) + return ret; + + result = SignatureHelper::getCertificationHash(pid); + + if (result.isEmpty() == false && result.getLength() < *length) + { + memcpy(hash, result.getBuffer(), result.getLength()); + *length = result.getLength(); + + ret = 0; + } + else + { + ret = -1; + } + + return ret; +} + +EXTERN_API int signature_helper_get_process_name(int pid, char *processName, uint32_t length) +{ + int ret = -1; + + if (pid < 0 || processName == NULL || length == 0) + return ret; + + ret = SignatureHelper::getProcessName(pid, processName, length); + + return ret; +} + diff --git a/common/SimpleTLV.cpp b/common/SimpleTLV.cpp new file mode 100644 index 0000000..84da755 --- /dev/null +++ b/common/SimpleTLV.cpp @@ -0,0 +1,250 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "SimpleTLV.h" + +namespace smartcard_service_api +{ + SimpleTLV::SimpleTLV():TLVHelper() + { + } + + SimpleTLV::SimpleTLV(TLVHelper *parent):TLVHelper(parent) + { + parentTLV = parent; + } + + SimpleTLV::SimpleTLV(const ByteArray &array):TLVHelper(array) + { + } + + SimpleTLV::SimpleTLV(const ByteArray &array, TLVHelper *parent):TLVHelper(array, parent) + { + parentTLV = parent; + } + + SimpleTLV::~SimpleTLV() + { + if (childTLV != NULL) + { + delete childTLV; + childTLV = NULL; + } + } + + int SimpleTLV::decodeTag(unsigned char *buffer) + { + /* 0x00 or 0xFF is invalid tag value */ + if (buffer[0] == 0x00 || buffer[0] == 0xFF) + { + return -1; + } + + currentT = buffer[0]; + + return 1; + } + + int SimpleTLV::decodeLength(unsigned char *buffer) + { + int count = 0; + + if (buffer[0] == 0xFF) + { + /* 3 bytes length */ + currentL = (buffer[1] << 8) | buffer[2]; + count = 3; + } + else + { + /* 1 byte length */ + currentL = buffer[0]; + count = 1; + } + + return count; + } + + int SimpleTLV::decodeValue(unsigned char *buffer) + { + if (currentL == 0) + return 0; + + currentV.setBuffer(buffer, currentL); + + return currentL; + } + + ByteArray SimpleTLV::encode(unsigned int tag, ByteArray buffer) + { + bool isLongBuffer = false; + ByteArray result; + unsigned int total_len = 0; + unsigned int current = 0; + unsigned char *temp_buffer = NULL; + + /* add tag's length */ + total_len += 1; + + /* add length's length */ + if (buffer.getLength() < 255) + { + total_len += 1; + } + else if (buffer.getLength() < 65536) + { + total_len += 3; + isLongBuffer = true; + } + else + { + return result; + } + + /* add buffer's length */ + total_len += buffer.getLength(); + + /* alloc new buffer */ + temp_buffer = new unsigned char[total_len]; + if (temp_buffer == NULL) + { + return result; + } + memset(temp_buffer, 0, total_len); + + /* fill tag */ + temp_buffer[current++] = (unsigned char)tag; + + /* fill length */ + if (isLongBuffer == true) + { + temp_buffer[current++] = (unsigned char)(0xFF); + temp_buffer[current++] = (unsigned char)(buffer.getLength() >> 8); + temp_buffer[current++] = (unsigned char)(buffer.getLength()); + } + else + { + temp_buffer[current++] = (unsigned char)(buffer.getLength()); + } + + /* fill value */ + if (buffer.getLength() > 0) + memcpy(temp_buffer + current, buffer.getBuffer(), buffer.getLength()); + + result.setBuffer(temp_buffer, total_len); + + delete []temp_buffer; + + return result; + } + + ByteArray SimpleTLV::encode(unsigned int tag, unsigned char *buffer, unsigned int length) + { + return encode(tag, ByteArray(buffer, length)); + } + + TLVHelper *SimpleTLV::getChildTLV(ByteArray data) + { + if (childTLV != NULL) + { + delete childTLV; + childTLV = NULL; + } + childTLV = new SimpleTLV(data, this); + + return (TLVHelper *)childTLV; + } + + ByteArray SimpleTLV::getOctetString(const ByteArray &array) + { + SimpleTLV tlv(array); + + return SimpleTLV::getOctetString(tlv); + } + + ByteArray SimpleTLV::getOctetString(SimpleTLV &tlv) + { + ByteArray result; + + if (tlv.decodeTLV() == true && tlv.getTag() == 0x04) /* OCTET STRING */ + { + result = tlv.getValue(); + } + else + { + SCARD_DEBUG_ERR("getOctetString failed (0x%02X)", tlv.getTag()); + } + + return result; + } + + bool SimpleTLV::getBoolean(const ByteArray &array) + { + SimpleTLV tlv(array); + + return SimpleTLV::getBoolean(tlv); + } + + bool SimpleTLV::getBoolean(SimpleTLV &tlv) + { + bool result = false; + + if (tlv.decodeTLV() == true && tlv.getTag() == 0x80) /* BOOLEAN */ + { + if (tlv.getValue().getAt(0) == 0) + result = false; + else + result = true; + } + else + { + SCARD_DEBUG_ERR("getBoolean failed (0x%02X)", tlv.getTag()); + } + + return result; + } + + int SimpleTLV::getInteger(const ByteArray &array) + { + SimpleTLV tlv(array); + + return SimpleTLV::getInteger(tlv); + } + + int SimpleTLV::getInteger(SimpleTLV &tlv) + { + int result = 0; + + if (tlv.decodeTLV() == true && tlv.getTag() == 0x80) /* TODO : INTEGER */ + { + } + else + { + SCARD_DEBUG_ERR("getInteger failed (0x%02X)", tlv.getTag()); + } + + return result; + } +} /* namespace smartcard_service_api */ diff --git a/common/Synchronous.cpp b/common/Synchronous.cpp new file mode 100644 index 0000000..3a6d027 --- /dev/null +++ b/common/Synchronous.cpp @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Synchronous.h" + +namespace smartcard_service_api +{ + Synchronous::Synchronous() + { + pthread_mutex_init(&syncMutex, NULL); + pthread_cond_init(&syncCondition, NULL); + } + + void Synchronous::syncLock() + { + pthread_mutex_lock(&syncMutex); + } + + void Synchronous::syncUnlock() + { + pthread_mutex_unlock(&syncMutex); + } + + int Synchronous::waitTimedCondition(int second) + { + struct timeval now; + struct timespec ts; + int result; + + if (second > 0) + { + gettimeofday(&now, NULL); + ts.tv_sec = now.tv_sec + second; + ts.tv_nsec = now.tv_usec * 1000; + + result = pthread_cond_timedwait(&syncCondition, &syncMutex, &ts); + } + else + { + result = pthread_cond_wait(&syncCondition, &syncMutex); + } + + return result; + } + + void Synchronous::signalCondition() + { + pthread_cond_signal(&syncCondition); + } + +} /* namespace smartcard_service_api */ diff --git a/common/TLVHelper.cpp b/common/TLVHelper.cpp new file mode 100644 index 0000000..87fb650 --- /dev/null +++ b/common/TLVHelper.cpp @@ -0,0 +1,174 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "TLVHelper.h" + +namespace smartcard_service_api +{ + void TLVHelper::initialize(TLVHelper *parent) + { + parentTLV = parent; + childTLV = NULL; + currentTLV = this; + offset = 0; + currentT = 0; + currentL = 0; + } + + TLVHelper::TLVHelper() + { + initialize(); + } + + TLVHelper::TLVHelper(TLVHelper *parent) + { + initialize(parent); + } + + TLVHelper::TLVHelper(const ByteArray &array) + { + setTLVBuffer(array); + } + + TLVHelper::TLVHelper(const ByteArray &array, TLVHelper *parent) + { + setTLVBuffer(array, parent); + } + + TLVHelper::~TLVHelper() + { + } + + bool TLVHelper::setTLVBuffer(const ByteArray &array, TLVHelper *parent) + { + initialize(parent); + + if (array.getLength() == 0) + return false; + + tlvBuffer = array; + + return true; + } + + bool TLVHelper::setTLVBuffer(unsigned char *buffer, unsigned int length, TLVHelper *parent) + { + return setTLVBuffer(ByteArray(buffer, length), parent); + } + + bool TLVHelper::_decodeTLV() + { + int result; + + currentT = 0; + currentL = 0; + currentV.releaseBuffer(); + + if (isEndOfBuffer()) + return false; + + /* T */ + if ((result = decodeTag(tlvBuffer.getBuffer(offset))) < 0) + return false; + + offset += result; + + /* L */ + if ((result = decodeLength(tlvBuffer.getBuffer(offset))) < 0) + return false; + + offset += result; + + if (currentL > 0) + { + /* V */ + if ((result = decodeValue(tlvBuffer.getBuffer(offset))) < 0) + return false; + + offset += result; + } + + return true; + } + + const char *TLVHelper::toString() + { + memset(strBuffer, 0, sizeof(strBuffer)); + + if (currentL == 0) + { + snprintf(strBuffer, sizeof(strBuffer), "T [%X], L [%d]", getTag(), getLength()); + } + else + { + snprintf(strBuffer, sizeof(strBuffer), "T [%X], L [%d], V %s", getTag(), getLength(), getValue().toString()); + } + + return strBuffer; + } + + TLVHelper *TLVHelper::getParentTLV() + { + return parentTLV; + } + + bool TLVHelper::enterToValueTLV() + { + bool result = false; + TLVHelper *temp = NULL; + + if (getLength() >= 2) + { + temp = currentTLV->getChildTLV(getValue()); + + if (temp != NULL) + { + currentTLV = temp; + result = true; + } + } + + return result; + } + + bool TLVHelper::returnToParentTLV() + { + bool result = true; + +// SCARD_DEBUG("current [%p], parent [%p]", currentTLV, currentTLV->getParentTLV()); + + if (currentTLV->getParentTLV() != NULL) + { + currentTLV = currentTLV->getParentTLV(); + } + else + { + /* top tlv */ + } + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/common/include/APDUHelper.h b/common/include/APDUHelper.h new file mode 100644 index 0000000..b1aa404 --- /dev/null +++ b/common/include/APDUHelper.h @@ -0,0 +1,159 @@ +/* +* Copyright (c) 2012 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 APDUHELPER_H_ +#define APDUHELPER_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class ResponseHelper + { + private: + ByteArray response; + unsigned char sw[2]; + int status; + ByteArray dataField; + + static int parseStatusWord(unsigned char *sw); + public: + ResponseHelper(); + ResponseHelper(const ByteArray &response); + ~ResponseHelper(); + + bool setResponse(const ByteArray &response); + int getStatus(); +// char *getErrorString(); + ByteArray getDataField(); + + static int getStatus(const ByteArray &response); + static ByteArray getDataField(const ByteArray &response); +// static char *getErrorString(); + }; + + class APDUCommand + { + private: + typedef struct _command_header_t + { + unsigned char cla; + unsigned char ins; + unsigned char param[2]; + } command_header_t; + + command_header_t header; + ByteArray commandData; + unsigned int maxResponseSize; + bool isExtendedLength; + + public: + static const unsigned char INS_DEACTIVATE_FILE = (unsigned char)0x04; + static const unsigned char INS_TERMINAL_PROFILE = (unsigned char)0x10; + static const unsigned char INS_TERMINAL_RESPONSE = (unsigned char)0x14; + static const unsigned char INS_VERIFY = (unsigned char)0x20; + static const unsigned char INS_CHANGE_PIN = (unsigned char)0x24; + static const unsigned char INS_DISABLE_PIN = (unsigned char)0x26; + static const unsigned char INS_ENABLE_PIN = (unsigned char)0x28; + static const unsigned char INS_UNBLOCK_PIN = (unsigned char)0x2C; + static const unsigned char INS_INCREASE = (unsigned char)0x32; + static const unsigned char INS_ACTIVATE_FILE = (unsigned char)0x44; + static const unsigned char INS_GET_CHALLENGE = (unsigned char)0x84; + static const unsigned char INS_AUTHENTICATE = (unsigned char)0x88; + static const unsigned char INS_AUTHENTICATE2 = (unsigned char)0x89; + static const unsigned char INS_MANAGE_CHANNEL = (unsigned char)0x70; + static const unsigned char INS_SEARCH_RECORD = (unsigned char)0xA2; + static const unsigned char INS_SELECT_FILE = (unsigned char)0xA4; + static const unsigned char INS_TERMINAL_CAPABILITY = (unsigned char)0xAA; + static const unsigned char INS_READ_BINARY = (unsigned char)0xB0; + static const unsigned char INS_READ_RECORD = (unsigned char)0xB2; + static const unsigned char INS_GET_RESPONSE = (unsigned char)0xC0; + static const unsigned char INS_RETRIEVE_DATA = (unsigned char)0xCB; + static const unsigned char INS_WRITE_BINARY = (unsigned char)0xD0; + static const unsigned char INS_UPDATE_BINARY = (unsigned char)0xD6; + static const unsigned char INS_UPDATE_RECORD = (unsigned char)0xDC; + static const unsigned char INS_SET_DATA = (unsigned char)0xDB; + static const unsigned char INS_CREATE_FILE = (unsigned char)0xE0; + static const unsigned char INS_APPEND_RECORD = (unsigned char)0xE2; + static const unsigned char INS_DELETE_FILE = (unsigned char)0xE4; + static const unsigned char INS_STATUS = (unsigned char)0xF2; +// static const unsigned char INS_ = (unsigned char)0x; + + static const unsigned char P1_SELECT_BY_ID = (unsigned char)0x00; + static const unsigned char P1_SELECT_PARENT_DF = (unsigned char)0x03; + static const unsigned char P1_SELECT_BY_DF_NAME = (unsigned char)0x04; + static const unsigned char P1_SELECT_BY_PATH = (unsigned char)0x08; + static const unsigned char P1_SELECT_BY_PATH_FROM_CURRENT_DF = (unsigned char)0x09; +// static const unsigned char P1_ = (unsigned char)0x; + + static const unsigned char P2_SELECT_GET_FCP = (unsigned char)0x04; +// static const unsigned char P2_ = (unsigned char)0x; + + APDUCommand(); + ~APDUCommand(); + + bool setCommand(unsigned char cla, unsigned char ins, unsigned char p1, unsigned char p2, ByteArray commandData, unsigned int maxResponseSize); + bool setCommand(const ByteArray &command); + + bool setChannel(int type, int channelNum); + + void setCLA(unsigned char cla); + unsigned char getCLA(); + + void setINS(unsigned char ins); + unsigned char getINS(); + + void setP1(unsigned char p1); + unsigned char getP1(); + + void setP2(unsigned char p2); + unsigned char getP2(); + + void setCommandData(const ByteArray &data); + ByteArray getCommandData(); + + void setMaxResponseSize(unsigned int maxResponseSize); + unsigned int setMaxResponseSize(); + + bool getBuffer(ByteArray &array); + }; + + class APDUHelper + { + public: + static const int COMMAND_OPEN_LOGICAL_CHANNEL = 1; + static const int COMMAND_CLOSE_LOGICAL_CHANNEL = 2; + static const int COMMAND_SELECT_BY_ID = 3; + static const int COMMAND_SELECT_PARENT_DF = 4; + static const int COMMAND_SELECT_BY_DF_NAME = 5; + static const int COMMAND_SELECT_BY_PATH = 6; + static const int COMMAND_SELECT_BY_PATH_FROM_CURRENT_DF = 7; + static const int COMMAND_READ_BINARY = 8; + static const int COMMAND_READ_RECORD = 9; + static const int COMMAND_WRITE_BINARY = 10; + static const int COMMAND_WRITE_RECORD = 11; + + static ByteArray generateAPDU(int command, int channel, ByteArray data); + }; + +} /* namespace smartcard_service_api */ +#endif /* APDUHELPER_H_ */ diff --git a/common/include/AccessCondition.h b/common/include/AccessCondition.h new file mode 100644 index 0000000..35f38de --- /dev/null +++ b/common/include/AccessCondition.h @@ -0,0 +1,92 @@ +/* +* Copyright (c) 2012 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 ACCESSCONDITION_H_ +#define ACCESSCONDITION_H_ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +using namespace std; + +namespace smartcard_service_api +{ + class APDUAccessRule + { + private : + bool permission; + map mapApduFilters; + + public : + APDUAccessRule() + { + permission = true; + } + + void loadAPDUAccessRule(const ByteArray &data); + bool isAuthorizedAccess(const ByteArray &command); + + void printAPDUAccessRules(); + }; + + class NFCAccessRule + { + private : + bool permission; + + public : + NFCAccessRule() + { + permission = true; + } + + void loadNFCAccessRule(const ByteArray &data); + bool isAuthorizedAccess(void); + + void printNFCAccessRules(); + }; + + class AccessCondition + { + private : + bool permission; + ByteArray aid; + vector hashes; + APDUAccessRule apduRule; + NFCAccessRule nfcRule; + + public : + AccessCondition() : permission(false) + { + } + + void loadAccessCondition(ByteArray &aid, ByteArray &data); + bool isAuthorizedAccess(ByteArray &certHash); + bool isAuthorizedAPDUAccess(ByteArray &command); + bool isAuthorizedNFCAccess(); + + void printAccessConditions(); + }; + +} /* namespace smartcard_service_api */ +#endif /* ACCESSCONDITION_H_ */ diff --git a/common/include/AccessControlList.h b/common/include/AccessControlList.h new file mode 100644 index 0000000..e13d08a --- /dev/null +++ b/common/include/AccessControlList.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2012 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 ACCESSCONTROLLIST_H_ +#define ACCESSCONTROLLIST_H_ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" +#include "Channel.h" + +using namespace std; + +namespace smartcard_service_api +{ + class Terminal; + class AccessCondition; + + class AccessControlList + { + protected: + map mapConditions; + Channel *channel; + Terminal *terminal; + + void printAccessControlList(); + + public: + static ByteArray AID_ALL; + static ByteArray AID_DEFAULT; + + AccessControlList(); + AccessControlList(Channel *channel); + AccessControlList(Terminal *terminal); + ~AccessControlList(); + + int setChannel(Channel *channel); + virtual int setTerminal(Terminal *terminal) { this->terminal = terminal; return 0; } + + virtual int loadACL() = 0; + + int updateACL(); + void releaseACL(); + + bool isAuthorizedAccess(ByteArray aid, ByteArray certHash); + bool isAuthorizedAccess(unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength); + }; + +} /* namespace smartcard_service_api */ +#endif /* ACCESSCONTROLLIST_H_ */ diff --git a/common/include/ByteArray.h b/common/include/ByteArray.h new file mode 100644 index 0000000..66fe588 --- /dev/null +++ b/common/include/ByteArray.h @@ -0,0 +1,81 @@ +/* +* Copyright (c) 2012 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 BYTEARRAY_H_ +#define BYTEARRAY_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +//#include "Serializable.h" + +#define ARRAY_AND_SIZE(x) (uint8_t *)(&x), sizeof(x) + +namespace smartcard_service_api +{ + class ByteArray //: public Serializable + { + protected: + uint8_t *buffer; + uint32_t length; + char strBuffer[100]; + + bool _setBuffer(uint8_t *array, uint32_t bufferLen); + void save(const char *filePath); + + public: + static ByteArray EMPTY; + + ByteArray(); + ByteArray(uint8_t *array, uint32_t bufferLen); + ByteArray(const ByteArray &T); + ~ByteArray(); + +// ByteArray serialize(); +// void deserialize(ByteArray buffer); + + bool setBuffer(uint8_t *array, uint32_t bufferLen); + void releaseBuffer(); + + uint32_t getLength() const; + uint8_t *getBuffer() const; + uint8_t *getBuffer(uint32_t offset) const; + + uint8_t getAt(uint32_t index) const; + uint8_t getReverseAt(uint32_t index) const; + + uint32_t copyFromArray(uint8_t *array, uint32_t bufferLen) const; + + /* operator overloading */ + ByteArray &operator =(const ByteArray &T); + ByteArray operator +(const ByteArray &T); + ByteArray &operator +=(const ByteArray &T); + bool operator ==(const ByteArray &T) const; + bool operator !=(const ByteArray &T) const; + bool operator <(const ByteArray &T) const; + bool operator >(const ByteArray &T) const; + uint8_t &operator [](uint32_t index) const; + + inline bool isEmpty() { return (buffer == (void *)0 || length == 0); } + const char *toString(); + }; + +} /* namespace smartcard_service_api */ +#endif /* BYTEARRAY_H_ */ diff --git a/common/include/Channel.h b/common/include/Channel.h new file mode 100644 index 0000000..e4c29ba --- /dev/null +++ b/common/include/Channel.h @@ -0,0 +1,74 @@ +/* +* Copyright (c) 2012 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 CHANNEL_H_ +#define CHANNEL_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Synchronous.h" +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class SessionHelper; /* explicit declaration */ + + typedef void (*transmitCallback)(unsigned char *buffer, unsigned int length, int error, void *userParam); + typedef void (*closeCallback)(int error, void *userParam); + + class Channel : public Synchronous + { + protected: + ByteArray selectResponse; + SessionHelper *session; + int channelNum; + + Channel() : Synchronous() + { + channelNum = -1; + } + Channel(SessionHelper *session) : Synchronous() + { + this->session = session; + } + + virtual void closeSync() = 0; + virtual int transmitSync(ByteArray command, ByteArray &result) = 0; + + public: + virtual ~Channel() {} + + virtual int close(closeCallback callback, void *userParam) = 0; + inline bool isBasicChannel() const { return (channelNum == 0); } + inline bool isClosed() const { return (channelNum < 0); } + + inline ByteArray getSelectResponse() const { return selectResponse; } + inline SessionHelper *getSession() const { return session; } + virtual int transmit(ByteArray command, transmitCallback callback, void *userData) = 0; + + friend class FileObject; + friend class ServerSession; + friend class ServerChannel; + friend class ServerDispatcher; + friend class ServerResource; + }; + +} /* namespace smartcard_service_api */ +#endif /* CHANNEL_H_ */ diff --git a/common/include/Debug.h b/common/include/Debug.h new file mode 100644 index 0000000..c5e2a77 --- /dev/null +++ b/common/include/Debug.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2012 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 DEBUG_H_ +#define DEBUG_H_ + +/* standard library header */ + +/* SLP library header */ +#include "dlog.h" + +/* local header */ + +#define COLOR_RED "\033[0;31m" +#define COLOR_GREEN "\033[0;32m" +#define COLOR_BROWN "\033[0;33m" +#define COLOR_BLUE "\033[0;34m" +#define COLOR_PURPLE "\033[0;35m" +#define COLOR_CYAN "\033[0;36m" +#define COLOR_LIGHTBLUE "\033[0;37m" +#define COLOR_END "\033[0;m" + +#define SCARD_DEBUG(fmt, ...)\ + do\ + {\ + LOGD("[%s(): %d] " fmt, __FUNCTION__, __LINE__,##__VA_ARGS__);\ + } while (0) + +#define SCARD_DEBUG_ERR(fmt, ...)\ + do\ + {\ + LOGE(COLOR_RED"[%s(): %d] " fmt COLOR_END, __FUNCTION__, __LINE__,##__VA_ARGS__);\ + }while (0) + +#define SCARD_BEGIN() \ + do\ + {\ + LOGD(COLOR_BLUE"[%s(): %d] BEGIN >>>>"COLOR_END, __FUNCTION__ ,__LINE__);\ + } while( 0 ) + +#define SCARD_END() \ + do\ + {\ + LOGD(COLOR_BLUE"[%s(): %d] END <<<<"COLOR_END, __FUNCTION__,__LINE__ );\ + } \ + while( 0 ) + +#endif /* DEBUG_H_ */ diff --git a/common/include/DispatcherHelper.h b/common/include/DispatcherHelper.h new file mode 100644 index 0000000..7d8a81f --- /dev/null +++ b/common/include/DispatcherHelper.h @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2012 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 DISPATCHERHELPER_H_ +#define DISPATCHERHELPER_H_ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Synchronous.h" +#include "DispatcherMsg.h" + +using namespace std; + +namespace smartcard_service_api +{ + class DispatcherHelper : public Synchronous + { + private: + pthread_t dispatcherThread; + + queue messageQ; + + static void *_dispatcherThreadFunc(void *data); + + DispatcherMsg *fetchMessage(); + + protected: + virtual void *dispatcherThreadFunc(DispatcherMsg *msg, void *data) = 0; + + public: + DispatcherHelper(); + ~DispatcherHelper(); + + void clearQueue(); + + void pushMessage(DispatcherMsg *msg); + + bool runDispatcherThread(); + void stopDispatcherThread(); + + friend void *_dispatcherThreadFunc(void *data); + }; + +} /* namespace smartcard_service_api */ +#endif /* DISPATCHERHELPER_H_ */ diff --git a/common/include/DispatcherMsg.h b/common/include/DispatcherMsg.h new file mode 100644 index 0000000..426f31f --- /dev/null +++ b/common/include/DispatcherMsg.h @@ -0,0 +1,74 @@ +/* +* Copyright (c) 2012 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 DISPATCHERMSG_H_ +#define DISPATCHERMSG_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Message.h" + +namespace smartcard_service_api +{ + class DispatcherMsg: public Message + { + private: + int peerSocket; + + public: + DispatcherMsg():Message() + { + peerSocket = -1; + } + + DispatcherMsg(Message *msg):Message() + { + peerSocket = -1; + message = msg->message; + param1 = msg->param1; + param2 = msg->param2; + error = msg->error; + data = msg->data; + caller = msg->caller; + callback = msg->callback; + userParam = msg->userParam; + } + + DispatcherMsg(Message *msg, int socket):Message() + { + peerSocket = socket; + message = msg->message; + param1 = msg->param1; + param2 = msg->param2; + error = msg->error; + data = msg->data; + caller = msg->caller; + callback = msg->callback; + userParam = msg->userParam; + } + + ~DispatcherMsg() {} + + inline int getPeerSocket() { return peerSocket; } + inline void setPeerSocket(int socket) { peerSocket = socket; } + }; + +} /* namespace smartcard_service_api */ +#endif /* DISPATCHERMSG_H_ */ diff --git a/common/include/FCI.h b/common/include/FCI.h new file mode 100644 index 0000000..8fea754 --- /dev/null +++ b/common/include/FCI.h @@ -0,0 +1,113 @@ +/* +* Copyright (c) 2012 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 FCI_H_ +#define FCI_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class FCP + { + private: + ByteArray fcpBuffer; + + char strBuffer[400]; + + unsigned int fileSize; + unsigned int totalFileSize; + unsigned int fid; + unsigned int sfi; + unsigned int maxRecordSize; + unsigned int numberOfRecord; + unsigned int fileType; + unsigned int fileStructure; + unsigned int lcs; + + void resetMemberVar(); + + public: + FCP(); + FCP(ByteArray &array); + ~FCP(); + + bool setFCP(ByteArray array); + ByteArray getFCP(); + void releaseFCP(); + + unsigned int getFileSize(); + unsigned int getTotalFileSize(); + unsigned int getFID(); + unsigned int getSFI(); + unsigned int getMaxRecordSize(); + unsigned int getNumberOfRecord(); + unsigned int getFileType(); + unsigned int getFileStructure(); + unsigned int getLCS(); + + const char *toString(); + }; + + class FCM + { + private: + ByteArray fcmBuffer; + + public: + FCM(); + virtual ~FCM(); + }; + + class FCI + { + private: + ByteArray fciBuffer; + FCP fcp; + FCM fcm; + + public: + static const int INFO_NOT_AVAILABLE = -1; + + static const int FT_DF = 0; + static const int FT_EF = 1; + + static const int FS_NO_EF = 0; + static const int FS_TRANSPARENT = 1; + static const int FS_LINEAR_FIXED = 2; + static const int FS_LINEAR_VARIABLE = 3; + static const int FS_CYCLIC = 4; + + static const int LCS_NO_INFORMATION_GIVEN = 0; + static const int LCS_CREATION_STATE = 1; + static const int LCS_INITIALISATION_STATE = 3; + static const int LCS_OPERATION_STATE_ACTIVATED = 5; + static const int LCS_OPERATION_STATE_DEACTIVATED = 4; + static const int LCS_TERMINATION_STATE = 6; + + FCI(); + ~FCI(); + + bool setFCIBuffer(ByteArray array); + }; + +} /* namespace smartcard_service_api */ +#endif /* FCI_H_ */ diff --git a/common/include/FileObject.h b/common/include/FileObject.h new file mode 100644 index 0000000..15f4254 --- /dev/null +++ b/common/include/FileObject.h @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2012 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 FILEOBJECT_H_ +#define FILEOBJECT_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "ProviderHelper.h" +#include "ByteArray.h" +#include "FCI.h" +#include "Record.h" + +using namespace std; + +namespace smartcard_service_api +{ + class FileObject : public ProviderHelper + { + private: + FCI fci; + FCP fcp; + + protected: + ByteArray selectResponse; + bool setSelectResponse(ByteArray response); + + public: + static const int SUCCESS = 0; + static const int ERROR_ILLEGAL_STATE = -1; + static const int ERROR_ILLEGAL_REFERENCE = -2; + static const int ERROR_ILLEGAL_PARAMETER = -3; + static const int ERROR_SECURITY = -4; + static const int ERROR_OPERATION_NOT_SUPPORT = -5; + static const int ERROR_IO = -6; + static const int ERROR_UNKNOWN = -99; + + FileObject(Channel *channel); + FileObject(Channel *channel, ByteArray selectResponse); + ~FileObject(); + + int select(ByteArray aid); + int select(ByteArray path, bool fromCurrentDF); + int select(unsigned int fid); + int selectParent(); + + FCI *getFCI(); + FCP *getFCP(); + + int readRecord(unsigned int sfi, unsigned int recordId, Record &result); + int writeRecord(unsigned int sfi, Record record); + + int searchRecord(unsigned int sfi, ByteArray searchParam, vector &result); + + int readBinary(unsigned int sfi, unsigned int offset, unsigned int length, ByteArray &result); + int writeBinary(unsigned int sfi, ByteArray data, unsigned int offset, unsigned int length); + }; + +} /* namespace smartcard_service_api */ +#endif /* FILEOBJECT_H_ */ diff --git a/common/include/GPSEACL.h b/common/include/GPSEACL.h new file mode 100644 index 0000000..efde39e --- /dev/null +++ b/common/include/GPSEACL.h @@ -0,0 +1,77 @@ +/* +* Copyright (c) 2012 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 GPSEACL_H_ +#define GPSEACL_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "AccessControlList.h" +#include "PKCS15.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class GPSEACL: public AccessControlList + { + private: + PKCS15 *pkcs15; + ByteArray refreshTag; + + static ByteArray OID_GLOBALPLATFORM; + + int loadAccessControl(PKCS15DODF *dodf); + int loadRules(ByteArray path); + int loadAccessConditions(ByteArray aid, ByteArray path); + + public: + GPSEACL(Channel *channel); + ~GPSEACL(); + + int loadACL(); + + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +typedef void *gp_se_acl_h; + +gp_se_acl_h gp_se_acl_create_instance(channel_h channel); +int gp_se_acl_load_acl(gp_se_acl_h handle); +int gp_se_acl_update_acl(gp_se_acl_h handle); +void gp_se_acl_release_acl(gp_se_acl_h handle); +bool gp_se_acl_is_authorized_access(gp_se_acl_h handle, unsigned char *aidBuffer, unsigned int aidLength, unsigned char *certHashBuffer, unsigned int certHashLength); +void gp_se_acl_destroy_instance(gp_se_acl_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* GPSEACL_H_ */ diff --git a/common/include/IPCHelper.h b/common/include/IPCHelper.h new file mode 100644 index 0000000..b038a35 --- /dev/null +++ b/common/include/IPCHelper.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2012 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 IPCHELPER_H_ +#define IPCHELPER_H_ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Message.h" +#include "DispatcherHelper.h" + +namespace smartcard_service_api +{ + class IPCHelper + { + protected: + static const int IPC_SERVER_PORT = 8989; + static const int IPC_SERVER_MAX_CLIENT = 10; + + int ipcSocket; + unsigned int watchId; + GIOChannel *ioChannel; + pthread_mutex_t ipcLock; + DispatcherHelper *dispatcher; + + static gboolean channelCallbackFunc(GIOChannel* channel, GIOCondition condition, gpointer data); + + virtual int handleIOErrorCondition(void *channel, GIOCondition condition) = 0; + virtual int handleInvalidSocketCondition(void *channel, GIOCondition condition) = 0; + virtual int handleIncomingCondition(void *channel, GIOCondition condition) = 0; + + public: + IPCHelper(); + ~IPCHelper(); + + bool createListenSocket(); + bool createConnectSocket(); + + bool sendMessage(Message *msg); + bool sendMessage(int socket, Message *msg); + Message *retrieveMessage(); + Message *retrieveMessage(int socket); + + void setDispatcher(DispatcherHelper *dispatcher); + + friend gboolean channelCallbackFunc(GIOChannel* channel, GIOCondition condition, gpointer data); + }; + +} /* namespace smartcard_service_api */ +#endif /* IPCHELPER_H_ */ diff --git a/common/include/ISO7816BERTLV.h b/common/include/ISO7816BERTLV.h new file mode 100644 index 0000000..29ca561 --- /dev/null +++ b/common/include/ISO7816BERTLV.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2012 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 ISO7816BERTLV_H_ +#define ISO7816BERTLV_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" +#include "TLVHelper.h" + +namespace smartcard_service_api +{ + class ISO7816BERTLV: public TLVHelper + { + private: +// ISO7816BERTLV child; + + unsigned char firstByte; + unsigned int tagClass; + unsigned int encoding; + + ISO7816BERTLV(TLVHelper *parent); + ISO7816BERTLV(const ByteArray &array, TLVHelper *parent); + + int decodeTag(unsigned char *buffer); + int decodeLength(unsigned char *buffer); + int decodeValue(unsigned char *buffer); + + TLVHelper *getChildTLV(ByteArray data); + + public: + ISO7816BERTLV(); + ISO7816BERTLV(const ByteArray &array); + ~ISO7816BERTLV(); + + unsigned int getClass(); + unsigned int getEncoding(); + + static ByteArray encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, ByteArray buffer); + static ByteArray encode(unsigned int tagClass, unsigned int encoding, unsigned int tag, unsigned char *buffer, unsigned int length); + }; + +} /* namespace smartcard_service_api */ +#endif /* ISO7816BERTLV_H_ */ diff --git a/common/include/Lock.h b/common/include/Lock.h new file mode 100644 index 0000000..89a2aff --- /dev/null +++ b/common/include/Lock.h @@ -0,0 +1,82 @@ +/* +* Copyright (c) 2012 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 LOCK_H_ +#define LOCK_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "pthread.h" + +namespace smartcard_service_api +{ + class Lock + { + public: + virtual ~Lock() {}; + virtual void lock() = 0; + virtual void unlock() = 0; + }; + + class PMutex : public Lock + { + private: + pthread_mutex_t mutex; + + public: + PMutex() { pthread_mutex_init(&mutex, NULL); } + ~PMutex() { pthread_mutex_destroy(&mutex); } + + inline void lock() { pthread_mutex_lock(&mutex); } + inline void unlock() { pthread_mutex_unlock(&mutex); } + }; +#define TOKENPASTE(x, y) x ## y +#define TOKENPASTE2(x, y) TOKENPASTE(x, y) +#define SCOPE_LOCK(X) \ + if (const AutoLockHelper& TOKENPASTE2(lock_, __LINE__) = makeAutoLock(X)) + + class AutoLockHelper + { + public: + inline operator bool() const + { + return true; + } + }; + + template + class AutoLock : public AutoLockHelper + { + private: + T *lock; + + public: + AutoLock(const AutoLock &_lock) { lock = _lock.lock; } + AutoLock(T& _lock) : lock(&_lock) { lock->lock(); } + ~AutoLock() { lock->unlock(); } + }; + + template + inline AutoLock makeAutoLock(T& lock) + { + return AutoLock(lock); + } + +} /* namespace smartcard_service_api */ +#endif /* SCOPELOCK_H_ */ diff --git a/common/include/Message.h b/common/include/Message.h new file mode 100644 index 0000000..26bcdcf --- /dev/null +++ b/common/include/Message.h @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2012 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 MESSAGE_H_ +#define MESSAGE_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Serializable.h" + +namespace smartcard_service_api +{ + class Message: public Serializable + { + private: + char text[200]; + + public: + static const int MSG_REQUEST_READERS = 0x80; + static const int MSG_REQUEST_SHUTDOWN = 0x81; + static const int MSG_REQUEST_OPEN_SESSION = 0x82; + static const int MSG_REQUEST_CLOSE_SESSION = 0x83; + static const int MSG_REQUEST_OPEN_CHANNEL = 0x84; + static const int MSG_REQUEST_CLOSE_CHANNEL = 0x85; + static const int MSG_REQUEST_GET_ATR = 0x86; + static const int MSG_REQUEST_TRANSMIT = 0x87; + static const int MSG_REQUEST_GET_CHANNEL_COUNT = 0x88; + + static const int MSG_NOTIFY_SE_REMOVED = 0x90; + static const int MSG_NOTIFY_SE_INSERTED = 0x91; + + static const int MSG_OPERATION_RELEASE_CLIENT = 0xC0; + + unsigned int message; + unsigned int param1; + unsigned int param2; + ByteArray data; + int error; + void *caller; + void *callback; + void *userParam; + + Message(); + ~Message(); + + ByteArray serialize(); + void deserialize(unsigned char *buffer, unsigned int length); + void deserialize(ByteArray buffer); + + const char *toString(); + }; + +} /* namespace smartcard_service_api */ +#endif /* MESSAGE_H_ */ diff --git a/common/include/NumberStream.h b/common/include/NumberStream.h new file mode 100644 index 0000000..7812027 --- /dev/null +++ b/common/include/NumberStream.h @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2012 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 NUMBERSTREAM_H_ +#define NUMBERSTREAM_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class NumberStream: public ByteArray + { + public: + NumberStream(const ByteArray &T); + + unsigned int getBigEndianNumber(); + unsigned int getLittleEndianNumber(); + + static unsigned int getBigEndianNumber(const ByteArray &T); + static unsigned int getLittleEndianNumber(const ByteArray &T); + + NumberStream &operator =(const ByteArray &T); + NumberStream &operator =(const NumberStream &T); + }; + +} /* namespace smartcard_service_api */ +#endif /* NUMBERSTREAM_H_ */ diff --git a/common/include/OpensslHelper.h b/common/include/OpensslHelper.h new file mode 100644 index 0000000..0688020 --- /dev/null +++ b/common/include/OpensslHelper.h @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +#ifndef OPENSSLHELPER_H_ +#define OPENSSLHELPER_H_ + +namespace smartcard_service_api +{ + class OpensslHelper + { + public: + /* base64 method */ + static bool encodeBase64String(const ByteArray &buffer, ByteArray &result, bool newLineChar = false); + static bool decodeBase64String(const char *buffer, ByteArray &result, bool newLineChar = true); + static bool decodeBase64String(const ByteArray &buffer, ByteArray &result, bool newLineChar = true); + + /* digest method */ + static bool digestBuffer(const char *algorithm, const uint8_t *buffer, const uint32_t length, ByteArray &result); + static bool digestBuffer(const char *algorithm, const ByteArray &buffer, ByteArray &result); + }; + +} /* namespace smartcard_service_api */ +#endif /* OPENSSLHELPER_H_ */ diff --git a/common/include/PKCS15.h b/common/include/PKCS15.h new file mode 100644 index 0000000..5119246 --- /dev/null +++ b/common/include/PKCS15.h @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2012 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 PKCS15_H_ +#define PKCS15_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "PKCS15Object.h" +#include "PKCS15ODF.h" + +using namespace std; + +namespace smartcard_service_api +{ + class PKCS15: public PKCS15Object + { + private: + map recordElement; + PKCS15ODF *odf; + + public: + static ByteArray PKCS15_AID; + + PKCS15(Channel *channel); + PKCS15(Channel *channel, ByteArray selectResponse); + ~PKCS15(); + + PKCS15ODF *getODF(); + int getTokenInfo(ByteArray &path); + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15_H_ */ diff --git a/common/include/PKCS15DODF.h b/common/include/PKCS15DODF.h new file mode 100644 index 0000000..dff03f1 --- /dev/null +++ b/common/include/PKCS15DODF.h @@ -0,0 +1,48 @@ +/* +* Copyright (c) 2012 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 PKCS15DODF_H_ +#define PKCS15DODF_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "PKCS15Object.h" +#include "PKCS15OID.h" + +namespace smartcard_service_api +{ + class PKCS15DODF: public PKCS15Object + { + private: + map mapOID; + + bool parseData(ByteArray data); + + public: + PKCS15DODF(); + PKCS15DODF(unsigned int fid, Channel *channel); + PKCS15DODF(ByteArray path, Channel *channel); + ~PKCS15DODF(); + + int searchOID(ByteArray oid, ByteArray &data); + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15DODF_H_ */ diff --git a/common/include/PKCS15ODF.h b/common/include/PKCS15ODF.h new file mode 100644 index 0000000..9a1021c --- /dev/null +++ b/common/include/PKCS15ODF.h @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2012 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 PKCS15ODF_H_ +#define PKCS15ODF_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "FileObject.h" +#include "PKCS15DODF.h" + +using namespace std; + +namespace smartcard_service_api +{ + class PKCS15ODF: public PKCS15Object + { + private: + bool parseData(ByteArray data); + PKCS15DODF *dodf; + + public: + static const unsigned int ODF_FID = 0x3150; + + static const unsigned int TAG_DODF = (unsigned int)0xA7; + static const unsigned int TAG_TOKENINFO = (unsigned int)0xA5; + +// PKCS15ODF(); + PKCS15ODF(Channel *channel); + PKCS15ODF(Channel *channel, ByteArray selectResponse); + ~PKCS15ODF(); + + int getPuKDFPath(ByteArray &path); + int getPrKDFPath(ByteArray &path); + int getAODFPath(ByteArray &path); + int getCDFFPath(ByteArray &path); + int getDODFPath(ByteArray &path); + + PKCS15DODF *getDODF(); + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15ODF_H_ */ diff --git a/common/include/PKCS15OID.h b/common/include/PKCS15OID.h new file mode 100644 index 0000000..234cd19 --- /dev/null +++ b/common/include/PKCS15OID.h @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2012 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 PKCS15OID_H_ +#define PKCS15OID_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class PKCS15OID + { + private: + ByteArray oid; + ByteArray name; + ByteArray path; + + bool parseOID(ByteArray data); + + public: + PKCS15OID(ByteArray data); + ~PKCS15OID(); + + ByteArray getOID(); + ByteArray getName(); + ByteArray getPath(); + + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15OID_H_ */ diff --git a/common/include/PKCS15Object.h b/common/include/PKCS15Object.h new file mode 100644 index 0000000..e5a1963 --- /dev/null +++ b/common/include/PKCS15Object.h @@ -0,0 +1,58 @@ +/* +* Copyright (c) 2012 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 PKCS15OBJECT_H_ +#define PKCS15OBJECT_H_ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "FileObject.h" +#include "PKCS15Path.h" + +using namespace std; + +namespace smartcard_service_api +{ + class PKCS15Object: public FileObject + { + protected: + map dataList; + + public: + /* TODO : encapsulate below to asn class */ + static const unsigned int TAG_SEQUENCE = (unsigned int)0x30; + static const unsigned int TAG_OCTET_STREAM = (unsigned int)0x04; + +// PKCS15Object(); + PKCS15Object(Channel *channel); + PKCS15Object(Channel *channel, ByteArray selectResponse); + ~PKCS15Object(); + + int decodePath(ByteArray path, PKCS15Path &result); + int getPath(unsigned int type, PKCS15Path &result); + int getPaths(vector &paths); + + static ByteArray getOctetStream(const ByteArray &data); + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15OBJECT_H_ */ diff --git a/common/include/PKCS15Path.h b/common/include/PKCS15Path.h new file mode 100644 index 0000000..9c5dbf6 --- /dev/null +++ b/common/include/PKCS15Path.h @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2012 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 PKCS15Path_H_ +#define PKCS15Path_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class PKCS15Path + { + private : + ByteArray path; + int index; + int length; + + bool parseData(ByteArray &data); + + public: + PKCS15Path(); + PKCS15Path(ByteArray &data); + PKCS15Path(ByteArray path, int index); + PKCS15Path(unsigned char *path, unsigned int length, int index); + ~PKCS15Path(); + + int getPath(ByteArray &path); + bool hasIndexLength(); + int getIndex(); + unsigned int getLength(); + int encode(ByteArray &result); + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15Path_H_ */ diff --git a/common/include/PKCS15TokenInfo.h b/common/include/PKCS15TokenInfo.h new file mode 100644 index 0000000..71f8083 --- /dev/null +++ b/common/include/PKCS15TokenInfo.h @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2012 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 PKCS15TOKENINFO_H_ +#define PKCS15TOKENINFO_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "PKCS15Object.h" + +namespace smartcard_service_api +{ + class PKCS15TokenInfo: public PKCS15Object + { + public: + PKCS15TokenInfo(Channel *channel); + ~PKCS15TokenInfo(); + }; + +} /* namespace smartcard_service_api */ +#endif /* PKCS15TOKENINFO_H_ */ diff --git a/common/include/ProviderHelper.h b/common/include/ProviderHelper.h new file mode 100644 index 0000000..2ad87a6 --- /dev/null +++ b/common/include/ProviderHelper.h @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2012 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 PROVIDERHELPER_H_ +#define PROVIDERHELPER_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Channel.h" + +namespace smartcard_service_api +{ + class ProviderHelper + { + protected: + Channel *channel; + +// ProviderHelper(); + + public: + ProviderHelper(Channel *channel); + ~ProviderHelper(); + + Channel *getChannel(); + }; + +} /* namespace smartcard_service_api */ +#endif /* PROVIDERHELPER_H_ */ diff --git a/common/include/ReaderHelper.h b/common/include/ReaderHelper.h new file mode 100644 index 0000000..50e6a17 --- /dev/null +++ b/common/include/ReaderHelper.h @@ -0,0 +1,60 @@ +/* +* Copyright (c) 2012 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 READERHELPER_H_ +#define READERHELPER_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Synchronous.h" +#include "SessionHelper.h" + +using namespace std; + +namespace smartcard_service_api +{ + class SEServiceHelper; + + typedef void (*openSessionCallback)(SessionHelper *session, int error, void *userData); + + class ReaderHelper : public Synchronous + { + protected: + char name[30]; + vector sessions; + SEServiceHelper *seService; + + ReaderHelper(); + + virtual SessionHelper *openSessionSync() = 0; + + public: + ~ReaderHelper(); + + const char *getName(); + SEServiceHelper *getSEService(); + bool isSecureElementPresent(); + virtual int openSession(openSessionCallback callback, void *userData) = 0; + virtual void closeSessions() = 0; + }; + +} /* namespace smartcard_service_api */ +#endif /* READERHELPER_H_ */ diff --git a/common/include/Record.h b/common/include/Record.h new file mode 100644 index 0000000..29ef734 --- /dev/null +++ b/common/include/Record.h @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2012 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 RECORD_H_ +#define RECORD_H_ + +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class Record + { + private: + ByteArray data; + unsigned int id; + + public: + Record(); + Record(unsigned int id, ByteArray buffer); + ~Record(); + + unsigned int getID(); + int getData(ByteArray &buffer); + }; + +} /* namespace smartcard_service_api */ +#endif /* RECORD_H_ */ diff --git a/common/include/SEServiceHelper.h b/common/include/SEServiceHelper.h new file mode 100644 index 0000000..de40eca --- /dev/null +++ b/common/include/SEServiceHelper.h @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2012 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 SESERVICEHELPER_H_ +#define SESERVICEHELPER_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Synchronous.h" +#include "ReaderHelper.h" + +using namespace std; + +namespace smartcard_service_api +{ + class SEServiceHelper : public Synchronous + { + protected: + bool connected; + vector readers; + + public: + SEServiceHelper(); + ~SEServiceHelper(); + + vector getReaders(); + bool isConnected(); + void shutdown(); + }; + +} /* namespace smartcard_service_api */ +#endif /* SESERVICEHELPER_H_ */ diff --git a/common/include/Serializable.h b/common/include/Serializable.h new file mode 100644 index 0000000..af1fe3d --- /dev/null +++ b/common/include/Serializable.h @@ -0,0 +1,32 @@ +/* +* Copyright (c) 2012 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 SERIALIZABLE_H_ +#define SERIALIZABLE_H_ + +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class Serializable + { + virtual ByteArray serialize() = 0; + virtual void deserialize(ByteArray buffer) = 0; + }; + +} /* namespace smartcard_service_api */ +#endif /* SERIALIZABLE_H_ */ diff --git a/common/include/SessionHelper.h b/common/include/SessionHelper.h new file mode 100644 index 0000000..3aed778 --- /dev/null +++ b/common/include/SessionHelper.h @@ -0,0 +1,76 @@ +/* +* Copyright (c) 2012 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 SESSIONHELPER_H_ +#define SESSIONHELPER_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Synchronous.h" +#include "ByteArray.h" +#include "Channel.h" + +using namespace std; + +namespace smartcard_service_api +{ + class ReaderHelper; + + typedef void (*openChannelCallback)(Channel *channel, int error, void *userData); + typedef void (*getATRCallback)(unsigned char *atr, unsigned int length, int error, void *userData); + typedef void (*closeSessionCallback)(int error, void *userData); + typedef void (*getChannelCountCallback)(unsigned count, int error, void *userData); + + class SessionHelper : public Synchronous + { + protected: + ReaderHelper *reader; + vector channels; + ByteArray atr; + bool closed; + + virtual ByteArray getATRSync() = 0; + virtual void closeSync() = 0; + + virtual Channel *openBasicChannelSync(ByteArray aid) = 0; + virtual Channel *openBasicChannelSync(unsigned char *aid, unsigned int length) = 0; + virtual Channel *openLogicalChannelSync(ByteArray aid) = 0; + virtual Channel *openLogicalChannelSync(unsigned char *aid, unsigned int length) = 0; + + public: + SessionHelper(ReaderHelper *reader); + virtual ~SessionHelper(); + + ReaderHelper *getReader(); + virtual int getATR(getATRCallback callback, void *userData) = 0; + virtual int close(closeSessionCallback callback, void *userData) = 0; + bool isClosed(); + virtual void closeChannels() = 0; + + virtual int openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData) = 0; + virtual int openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData) = 0; + virtual int openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData) = 0; + virtual int openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData) = 0; + + }; + +} /* namespace smartcard_service_api */ +#endif /* SESSIONHELPER_H_ */ diff --git a/common/include/SignatureHelper.h b/common/include/SignatureHelper.h new file mode 100644 index 0000000..a2c0923 --- /dev/null +++ b/common/include/SignatureHelper.h @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2012 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 SIGNATUREHELPER_H_ +#define SIGNATUREHELPER_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#ifdef __cplusplus +#include "ByteArray.h" +#endif /* __cplusplus */ + +#ifdef __cplusplus +namespace smartcard_service_api +{ + class SignatureHelper + { + public: + static int getProcessName(int pid, char *processName, uint32_t length); + static ByteArray getCertificationHash(const char *packageName); + static ByteArray getCertificationHash(int pid); + }; + +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int signature_helper_get_process_name(int pid, char *processName, uint32_t length); +int signature_helper_get_certificate_hash(const char *packageName, uint8_t *hash, uint32_t *length); +int signature_helper_get_certificate_hash_by_pid(int pid, uint8_t *hash, uint32_t *length); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SIGNATUREHELPER_H_ */ diff --git a/common/include/SimpleTLV.h b/common/include/SimpleTLV.h new file mode 100644 index 0000000..de35eb8 --- /dev/null +++ b/common/include/SimpleTLV.h @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2012 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 SIMPLETLV_H_ +#define SIMPLETLV_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" +#include "TLVHelper.h" + +namespace smartcard_service_api +{ + class SimpleTLV : public TLVHelper + { + private: + SimpleTLV(TLVHelper *parent); + SimpleTLV(const ByteArray &array, TLVHelper *parent); + + int decodeTag(unsigned char *buffer); + int decodeLength(unsigned char *buffer); + int decodeValue(unsigned char *buffer); + + TLVHelper *getChildTLV(ByteArray data); + + public: + SimpleTLV(); + SimpleTLV(const ByteArray &array); + ~SimpleTLV(); + + static ByteArray getOctetString(const ByteArray &array); + static bool getBoolean(const ByteArray &array); + static int getInteger(const ByteArray &array); + + static ByteArray getOctetString(SimpleTLV &tlv); + static bool getBoolean(SimpleTLV &tlv); + static int getInteger(SimpleTLV &tlv); + + static ByteArray encode(unsigned int tag, ByteArray buffer); + static ByteArray encode(unsigned int tag, unsigned char *buffer, unsigned int length); + }; + +} /* namespace smartcard_service_api */ +#endif /* SIMPLETLV_H_ */ diff --git a/common/include/Synchronous.h b/common/include/Synchronous.h new file mode 100644 index 0000000..d2aec51 --- /dev/null +++ b/common/include/Synchronous.h @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2012 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 SYNCHRONOUS_H_ +#define SYNCHRONOUS_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ + +namespace smartcard_service_api +{ + class Synchronous + { + protected: + pthread_mutex_t syncMutex; + pthread_cond_t syncCondition; + + void syncLock(); + void syncUnlock(); + int waitTimedCondition(int second); + void signalCondition(); + + public: + Synchronous(); + }; + +} /* namespace smartcard_service_api */ +#endif /* SYNCHRONOUS_H_ */ diff --git a/common/include/TLVHelper.h b/common/include/TLVHelper.h new file mode 100644 index 0000000..a48dc05 --- /dev/null +++ b/common/include/TLVHelper.h @@ -0,0 +1,89 @@ +/* +* Copyright (c) 2012 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 TLVHELPER_H_ +#define TLVHELPER_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" + +namespace smartcard_service_api +{ + class TLVHelper + { + protected: + TLVHelper *currentTLV; + TLVHelper *parentTLV; + TLVHelper *childTLV; + + char strBuffer[200]; + ByteArray tlvBuffer; + unsigned int offset; + + unsigned int currentT; + unsigned int currentL; + ByteArray currentV; + + void initialize(TLVHelper *parent = NULL); + TLVHelper(TLVHelper *parent); + TLVHelper(const ByteArray &array, TLVHelper *parent); + + virtual int decodeTag(unsigned char *buffer) = 0; + virtual int decodeLength(unsigned char *buffer) = 0; + virtual int decodeValue(unsigned char *buffer) = 0; + + virtual TLVHelper *getChildTLV(ByteArray data) = 0; + TLVHelper *getParentTLV(); + + bool setTLVBuffer(const ByteArray &array, TLVHelper *parent); + bool setTLVBuffer(unsigned char *buffer, unsigned int length, TLVHelper *parent); + + bool _isEndOfBuffer() { return offset >= tlvBuffer.getLength(); } + bool _decodeTLV(); + + unsigned int _getTag() { return currentT; } + unsigned int _getLength() { return currentL; } + ByteArray _getValue() { return currentV; } + + public: + TLVHelper(); + TLVHelper(const ByteArray &array); + ~TLVHelper(); + + bool setTLVBuffer(const ByteArray &array) { return setTLVBuffer(array, NULL); } + bool setTLVBuffer(unsigned char *buffer, unsigned int length) { return setTLVBuffer(buffer, length, NULL); } + + bool isEndOfBuffer() { return currentTLV->_isEndOfBuffer(); } + bool decodeTLV() { return currentTLV->_decodeTLV(); } + + unsigned int getTag() { return currentTLV->_getTag(); } + unsigned int getLength() { return currentTLV->_getLength(); } + ByteArray getValue() { return currentTLV->_getValue(); } + + const char *toString(); + + bool enterToValueTLV(); + bool returnToParentTLV(); + }; + +} /* namespace smartcard_service_api */ +#endif /* TLVHELPER_H_ */ diff --git a/common/include/Terminal.h b/common/include/Terminal.h new file mode 100644 index 0000000..2cc8c6a --- /dev/null +++ b/common/include/Terminal.h @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2012 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 TERMINAL_H_ +#define TERMINAL_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" +#include "Synchronous.h" + +namespace smartcard_service_api +{ + typedef void (*terminalNotificationCallback)(void *terminal, int event, int error, void *user_param); + + typedef void (*terminalTransmitCallback)(unsigned char *buffer, unsigned int length, int error, void *userParam); + typedef void (*terminalGetATRCallback)(unsigned char *buffer, unsigned int length, int error, void *userParam); + + class Terminal : public Synchronous + { + protected: + terminalNotificationCallback statusCallback; + bool initialized; + char *name; + + public: + static const int NOTIFY_SE_AVAILABLE = 1; + static const int NOTIFY_SE_NOT_AVAILABLE = -1; + + Terminal() + { + statusCallback = NULL; + initialized = false; + name = NULL; + } + virtual ~Terminal() {} + + virtual bool initialize() = 0; + virtual void finalize() = 0; + inline bool isInitialized() { return initialized; } + + inline char *getName() { return name; } + inline void setStatusCallback(terminalNotificationCallback callback) { statusCallback = callback; } + + virtual bool isSecureElementPresence() = 0; + + virtual int transmitSync(ByteArray command, ByteArray &result) = 0; + virtual int getATRSync(ByteArray &atr) = 0; + + virtual int transmit(ByteArray command, terminalTransmitCallback callback, void *userData) = 0; + virtual int getATR(terminalGetATRCallback callback, void *userData) = 0; + }; + +} /* namespace smartcard_service_api */ +#endif /* TERMINAL_H_ */ diff --git a/common/include/TerminalInterface.h b/common/include/TerminalInterface.h new file mode 100644 index 0000000..441082f --- /dev/null +++ b/common/include/TerminalInterface.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2012 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 TERMINALINTERFACE_H_ +#define TERMINALINTERFACE_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ + +//typedef unsigned int terminal_handle_h; +// +//typedef enum +//{ +// TERMINAL_SUCCESS = 0, +// +// TERMINAL_ERROR_UNKNOWN = -1, +// /* TERMINAL_ERROR_ = -, */ +//} terminal_result_e; +// +//typedef char *(*terminal_get_name_fn)(); +//typedef terminal_result_e (*terminal_initialize_fn)(int param1, char *param2); +//typedef terminal_result_e (*terminal_finalize_fn)(int param1, char *param2); +//typedef terminal_result_e (*terminal_open_fn)(int param1, char *param2, terminal_handle_h *handle); +//typedef terminal_result_e (*terminal_close_fn)(terminal_handle_h handle); +//typedef terminal_result_e (*terminal_transmit_fn)(terminal_handle_h handle, unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int *resp_len); +//typedef terminal_result_e (*terminal_get_atr_fn)(terminal_handle_h handle, unsigned char *atr, unsigned int *atr_len); +// +//typedef struct _terminal_interfaces_t +//{ +// terminal_get_name_fn api_get_name; +// terminal_initialize_fn api_initialize; +// terminal_finalize_fn api_finalize; +// terminal_open_fn api_open; +// terminal_close_fn api_close; +// terminal_transmit_fn api_transmit; +// terminal_get_atr_fn api_get_atr; +//} terminal_interfaces_t; +// +//typedef int (*terminal_get_interfaces_fn)(terminal_interfaces_t *apis); + +typedef const char *(*terminal_get_name_fn)(); +typedef void *(*terminal_create_instance_fn)(); +typedef void (*terminal_destroy_instance_fn)(void *); + +#endif /* TERMINALINTERFACE_H_ */ diff --git a/common/include/smartcard-types.h b/common/include/smartcard-types.h new file mode 100644 index 0000000..15c7c5e --- /dev/null +++ b/common/include/smartcard-types.h @@ -0,0 +1,43 @@ +/* +* Copyright (c) 2012 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 SMARTCARD_TYPES_H_ +#define SMARTCARD_TYPES_H_ + +#include +#include + +typedef void *se_service_h; +typedef void *reader_h; +typedef void *session_h; +typedef void *channel_h; + +typedef void (*se_service_connected_cb)(se_service_h handle, void *context); +typedef void (*se_service_event_cb)(se_service_h handle, char *se_name, int event, void *context); +typedef void (*se_sesrvice_error_cb)(se_service_h handle, int error, void *context); + +typedef void (*reader_open_session_cb)(session_h session, int error, void *user_data); + +typedef void (*session_open_channel_cb)(channel_h channel, int error, void *user_data); +typedef void (*session_get_atr_cb)(unsigned char *atr, unsigned int length, int error, void *user_data); +typedef void (*session_close_session_cb)(int error, void *user_data); +typedef void (*session_get_channel_count_cb)(unsigned count, int error, void *user_data); + +typedef void (*channel_transmit_cb)(unsigned char *buffer, unsigned int length, int error, void *user_data); +typedef void (*channel_close_cb)(int error, void *user_data); + +#endif /* SMARTCARD_TYPES_H_ */ diff --git a/common/smartcard-service-common.pc b/common/smartcard-service-common.pc new file mode 100644 index 0000000..36ea9c9 --- /dev/null +++ b/common/smartcard-service-common.pc @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=/usr +exec_prefix=${prefix}/bin +includedir=${prefix}/include +libdir=${prefix}/lib + +Name: smartcard-service-common +Description: Make flags of Common library of Smartcard service +Version: 1.0 +Requires: +Libs: -L${libdir} -lsmartcard-service-common +Cflags: -I${includedir}/smartcard-service-common \ No newline at end of file diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c7c2e9a --- /dev/null +++ b/debian/changelog @@ -0,0 +1,55 @@ +smartcard-service (0.1.0-3) unstable; urgency=low + + * add an exceptional case when is openning client channel (nfc-manager) + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.1.0-3 + + -- Wonkyu Kwon Fri, 20 Apr 2012 11:00:00 +0900 + +smartcard-service (0.1.0-2) unstable; urgency=low + + * add helpers for openssl and package signature + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.1.0-2 + + -- Wonkyu Kwon Fri, 23 Mar 2012 12:40:00 +0900 + +smartcard-service (0.1.0-1) unstable; urgency=low + + * Upload package + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.1.0-1 + + -- Wonkyu Kwon Wed, 14 Mar 2012 13:30:00 +0900 + +smartcard-service (0.0.0-4) unstable; urgency=low + + * Upload package + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.0.0-4 + + -- Wonkyu Kwon Tue, 13 Mar 2012 13:10:00 +0900 + +smartcard-service (0.0.0-3) unstable; urgency=low + + * namespace and macro name change + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.0.0-3 + + -- Sangsoo Lee Wed, 07 Mar 2012 19:26:46 +0900 + +smartcard-service (0.0.0-2) unstable; urgency=low + + * getChannelCount api add + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.0.0-2 + + -- Sangsoo Lee Thu, 23 Feb 2012 21:10:42 +0900 + +smartcard-service (0.0.0-1) unstable; urgency=low + + * Initial release + * Git: slp/pkgs/s/smartcard-service + * Tag: smartcard-service_0.0.0-1 + + -- Wonkyu Kwon Thu, 31 Jan 2012 00:00:00 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +8 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..f0eabd9 --- /dev/null +++ b/debian/control @@ -0,0 +1,65 @@ +Source: smartcard-service +Priority: extra +Maintainer: Wonkyu Kwon , Sangsoo Lee , Sungjae Lim , Junyong Sim , Sechang Sohn +Build-Depends: debhelper (>= 8.0.0), libglib2.0-dev, libvconf-dev, libsecurity-server-client-dev, dlog-dev, wrt-commons-dev, libaul-1-dev, libssl-dev +#Build-Depends: debhelper (>= 8.0.0), libglib2.0-dev, libvconf-dev, libsecurity-server-client-dev, dlog-dev, libpkcs11-helper1-dev, wrt-commons, libaul-dev, libssl-dev +#Standards-Version: 3.9.2 +Section: mixed +Homepage: +#Vcs-Git: git://git.debian.org/collab-maint/smartcard-service.git +#Vcs-Browser: http://git.debian.org/?p=collab-maint/smartcard-service.git;a=summary + +Package: smartcard-service-common +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Common library of Smart card service + Common library of Smart card service + +Package: smartcard-service-common-dev +Section: libdevel +Architecture: any +Depends: smartcard-service-common (= ${binary:Version}) +Description: Common library of Smart card service + Common library of Smart card service + +Package: smartcard-service-common-dbg +Section: debug +Architecture: any +Depends: smartcard-service-common (= ${binary:Version}) +Description: Common library of Smart card service (unstripped) + Common library of Smart card service (unstripped) + +Package: smartcard-service-server +Architecture: any +Depends: smartcard-service-common-dev (= ${binary:Version}) +Description: Main process of Smart card service + Main process of Smart card service + +Package: smartcard-service-server-dbg +Section: debug +Architecture: any +Depends: smartcard-service-server (= ${binary:Version}) +Description: Main process of Smart card service (unstripped) + Main process of Smart card service (unstripped) + +Package: smartcard-service +Section: libs +Architecture: any +Depends: smartcard-service-common-dev (= ${binary:Version}) +Description: User library of Smart card service + User library of Smart card service + +Package: smartcard-service-dev +Section: libdevel +Architecture: any +Depends: smartcard-service (= ${binary:Version}) +Description: User library of Smart card service + User library of Smart card service + +Package: smartcard-service-dbg +Section: debug +Architecture: any +Depends: smartcard-service (= ${binary:Version}) +Description: User library of Smart card service (unstripped) + User library of Smart card service (unstripped) diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..d6ef688 --- /dev/null +++ b/debian/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +override_dh_auto_build: + + cd $(CMAKE_BINARY_DIR) + dh_auto_build + +override_dh_install: + + mkdir -p $(CURDIR)/debian/tmp/etc/init.d + mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/ + mkdir -p $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/ + + cp -af $(CURDIR)/debian/smartcard-service-server.init $(CURDIR)/debian/tmp/etc/init.d/smartcard-service-server + ln -s ../init.d/smartcard-service-server $(CURDIR)/debian/tmp/etc/rc.d/rc3.d/S79smartcard-service-server + ln -s ../init.d/smartcard-service-server $(CURDIR)/debian/tmp/etc/rc.d/rc5.d/S79smartcard-service-server + + dh_install + +override_dh_installinit: + +%: + dh $@ + diff --git a/debian/smartcard-service-common-dev.dirs b/debian/smartcard-service-common-dev.dirs new file mode 100644 index 0000000..4418816 --- /dev/null +++ b/debian/smartcard-service-common-dev.dirs @@ -0,0 +1,2 @@ +usr/lib +usr/include diff --git a/debian/smartcard-service-common-dev.install b/debian/smartcard-service-common-dev.install new file mode 100644 index 0000000..2d332a5 --- /dev/null +++ b/debian/smartcard-service-common-dev.install @@ -0,0 +1,5 @@ +usr/include/smartcard-service-common/* +#usr/lib/lib*.a +usr/lib/libsmartcard-service-common.so +usr/lib/pkgconfig/smartcard-service-common.pc +#usr/share/pkgconfig/* diff --git a/debian/smartcard-service-common.dirs b/debian/smartcard-service-common.dirs new file mode 100644 index 0000000..6845771 --- /dev/null +++ b/debian/smartcard-service-common.dirs @@ -0,0 +1 @@ +usr/lib diff --git a/debian/smartcard-service-common.install b/debian/smartcard-service-common.install new file mode 100644 index 0000000..3b87046 --- /dev/null +++ b/debian/smartcard-service-common.install @@ -0,0 +1 @@ +usr/lib/libsmartcard-service-common.so.* diff --git a/debian/smartcard-service-dev.dirs b/debian/smartcard-service-dev.dirs new file mode 100644 index 0000000..4418816 --- /dev/null +++ b/debian/smartcard-service-dev.dirs @@ -0,0 +1,2 @@ +usr/lib +usr/include diff --git a/debian/smartcard-service-dev.install b/debian/smartcard-service-dev.install new file mode 100644 index 0000000..a547e24 --- /dev/null +++ b/debian/smartcard-service-dev.install @@ -0,0 +1,5 @@ +usr/include/smartcard-service/* +#usr/lib/lib*.a +usr/lib/libsmartcard-service.so +usr/lib/pkgconfig/smartcard-service.pc +#usr/share/pkgconfig/* diff --git a/debian/smartcard-service-server.dirs b/debian/smartcard-service-server.dirs new file mode 100644 index 0000000..2d445a0 --- /dev/null +++ b/debian/smartcard-service-server.dirs @@ -0,0 +1,2 @@ +usr/bin +etc \ No newline at end of file diff --git a/debian/smartcard-service-server.init b/debian/smartcard-service-server.init new file mode 100755 index 0000000..ffc409b --- /dev/null +++ b/debian/smartcard-service-server.init @@ -0,0 +1,28 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: smartcard-service-server +# Required-Start: $network $local_fs +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: +# Description: +# <...> +# <...> +### END INIT INFO + +# Author: Wonkyu Kwon + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/usr/bin +DESC=smartcard-daemon # Introduce a short description here +NAME=smartcard-daemon # Introduce the short server's name here +DAEMON=/usr/bin/smartcard-daemon # Introduce the server's location here +DAEMON_ARGS="" # Arguments to run the daemon with +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x $DAEMON ] || exit 0 + +$DAEMON $DAEMON_ARGS & \ No newline at end of file diff --git a/debian/smartcard-service-server.install b/debian/smartcard-service-server.install new file mode 100644 index 0000000..8a71c41 --- /dev/null +++ b/debian/smartcard-service-server.install @@ -0,0 +1,2 @@ +usr/bin/smartcard-daemon +etc/* \ No newline at end of file diff --git a/debian/smartcard-service.dirs b/debian/smartcard-service.dirs new file mode 100644 index 0000000..6845771 --- /dev/null +++ b/debian/smartcard-service.dirs @@ -0,0 +1 @@ +usr/lib diff --git a/debian/smartcard-service.install b/debian/smartcard-service.install new file mode 100644 index 0000000..05b76e3 --- /dev/null +++ b/debian/smartcard-service.install @@ -0,0 +1 @@ +usr/lib/libsmartcard-service.so.* diff --git a/packaging/smartcard-service-server.init b/packaging/smartcard-service-server.init new file mode 100755 index 0000000..ffc409b --- /dev/null +++ b/packaging/smartcard-service-server.init @@ -0,0 +1,28 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: smartcard-service-server +# Required-Start: $network $local_fs +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: +# Description: +# <...> +# <...> +### END INIT INFO + +# Author: Wonkyu Kwon + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/usr/bin +DESC=smartcard-daemon # Introduce a short description here +NAME=smartcard-daemon # Introduce the short server's name here +DAEMON=/usr/bin/smartcard-daemon # Introduce the server's location here +DAEMON_ARGS="" # Arguments to run the daemon with +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x $DAEMON ] || exit 0 + +$DAEMON $DAEMON_ARGS & \ No newline at end of file diff --git a/packaging/smartcard-service.spec b/packaging/smartcard-service.spec new file mode 100644 index 0000000..d889a43 --- /dev/null +++ b/packaging/smartcard-service.spec @@ -0,0 +1,117 @@ +Name: smartcard-service +Summary: Smartcard Service FW +Version: 0.1.0 +Release: 8 +Group: libs +License: Samsung Proprietary License +Source0: %{name}-%{version}.tar.gz +Source1: smartcard-service-server.init +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(security-server) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libssl) +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(dpl-wrt-dao-ro) +BuildRequires: cmake +BuildRequires: gettext-tools +Requires(post): /sbin/ldconfig +Requires(post): /usr/bin/vconftool +requires(postun): /sbin/ldconfig + +%description +Smartcard Service FW. + +%prep +%setup -q + +%package devel +Summary: smartcard service +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +smartcard service. + +%package -n smartcard-service-common +Summary: common smartcard service +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description -n smartcard-service-common +common smartcard service. + +%package -n smartcard-service-common-devel +Summary: common smartcard service +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description -n smartcard-service-common-devel +common smartcard service. + +%package -n smartcard-service-server +Summary: server smartcard service +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description -n smartcard-service-server +smartcard service. + +%build +mkdir obj-arm-limux-qnueabi +cd obj-arm-limux-qnueabi +cmake .. -DCMAKE_INSTALL_PREFIX=%{_prefix} +#make %{?jobs:-j%jobs} + +%install +cd obj-arm-limux-qnueabi +%make_install +%__mkdir -p %{buildroot}/etc/init.d/ +%__mkdir -p %{buildroot}/etc/rc.d/rc3.d/ +%__mkdir -p %{buildroot}/etc/rc.d/rc5.d/ +%__cp -af %SOURCE1 %{buildroot}/etc/init.d/smartcard-service-server +chmod 755 %{buildroot}/etc/init.d/smartcard-service-server + +%post +/sbin/ldconfig + +ln -sf /etc/init.d/smartcard-service-server /etc/rc.d/rc3.d/S79smartcard-service-server +ln -sf /etc/init.d/smartcard-service-server /etc/rc.d/rc5.d/S79smartcard-service-server + +%postun +/sbin/ldconfig + +rm -f /etc/rc.d/rc3.d/S79smartcard-service-server +rm -f /etc/rc.d/rc5.d/S79smartcard-service-server + +#%post +# -n nfc-common-lib -p /sbin/ldconfig + +#%postun +# -n nfc-common-lib -p /sbin/ldconfig + +%files +%defattr(-,root,root,-) +/usr/lib/libsmartcard-service.so.* + +%files devel +%defattr(-,root,root,-) +/usr/include/smartcard-service/* +/usr/lib/libsmartcard-service.so +/usr/lib/pkgconfig/smartcard-service.pc + +%files -n smartcard-service-common +%defattr(-,root,root,-) +/usr/lib/libsmartcard-service-common.so.* + +%files -n smartcard-service-common-devel +%defattr(-,root,root,-) +/usr/include/smartcard-service-common/* +/usr/lib/libsmartcard-service-common.so +/usr/lib/pkgconfig/smartcard-service-common.pc + +%files -n smartcard-service-server +%defattr(-,root,root,-) +/usr/bin/smartcard-daemon +#/usr/bin/smartcard-test-client +/etc/init.d/smartcard-service-server diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000..b80eb8e --- /dev/null +++ b/server/CMakeLists.txt @@ -0,0 +1,48 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(smartcard-daemon CXX) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ SRCS) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs_server REQUIRED glib-2.0 gobject-2.0 security-server vconf dlog) + +FOREACH(flag ${pkgs_server_CFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +MESSAGE("CHECK MODULE in ${PROJECT_NAME} ${pkgs_server_LDFLAGS}") + +# this for NFC flag + +SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -fno-strict-aliasing -Wl,-zdefs -fvisibility=hidden") + +SET(ARM_CXXFLAGS "${ARM_CXXLAGS} -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common -fpic") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM_CXXFLAGS}") +ENDIF() + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DLOG_TAG=\"SCARD_SERVER\"") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_server_LDFLAGS} "-L../common" "-lsmartcard-service-common" "-pie -ldl") + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/server/ClientInstance.cpp b/server/ClientInstance.cpp new file mode 100644 index 0000000..779883b --- /dev/null +++ b/server/ClientInstance.cpp @@ -0,0 +1,118 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ClientInstance.h" +#include "ServerResource.h" +#include "SignatureHelper.h" + +namespace smartcard_service_api +{ + void ClientInstance::setPID(int pid) + { + this->pid = pid; + +#if 0 + if (pid > 0) + { + certHash = SignatureHelper::getCertificationHash(pid); + } +#endif + } + + bool ClientInstance::createService(unsigned int context) + { + bool result = false; + + if (getService(context) == NULL) + { + ServiceInstance *instance = new ServiceInstance(this, context); + if (instance != NULL) + { + mapServices.insert(make_pair(context, instance)); + result = true; + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + else + { + SCARD_DEBUG_ERR("service already exist [%d]", context); + } + + return result; + } + + ServiceInstance *ClientInstance::getService(unsigned int context) + { + ServiceInstance *result = NULL; + map::iterator item; + + if ((item = mapServices.find(context)) != mapServices.end()) + { + result = item->second; + } + + return result; + } + + void ClientInstance::removeService(unsigned int context) + { + map::iterator item; + + if ((item = mapServices.find(context)) != mapServices.end()) + { + delete item->second; + mapServices.erase(item); + } + } + + void ClientInstance::removeServices() + { + map::iterator item; + + for (item = mapServices.begin(); item != mapServices.end(); item++) + { + delete item->second; + } + + mapServices.clear(); + } + + bool ClientInstance::sendMessageToAllServices(int socket, Message &msg) + { + bool result = true; + map::iterator item; + + for (item = mapServices.begin(); item != mapServices.end(); item++) + { + if (ServerIPC::getInstance()->sendMessage(socket, &msg) == false) + result = false; + } + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerChannel.cpp b/server/ServerChannel.cpp new file mode 100644 index 0000000..2ead32c --- /dev/null +++ b/server/ServerChannel.cpp @@ -0,0 +1,108 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServerChannel.h" +#include "APDUHelper.h" + +namespace smartcard_service_api +{ + ServerChannel::ServerChannel(ServerSession *session, void *caller, int channelNum, Terminal *terminal):Channel(session) + { + this->terminal = terminal; + this->caller = caller; + this->channelNum = channelNum; + } + + ServerChannel::~ServerChannel() + { + if (isClosed() == false) + { + closeSync(); + } + } + + void ServerChannel::closeSync() + { + ByteArray command, result; + APDUHelper apdu; + int rv; + + if (isBasicChannel() == false) + { + /* close channel */ + command = apdu.generateAPDU(APDUHelper::COMMAND_CLOSE_LOGICAL_CHANNEL, channelNum, ByteArray::EMPTY); + rv = terminal->transmitSync(command, result); + + if (rv == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + + if (resp.getStatus() == 0) + { + SCARD_DEBUG("close success"); + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, result.getLength()); + } + } + + channelNum = -1; + } + + int ServerChannel::getChannelNumber() + { + return channelNum; + } + + int ServerChannel::transmitSync(ByteArray command, ByteArray &result) + { + APDUCommand helper; + + if (session != NULL) /* admin channel */ + { + helper.setCommand(command); + + /* filter command */ + if ((helper.getINS() == APDUCommand::INS_SELECT_FILE && helper.getP1() == APDUCommand::P1_SELECT_BY_DF_NAME) || + (helper.getINS() == APDUCommand::INS_MANAGE_CHANNEL)) + { + return -4; /* security reason */ + } + + /* insert channel ID */ + helper.setChannel(0, channelNum); + + helper.getBuffer(command); + } + + SCARD_DEBUG("command [%d] : %s", command.getLength(), command.toString()); + + return terminal->transmitSync(command, result); + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerDispatcher.cpp b/server/ServerDispatcher.cpp new file mode 100644 index 0000000..48d003d --- /dev/null +++ b/server/ServerDispatcher.cpp @@ -0,0 +1,594 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServerDispatcher.h" +#include "ServerResource.h" +#include "ServerSEService.h" +#include "ServerChannel.h" +#include "ServerSession.h" +#include "ServerReader.h" + +namespace smartcard_service_api +{ + ServerDispatcher::ServerDispatcher():DispatcherHelper() + { + SCARD_BEGIN(); + + runDispatcherThread(); + + SCARD_END(); + } + + ServerDispatcher::~ServerDispatcher() + { + } + + ServerDispatcher *ServerDispatcher::getInstance() + { + static ServerDispatcher instance; + + return &instance; + } + + void *ServerDispatcher::dispatcherThreadFunc(DispatcherMsg *msg, void *data) + { + int socket = -1; + ServerResource *resource = NULL; + + if (data == NULL) + { + SCARD_DEBUG_ERR("dispatcher instance is null"); + return NULL; + } + + if (msg == NULL) + { + SCARD_DEBUG_ERR("message is null"); + return NULL; + } + + resource = &ServerResource::getInstance(); + socket = msg->getPeerSocket(); + + switch (msg->message) + { + /* handle message */ + case Message::MSG_REQUEST_READERS : + { + SCARD_DEBUG("[MSG_REQUEST_READERS]"); + +#if 0 + seService->dispatcherCallback(msg, msg->getPeerSocket()); +#else + int count = 0; + Message response(*msg); + ByteArray info; + ClientInstance *instance = NULL; + + if ((instance = resource->getClient(socket)) != NULL) + { + /* update client PID */ + if (instance->getPID() == -1) + { + instance->setPID(msg->error); + SCARD_DEBUG_ERR("update PID [%d]", msg->error); + } + + /* create service */ + if (resource->getService(socket, (unsigned int)msg->userParam) == NULL) + { + if (resource->createService(socket, (unsigned int)msg->userParam) == true) + { + SCARD_DEBUG_ERR("client added : context [%d]", (unsigned int)msg->userParam); + } + else + { + SCARD_DEBUG_ERR("createClient failed"); + + response.param1 = 0; + response.error = -1; + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + + return NULL; + } + } + + if ((count = resource->getReadersInformation(info)) > 0) + { + response.param1 = count; + response.param2 = 0; + response.error = 0; + response.data = info; + } + else + { + SCARD_DEBUG("no secure elements"); + + response.error = -1; + } + } + else + { + SCARD_DEBUG("client doesn't exist, socket [%d]", socket); + + response.error = -1; + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); +#endif + } + break; + + case Message::MSG_REQUEST_SHUTDOWN : +#if 0 + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_SHUTDOWN]"); + + if (msg->param1 != 0) + { + ServerChannel *channel = NULL; + + channel = (ServerChannel *)msg->param1; + + channel->closeSync(); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_SHUTDOWN]"); + + response.error = 0; + + resource->removeService(socket, msg->error/* service context */); + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_REQUEST_OPEN_SESSION : +#if 0 + { + Message response(*msg); + ServerReader *reader = NULL; + ServerSession *session = NULL; + + SCARD_DEBUG("[MSG_REQUEST_OPEN_SESSION]"); + + if (msg->param1 != 0) + { + reader = (ServerReader *)msg->param1; + + session = reader->openSessionSync(msg->data, msg->caller); + } + + /* TODO : attach atr??? */ + response.param1 = (unsigned int)session; + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + Message response(*msg); + unsigned int handle = -1; + + SCARD_DEBUG("[MSG_REQUEST_OPEN_SESSION]"); + + response.param1 = -1; + response.error = -1; + + if (resource->isValidReaderHandle(msg->param1)) + { + handle = resource->createSession(socket, msg->error/* service context */, msg->param1, msg->data, msg->caller); + if (handle != IntegerHandle::INVALID_HANDLE) + { + response.param1 = handle; + response.error = 0; + } + else + { + SCARD_DEBUG_ERR("createSession failed [%d]", handle); + } + } + else + { + SCARD_DEBUG_ERR("request invalid reader handle [%d]", msg->param1); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_REQUEST_CLOSE_SESSION : +#if 0 + { + Message response(*msg); + ServerSession *session = NULL; + + SCARD_DEBUG("[MSG_REQUEST_CLOSE_SESSION]"); + + if (msg->param1 != 0) + { + session = (ServerSession *)msg->param1; + + session->closeSync(); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_CLOSE_SESSION]"); + + response.param1 = -1; + response.error = -1; + + if (resource->isValidSessionHandle(socket, msg->error/* service context */, msg->param1)) + { + resource->removeSession(socket, msg->error/* service context */, msg->param1); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_REQUEST_OPEN_CHANNEL : +#if 0 + { + Message response(*msg); + ServerSession *session = NULL; + + SCARD_DEBUG("[MSG_REQUEST_OPEN_CHANNEL]"); + + if (/* check valid session handle */msg->param2 != 0) + { + ServerChannel *channel = NULL; + + session = (ServerSession *)msg->param2; + + if (msg->param1 == 0) + channel = (ServerChannel *)session->openBasicChannelSync(msg->data, msg->caller); + else + channel = (ServerChannel *)session->openLogicalChannelSync(msg->data, msg->caller); + + if (channel != NULL) + { + response.param1 = (unsigned int)channel; + response.param2 = channel->getChannelID(); + response.error = 0; + response.data = channel->getSelectResponse(); + } + else + { + SCARD_DEBUG_ERR("channel is null."); + + /* set error value */ + response.param1 = 0; + response.param2 = 0; + response.error = -4; + response.data.releaseBuffer(); + } + } + else + { + SCARD_DEBUG_ERR("session is invalid"); + + response.param1 = 0; + response.param2 = 0; + response.error = -1; + response.data.releaseBuffer(); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + Message response(*msg); + unsigned int channelID = -1; + + SCARD_DEBUG("[MSG_REQUEST_OPEN_CHANNEL]"); + + response.param1 = 0; + response.param2 = 0; + response.error = -1; + response.data.releaseBuffer(); + + channelID = resource->createChannel(socket, msg->error/* service context */, msg->param2, msg->param1, msg->data); + if (channelID != IntegerHandle::INVALID_HANDLE) + { + ServerChannel *temp = (ServerChannel *)resource->getChannel(socket, msg->error/* service context */, channelID); + + if (temp != NULL) + { + response.param1 = channelID; + response.param2 = temp->channelNum; + response.error = 0; + response.data = temp->selectResponse; + } + else + { + SCARD_DEBUG_ERR("IS IT POSSIBLE??????????????????"); + } + } + else + { + SCARD_DEBUG_ERR("channel is null."); + + /* set error value */ + response.error = -4; + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_REQUEST_GET_CHANNEL_COUNT : + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_GET_CHANNEL_COUNT]"); + + response.error = 0; + + response.param1 = resource->getChannelCount(socket, msg->error/* service context */, msg->param1); + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } + break; + + case Message::MSG_REQUEST_CLOSE_CHANNEL : +#if 0 + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_CLOSE_CHANNEL]"); + + if (msg->param1 != 0) + { + ServerChannel *channel = NULL; + + channel = (ServerChannel *)msg->param1; + + channel->closeSync(); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_CLOSE_CHANNEL]"); + + response.error = 0; + + if (resource->getChannel(socket, msg->error/* service context */, msg->param1) != NULL) + { + resource->removeChannel(socket, msg->error/* service context */, msg->param1); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_REQUEST_GET_ATR : +#if 0 + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_GET_ATR]"); + + if (msg->param1 != 0) + { + ServerChannel *channel = NULL; + + channel = (ServerChannel *)msg->param1; + + channel->closeSync(); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + int rv; + Message response(*msg); + ByteArray result; + ServiceInstance *client = NULL; + + SCARD_DEBUG("[MSG_REQUEST_GET_ATR]"); + + response.param1 = 0; + response.param2 = 0; + response.error = -1; + + if ((client = resource->getService(socket, msg->error/* service context */)) != NULL) + { + Terminal *terminal = NULL; + + if ((terminal = client->getTerminal(msg->param1)) != NULL) + { + if ((rv = terminal->getATRSync(result)) == 0) + { + response.data = result; + response.error = 0; + } + else + { + SCARD_DEBUG_ERR("transmit failed [%d]", rv); + + response.error = rv; + } + } + else + { + SCARD_DEBUG_ERR("getTerminal failed : socket [%d], context [%d], session [%d]", socket, msg->error/* service context */, msg->param1); + } + } + else + { + SCARD_DEBUG_ERR("getClient failed : socket [%d], context [%d], session [%d]", socket, msg->error/* service context */, msg->param1); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_REQUEST_TRANSMIT : +#if 0 + { + Message response(*msg); + ByteArray result; + int rv; + + SCARD_DEBUG("[MSG_REQUEST_TRANSMIT]"); + + if (msg->param1 != 0) + { + ServerChannel *channel = NULL; + + channel = (ServerChannel *)msg->param1; + + if ((rv = channel->transmitSync(msg->data, result)) == 0) + { + response.data = result; + } + else + { + SCARD_DEBUG_ERR("transmit failed [%d]", rv); + } + } + +// if (resource->isValidChannelHandle((void *)msg->param1)) +// { +// } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + int rv; + Message response(*msg); + ByteArray result; + Channel *channel = NULL; + + SCARD_DEBUG("[MSG_REQUEST_TRANSMIT]"); + + response.param1 = 0; + response.param2 = 0; + response.error = -1; + + if ((channel = resource->getChannel(socket, msg->error/* service context */, msg->param1)) != NULL) + { + if ((rv = channel->transmitSync(msg->data, result)) == 0) + { + response.data = result; + response.error = 0; + } + else + { + SCARD_DEBUG_ERR("transmit failed [%d]", rv); + + response.error = rv; + } + } + else + { + SCARD_DEBUG_ERR("invalid handle : socket [%d], context [%d], channel [%d]", socket, msg->error/* service context */, msg->param1); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + } +#endif + break; + + case Message::MSG_OPERATION_RELEASE_CLIENT : +#if 0 + { + Message response(*msg); + + SCARD_DEBUG("[MSG_REQUEST_CLOSE_CHANNEL]"); + + if (msg->param1 != 0) + { + ServerChannel *channel = NULL; + + channel = (ServerChannel *)msg->param1; + + channel->closeSync(); + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(msg->getPeerSocket(), &response); + } +#else + { + SCARD_DEBUG("[MSG_OPERATION_RELEASE_CLIENT]"); + + resource->removeClient(msg->param1); + } +#endif + break; + + default : + SCARD_DEBUG("unknown message [%s], socket [%d]", msg->toString(), socket); + break; + } + + return NULL; + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerIPC.cpp b/server/ServerIPC.cpp new file mode 100644 index 0000000..d44784e --- /dev/null +++ b/server/ServerIPC.cpp @@ -0,0 +1,246 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServerIPC.h" +#include "ServerResource.h" +#include "ServerDispatcher.h" + +namespace smartcard_service_api +{ + ServerIPC::ServerIPC():IPCHelper() + { + SCARD_BEGIN(); + + setDispatcher(ServerDispatcher::getInstance()); + + SCARD_END(); + } + + ServerIPC::~ServerIPC() + { + } + + ServerIPC *ServerIPC::getInstance() + { + static ServerIPC instance; + + return &instance; + } + + bool ServerIPC::acceptClient() + { + GIOCondition condition = (GIOCondition)(G_IO_ERR | G_IO_HUP | G_IO_IN); + socklen_t addrlen = 0; + int client_sock_fd = 0; + GIOChannel *client_channel = NULL; + int client_src_id; + + SCARD_DEBUG("client is trying to connect to server"); + + pthread_mutex_lock(&ipcLock); + client_sock_fd = accept(ipcSocket, NULL, &addrlen); + pthread_mutex_unlock(&ipcLock); + + if (client_sock_fd < 0) + { + SCARD_DEBUG_ERR("can not accept client"); + goto ERROR; + } + + SCARD_DEBUG("client is accepted by server"); + + if ((client_channel = g_io_channel_unix_new(client_sock_fd)) == NULL) + { + SCARD_DEBUG_ERR("create new g io channel is failed"); + goto ERROR; + } + + if ((client_src_id = g_io_add_watch(client_channel, condition, &IPCHelper::channelCallbackFunc, this)) < 1) + { + SCARD_DEBUG_ERR("add io callback is failed"); + goto ERROR; + } + + SCARD_DEBUG("client socket is bound with g_io_channel"); + + if (ServerResource::getInstance().createClient(client_channel, client_sock_fd, client_src_id, 0, -1) == false) + { + SCARD_DEBUG_ERR("failed to add client"); + } + + return true; + +ERROR : + if (client_channel != NULL) + { + g_io_channel_unref(client_channel); + } + + if (client_sock_fd != -1) + { + shutdown(client_sock_fd, SHUT_RDWR); + close(client_sock_fd); + } + + return false; + } + + void ServerIPC::restartServerIPC() + { + if (watchId != 0) + { + g_source_remove(watchId); + watchId = 0; + } + + if (ioChannel != NULL) + { + g_io_channel_unref(ioChannel); + ioChannel = NULL; + } + + if (ipcSocket != -1) + { + shutdown(ipcSocket, SHUT_RDWR); + close(ipcSocket); + + ipcSocket = -1; + } + + createListenSocket(); + } + + void ServerIPC::releaseClient(void *channel, int socket, int watchID) + { + if (watchID != 0) + { + g_source_remove(watchID); + } + + if (channel != NULL) + { + g_io_channel_unref((GIOChannel *)channel); + } + + if (socket >= 0) + { + shutdown(socket, SHUT_RDWR); + close(socket); + } + } + + int ServerIPC::handleIOErrorCondition(void *channel, GIOCondition condition) + { + SCARD_BEGIN(); + + if(channel == ioChannel) + { + SCARD_DEBUG("server socket is closed"); + restartServerIPC(); + } + else + { + DispatcherMsg *dispMsg = NULL; + int peerSocket = g_io_channel_unix_get_fd((GIOChannel *)channel); + + SCARD_DEBUG("client socket is closed, socket [%d]", peerSocket); + + /* push messsage to dispatcher */ + dispMsg = new DispatcherMsg(); + + dispMsg->message = Message::MSG_OPERATION_RELEASE_CLIENT; + dispMsg->param1 = peerSocket; + dispMsg->setPeerSocket(peerSocket); + + /* push to dispatcher */ + ServerDispatcher::getInstance()->pushMessage(dispMsg); + } + + SCARD_END(); + + return FALSE; + } + + int ServerIPC::handleInvalidSocketCondition(void *channel, GIOCondition condition) + { + SCARD_BEGIN(); + SCARD_END(); + + return FALSE; + } + + int ServerIPC::handleIncomingCondition(void *channel, GIOCondition condition) + { + int result = FALSE; + + SCARD_BEGIN(); + + if(channel == ioChannel) + { + /* connect state. should accept */ + SCARD_DEBUG("new client connected"); + + result = acceptClient(); + } + else + { + int peerSocket = g_io_channel_unix_get_fd((GIOChannel *)channel); + + SCARD_DEBUG("data incomming from [%d]", peerSocket); + + if (peerSocket >= 0) + { + Message *msg = NULL; + + /* read message */ + if ((msg = retrieveMessage(peerSocket)) != NULL) + { + DispatcherMsg *dispMsg = new DispatcherMsg(msg, peerSocket); + + /* push to dispatcher */ + ServerDispatcher::getInstance()->pushMessage(dispMsg); + + result = TRUE; + + delete msg; + } + else + { + /* clear client connection */ + SCARD_DEBUG_ERR("retrieve message failed, socket [%d]", peerSocket); + } + } + else + { + SCARD_DEBUG_ERR("client context doesn't exist, socket [%d]", peerSocket); + } + } + + SCARD_END(); + + return result; + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerReader.cpp b/server/ServerReader.cpp new file mode 100644 index 0000000..7529b7f --- /dev/null +++ b/server/ServerReader.cpp @@ -0,0 +1,128 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServerSEService.h" +#include "ServerReader.h" +#include "GPSEACL.h" + +namespace smartcard_service_api +{ + ServerReader::ServerReader(ServerSEService *seService, char *name, Terminal *terminal):ReaderHelper() + { + unsigned int length = 0; + + acList = NULL; + + if (seService == NULL || name == NULL || strlen(name) == 0 || terminal == NULL) + { + SCARD_DEBUG_ERR("invalid param"); + + return; + } + + this->terminal = terminal; + this->seService = seService; + + length = strlen(name); + length = (length < sizeof(this->name)) ? length : sizeof(this->name); + memcpy(this->name, name, length); + + /* open admin channel */ + adminChannel = new ServerChannel(NULL, NULL, 0, terminal); + if (adminChannel == NULL) + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + + ServerReader::~ServerReader() + { + closeSessions(); + + if (acList != NULL) + { + delete acList; + acList = NULL; + } + + if (adminChannel != NULL) + { + delete adminChannel; + adminChannel = NULL; + } + } + + void ServerReader::closeSessions() + { + size_t i; + + for (i = 0; i < sessions.size(); i++) + { + if (sessions[i] != NULL) + ((ServerSession *)sessions[i])->closeSync(); + } + + sessions.clear(); + } + + AccessControlList *ServerReader::getAccessControlList() + { + if (acList == NULL) + { + /* load access control */ + acList = new GPSEACL(adminChannel); + if (acList != NULL) + { + acList->loadACL(); + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + + return acList; + } + + ServerSession *ServerReader::openSessionSync() + { + return openSessionSync(ByteArray::EMPTY, NULL); + } + + ServerSession *ServerReader::openSessionSync(ByteArray packageCert, void *caller) + { + ServerSession *session = NULL; + + session = new ServerSession(this, packageCert, caller, terminal); + if (session == NULL) + return session; + + sessions.push_back(session); + + return session; + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerResource.cpp b/server/ServerResource.cpp new file mode 100644 index 0000000..f8ad898 --- /dev/null +++ b/server/ServerResource.cpp @@ -0,0 +1,816 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServerResource.h" +#include "TerminalInterface.h" +#include "APDUHelper.h" +#include "SignatureHelper.h" +#include "GPSEACL.h" + +namespace smartcard_service_api +{ + unsigned int IntegerHandle::newHandle = 0; + set IntegerHandle::setHandles; + PMutex IntegerHandle::mutexLock; + + unsigned int IntegerHandle::assignHandle() + { + SCOPE_LOCK(mutexLock) + { + pair::iterator, bool> result; + + do + { + newHandle++; + if (newHandle == (unsigned int)-1) + { + newHandle = 1; + } + + result = setHandles.insert(newHandle); + + } + while (!result.second); + } + + SCARD_DEBUG("assign handle : newHandle [%d]", newHandle); + + return newHandle; + } + + void IntegerHandle::releaseHandle(unsigned int handle) + { + SCARD_DEBUG("will be released : Handle [%d]", handle); + + SCOPE_LOCK(mutexLock) + { + setHandles.erase(handle); + } + } + +#define OMAPI_SE_PATH "/usr/lib/se" + + ServerResource::ServerResource() + { + SCARD_BEGIN(); + + serverIPC = ServerIPC::getInstance(); + serverDispatcher = ServerDispatcher::getInstance(); + +#if 1 + loadSecureElements(); +#endif + SCARD_END(); + } + + ServerResource::~ServerResource() + { + } + + ServerResource &ServerResource::getInstance() + { + static ServerResource serverResource; + + return serverResource; + } + + bool ServerResource::createClient(void *ioChannel, int socket, int watchID, int state, int pid) + { + bool result = false; + + if (getClient(socket) == NULL) + { + ClientInstance *instance = new ClientInstance(ioChannel, socket, watchID, state, pid); + if (instance != NULL) + { + mapClients.insert(make_pair(socket, instance)); + result = true; + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + else + { + SCARD_DEBUG_ERR("client already exist [%d]", socket); + } + + return result; + } + + ClientInstance *ServerResource::getClient(int socket) + { + ClientInstance *result = NULL; + map::iterator item; + + if ((item = mapClients.find(socket)) != mapClients.end()) + { + result = item->second; + } + + return result; + } + + void ServerResource::setPID(int socket, int pid) + { + map::iterator item; + + if ((item = mapClients.find(socket)) != mapClients.end()) + { + if (item->second->getPID() < 0) + item->second->setPID(pid); + } + } + + void ServerResource::removeClient(int socket) + { + map::iterator item; + + if ((item = mapClients.find(socket)) != mapClients.end()) + { + ServerIPC::getInstance()->releaseClient(item->second->getIOChannel(), item->second->getSocket(), item->second->getWatchID()); + + delete item->second; + mapClients.erase(item); + } + else + { + SCARD_DEBUG("client exists already [%d]", socket); + } + } + + void ServerResource::removeClients() + { + map::iterator item; + + for (item = mapClients.begin(); item != mapClients.end(); item++) + { + ServerIPC::getInstance()->releaseClient(item->second->getIOChannel(), item->second->getSocket(), item->second->getWatchID()); + + delete item->second; + } + + mapClients.clear(); + } + + bool ServerResource::createService(int socket, unsigned int context) + { + bool result = false; + ClientInstance *instance = NULL; + + if ((instance = getClient(socket)) != NULL) + { + if ((result = instance->createService(context)) == false) + { + SCARD_DEBUG_ERR("ClientInstance::createService failed [%d] [%d]", socket, context); + } + } + else + { + SCARD_DEBUG_ERR("client doesn't exist [%d]", socket); + } + + return result; + } + + ServiceInstance *ServerResource::getService(int socket, unsigned int context) + { + ServiceInstance *result = NULL; + ClientInstance *instance = NULL; + + if ((instance = getClient(socket)) != NULL) + { + result = instance->getService(context); + } + else + { + SCARD_DEBUG_ERR("client doesn't exist [%d]", socket); + } + + return result; + } + + void ServerResource::removeService(int socket, unsigned int context) + { + ClientInstance *instance = NULL; + + if ((instance = getClient(socket)) != NULL) + { + instance->removeService(context); + } + else + { + SCARD_DEBUG_ERR("client doesn't exist [%d]", socket); + } + } + + void ServerResource::removeServices(int socket) + { + ClientInstance *instance = NULL; + + if ((instance = getClient(socket)) != NULL) + { + instance->removeServices(); + } + else + { + SCARD_DEBUG_ERR("client doesn't exist [%d]", socket); + } + } + + Terminal *ServerResource::getTerminal(unsigned int terminalID) + { + Terminal *result = NULL; + map::iterator item; + + if ((item = mapTerminals.find(terminalID)) != mapTerminals.end()) + { + result = item->second; + } + else + { + SCARD_DEBUG_ERR("Terminal doesn't exist [%d]", terminalID); + } + + return result; + } + + Terminal *ServerResource::getTerminal(const char *name) + { + Terminal *result = NULL; + map::iterator item; + + for (item = mapTerminals.begin(); item != mapTerminals.end(); item++) + { + if (strncmp(name, item->second->getName(), strlen(name)) == 0) + { + result = item->second; + break; + } + } + + return result; + } + + unsigned int ServerResource::createSession(int socket, unsigned int context, unsigned int terminalID, ByteArray packageCert, void *caller) + { + unsigned int result = -1; + Terminal *temp = NULL; + ServiceInstance *instance = NULL; + + if ((instance = getService(socket, context)) != NULL) + { + if ((temp = getTerminal(terminalID)) != NULL) + { + result = instance->openSession(temp, packageCert, caller); + } + } + else + { + SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context); + } + + return result; + } + + ServerSession *ServerResource::getSession(int socket, unsigned int context, unsigned int sessionID) + { + ServerSession *result = NULL; + ServiceInstance *instance = NULL; + + if ((instance = getService(socket, context)) != NULL) + { + result = instance->getSession(sessionID); + } + else + { + SCARD_DEBUG_ERR("Session doesn't exist : socket [%d], context [%d], handle [%d]", socket, context, sessionID); + } + + return result; + } + + unsigned int ServerResource::getChannelCount(int socket, unsigned int context, unsigned int sessionID) + { + unsigned int result = -1; + ServiceInstance *instance = NULL; + + if ((instance = getService(socket, context)) != NULL) + { + result = instance->getChannelCountBySession(sessionID); + } + else + { + SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context); + } + + return result; + } + + void ServerResource::removeSession(int socket, unsigned int context, unsigned int sessionID) + { + ServiceInstance *instance = NULL; + + if ((instance = getService(socket, context)) != NULL) + { + instance->closeSession(sessionID); + } + else + { + SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context); + } + } + + unsigned int ServerResource::createChannel(int socket, unsigned int context, unsigned int sessionID, int channelType, ByteArray aid) + { + unsigned int result = -1; + ServiceInstance *client = NULL; + + if ((client = getService(socket, context)) != NULL) + { + if (client->isVaildSessionHandle(sessionID) == true) + { + AccessControlList *acList = NULL; + ServerSession *session = NULL; + Terminal *terminal = NULL; + + terminal = client->getTerminal(sessionID); + session = client->getSession(sessionID); + if (terminal != NULL && session != NULL) + { + int rv = 0; + int channelNum = 0; + ByteArray certHash; + ByteArray selectResponse; + ByteArray command; + char filename[1024] = { 0, }; + + /* check exceptional case */ + SignatureHelper::getProcessName(client->getParent()->getPID(), filename, sizeof(filename)); + if (strncmp(filename, "ozD3Dw1MZruTDKHWGgYaDib2B2LV4/nfT+8b/g1Vsk8=", sizeof(filename)) != 0) + { +#if 1 + certHash = session->packageCert; +#else + certHash = client->getParent()->getCertificationHash(); +#endif + /* request open channel sequence */ + if ((acList = getAccessControlList(terminal)) == NULL) + { + SCARD_DEBUG_ERR("acList is null"); + + return result; + } + + if (acList->isAuthorizedAccess(aid, certHash) == false) + { + SCARD_DEBUG_ERR("unauthorized access, aid %s, hash %s", aid.toString(), certHash.toString()); + + return result; + } + } + + if (channelType == 1) + { + ByteArray response; + + /* open channel */ + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY); + rv = terminal->transmitSync(command, response); + + if (rv == 0 && response.getLength() >= 2) + { + ResponseHelper resp(response); + + if (resp.getStatus() == 0) + { + channelNum = resp.getDataField()[0]; + + SCARD_DEBUG("channelNum [%d]", channelNum); + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), response[response.getLength() - 2], response[response.getLength() - 1]); + + return result; + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, response.getLength()); + + return result; + } + } + + /* select aid */ + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, channelNum, aid); + rv = terminal->transmitSync(command, selectResponse); + if (rv == 0 && selectResponse.getLength() >= 2) + { + ResponseHelper resp(selectResponse); + + if (resp.getStatus() == 0) + { + result = client->openChannel(sessionID, channelNum); + if (result != IntegerHandle::INVALID_HANDLE) + { + ServerChannel *temp = (ServerChannel *)client->getChannel(result); + if (temp != NULL) + { + /* set select response */ + temp->selectResponse = selectResponse; + } + else + { + SCARD_DEBUG_ERR("IS IT POSSIBLE??????????????????"); + } + } + else + { + SCARD_DEBUG_ERR("channel is null."); + } + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), selectResponse[selectResponse.getLength() - 2], selectResponse[selectResponse.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, selectResponse.getLength()); + } + + } + else + { + SCARD_DEBUG_ERR("session is invalid [%d]", sessionID); + } + } + else + { + SCARD_DEBUG_ERR("session is invalid [%d]", sessionID); + } + } + else + { + SCARD_DEBUG_ERR("getClient is failed [%d] [%d]", socket, context); + } + + return result; + } + + Channel *ServerResource::getChannel(int socket, unsigned int context, unsigned int channelID) + { + Channel *result = NULL; + ServiceInstance *instance = NULL; + + if ((instance = getService(socket, context)) != NULL) + { + result = instance->getChannel(channelID); + } + else + { + SCARD_DEBUG_ERR("Channel doesn't exist : socket [%d], context [%d], handle [%d]", socket, context, channelID); + } + + return result; + } + + void ServerResource::removeChannel(int socket, unsigned int context, unsigned int channelID) + { + ServiceInstance *instance = NULL; + + if ((instance = getService(socket, context)) != NULL) + { + instance->closeChannel(channelID); + } + else + { + SCARD_DEBUG_ERR("getService doesn't exist : socket [%d], context [%d]", socket, context); + } + } + + AccessControlList *ServerResource::getAccessControlList(Terminal *terminal) + { + AccessControlList *result = NULL; + map::iterator item; + + if ((item = mapACL.find(terminal)) == mapACL.end()) + { + ServerChannel *channel = new ServerChannel(NULL, NULL, 0, terminal); + if (channel != NULL) + { + /* load access control */ + result = new GPSEACL(channel); + if (result != NULL) + { + result->loadACL(); + + mapACL.insert(make_pair(terminal, result)); + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + else + { + result = item->second; + } + + return result; + } + + Terminal *ServerResource::createInstance(void *library) + { + Terminal *terminal = NULL; + terminal_create_instance_fn createInstance = NULL; + + /* create se instance */ + createInstance = (terminal_create_instance_fn)dlsym(library, "create_instance"); + if (createInstance != NULL) + { + terminal = (Terminal *)createInstance(); + if (terminal != NULL) + { + SCARD_DEBUG("terminal [%p]", terminal); + } + else + { + SCARD_DEBUG_ERR("terminal is null"); + } + } + else + { + SCARD_DEBUG_ERR("create_instance is null [%d]", errno); + } + + return terminal; + } + + bool ServerResource::appendSELibrary(char *library) + { + void *libHandle = NULL; + bool result = false; + + libHandle = dlopen(library, RTLD_LAZY); + if (libHandle != NULL) + { + Terminal *terminal = NULL; + + terminal = createInstance(libHandle); + if (terminal != NULL) + { + unsigned int handle = IntegerHandle::assignHandle(); + + mapTerminals.insert(make_pair(handle, terminal)); + libraries.push_back(libHandle); + + terminal->setStatusCallback(&ServerResource::terminalCallback); + + SCARD_DEBUG("register success [%s] [%p] [%s] [%p]", library, libHandle, terminal->getName(), terminal); + + result = true; + } + else + { + SCARD_DEBUG_ERR("terminal is null [%s]", library); + + dlclose(libHandle); + } + } + else + { + SCARD_DEBUG_ERR("it is not se file [%s] [%d]", library, errno); + } + + return result; + } + + int ServerResource::loadSecureElements() + { + int result; + void *libHandle; + DIR *dir = NULL; + struct dirent *entry = NULL; + + if ((dir = opendir(OMAPI_SE_PATH)) != NULL) + { + while ((entry = readdir(dir)) != NULL) + { + if (strncmp(entry->d_name, ".", 1) != 0 && strncmp(entry->d_name, "..", 2) != 0) + { + char fullPath[1024] = { 0, }; + + /* TODO : need additional name rule :) */ + + /* open each files */ + libHandle = NULL; + + snprintf(fullPath, sizeof(fullPath), "%s/%s", OMAPI_SE_PATH, entry->d_name); + + SCARD_DEBUG("se name [%s]", fullPath); + + result = appendSELibrary(fullPath); + } + } + + closedir(dir); + + result = 0; + } + else + { + result = -1; + } + + return result; + } + + void ServerResource::unloadSecureElements() + { + size_t i; + map::iterator item; + + for (item = mapTerminals.begin(); item != mapTerminals.end(); item++) + { + item->second->finalize(); + + IntegerHandle::releaseHandle(item->first); + } + + mapTerminals.clear(); + + for (i = 0; i < libraries.size(); i++) + { + if (libraries[i] != NULL) + dlclose(libraries[i]); + } + + libraries.clear(); + } + + bool ServerResource::isValidReaderHandle(unsigned int reader) + { + return (getTerminal(reader) != NULL); + } + + bool ServerResource::isValidSessionHandle(int socket, unsigned int context, unsigned int session) + { + ServiceInstance *instance = NULL; + + return (((instance = getService(socket, context)) != NULL) && (getService(socket, context)->isVaildSessionHandle(session))); + } + + int ServerResource::getReadersInformation(ByteArray &info) + { + int result = 0; + unsigned char *buffer = NULL; + unsigned int length = 0; + unsigned int offset = 0; + unsigned int nameLen = 0; + + if (mapTerminals.size() > 0) + { + map::iterator item; + + for (item = mapTerminals.begin(); item != mapTerminals.end(); item++) + { + if (item->second->isSecureElementPresence()) + { + length += sizeof(nameLen) + strlen(item->second->getName()) + sizeof(unsigned int); + result++; + } + } + + buffer = new unsigned char[length]; + if (buffer != NULL) + { + memset(buffer, 0, length); + + for (item = mapTerminals.begin(); item != mapTerminals.end(); item++) + { + if (item->second->isSecureElementPresence()) + { + nameLen = strlen(item->second->getName()); + + memcpy(buffer + offset, &nameLen, sizeof(nameLen)); + offset += sizeof(nameLen); + + memcpy(buffer + offset, item->second->getName(), nameLen); + offset += nameLen; + + memcpy(buffer + offset, &item->first, sizeof(unsigned int)); + offset += sizeof(unsigned int); + } + } + + info.setBuffer(buffer, length); + delete []buffer; + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + result = -1; + } + } + else + { + SCARD_DEBUG("no secure element"); + } + + return result; + } + + bool ServerResource::sendMessageToAllClients(Message &msg) + { + bool result = true; + map::iterator item; + + for (item = mapClients.begin(); item != mapClients.end(); item++) + { + if (item->second->sendMessageToAllServices(item->second->getSocket(), msg) == false) + result = false; + } + + return result; + } + + void ServerResource::terminalCallback(void *terminal, int event, int error, void *user_param) + { + SCARD_BEGIN(); + + switch (event) + { + case Terminal::NOTIFY_SE_AVAILABLE : + { + Message msg; + + SCARD_DEBUG("[NOTIFY_SE_AVAILABLE]"); + + SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param); + + /* send all client to refresh reader */ + msg.message = msg.MSG_NOTIFY_SE_INSERTED; + msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1); + + ServerResource::getInstance().sendMessageToAllClients(msg); + } + break; + + case Terminal::NOTIFY_SE_NOT_AVAILABLE : + { + Message msg; + + SCARD_DEBUG("[NOTIFY_SE_NOT_AVAILABLE]"); + + SCARD_DEBUG("terminal [%s], event [%d], error [%d], user_param [%p]", (char *)terminal, event, error, user_param); + + /* send all client to refresh reader */ + msg.message = msg.MSG_NOTIFY_SE_REMOVED; + msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1); + + ServerResource::getInstance().sendMessageToAllClients(msg); + } + break; + + default : + break; + } + + SCARD_END(); + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerSEService.cpp b/server/ServerSEService.cpp new file mode 100644 index 0000000..0de9769 --- /dev/null +++ b/server/ServerSEService.cpp @@ -0,0 +1,396 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Message.h" +#include "TerminalInterface.h" +#include "ServerSEService.h" +#include "ServerResource.h" + +namespace smartcard_service_api +{ +#define OMAPI_SE_PATH "/usr/lib/se" + + ServerSEService::ServerSEService():SEServiceHelper() + { +#if 0 + openSELibraries(); +#endif + } + + ServerSEService::~ServerSEService() + { +#if 0 + closeSELibraries(); +#endif + } + + ServerSEService &ServerSEService::getInstance() + { + static ServerSEService seService; + + return seService; + } + + Terminal *ServerSEService::createInstance(void *library) + { + Terminal *terminal = NULL; + terminal_create_instance_fn createInstance = NULL; + + /* create se instance */ + createInstance = (terminal_create_instance_fn)dlsym(library, "create_instance"); + if (createInstance != NULL) + { + terminal = (Terminal *)createInstance(); + if (terminal != NULL) + { + SCARD_DEBUG("terminal [%p]", terminal); + } + else + { + SCARD_DEBUG_ERR("terminal is null"); + } + } + else + { + SCARD_DEBUG_ERR("create_instance is null [%d]", errno); + } + + return terminal; + } + + bool ServerSEService::appendSELibrary(char *library) + { + void *libHandle = NULL; + bool result = false; + + libHandle = dlopen(library, RTLD_LAZY); + if (libHandle != NULL) + { + Terminal *terminal = NULL; + + terminal = createInstance(libHandle); + if (terminal != NULL) + { + SCARD_DEBUG("SE info : [%s] [%s]", library, terminal->getName()); + + libraries.push_back(libHandle); + + pair newPair(terminal->getName(), terminal); + mapTerminals.insert(newPair); + + if (terminal->isSecureElementPresence() == true) + { + ServerReader *reader = new ServerReader(this, terminal->getName(), terminal); + if (reader != NULL) + { + SCARD_DEBUG("register success [%s]", terminal->getName()); + + readers.push_back(reader); + } + else + { + SCARD_DEBUG_ERR("ServerReader alloc failed [%s]", terminal->getName()); + /* throw exception */ + } + } + else + { + SCARD_DEBUG("SE is not ready [%s]", terminal->getName()); + } + + result = true; + } + else + { + SCARD_DEBUG_ERR("createInstance failed [%s]", library); + + dlclose(libHandle); + } + } + else + { + SCARD_DEBUG_ERR("it is not se file [%s] [%d]", library, errno); + } + + return result; + } + + int ServerSEService::openSELibraries() + { + int result; + void *libHandle; + DIR *dir = NULL; + struct dirent *entry = NULL; + + if ((dir = opendir(OMAPI_SE_PATH)) != NULL) + { + while ((entry = readdir(dir)) != NULL) + { + if (strncmp(entry->d_name, ".", 1) != 0 && strncmp(entry->d_name, "..", 2) != 0) + { + char fullPath[1024] = { 0, }; + + /* need additional name rule :) */ + /* open each files */ + libHandle = NULL; + + snprintf(fullPath, sizeof(fullPath), "%s/%s", OMAPI_SE_PATH, entry->d_name); + + SCARD_DEBUG("se name [%s]", fullPath); + + result = appendSELibrary(fullPath); + } + } + + closedir(dir); + + result = 0; + } + else + { + result = -1; + } + + return result; + } + + void ServerSEService::closeSELibraries() + { + if (libraries.size() > 0) + { + size_t i; + + for (i = 0; i < libraries.size(); i++) + { + if (libraries[i] != NULL) + dlclose(libraries[i]); + } + } + } + +#if 0 + bool ServerSEService::isValidReaderHandle(void *handle) + { + bool result = false; + size_t i; + + for (i = 0; i < readers.size(); i++) + { + if ((void *)readers[i] == handle) + { + result = true; + break; + } + } + + return false; + } +#endif + +#if 0 + bool ServerSEService::dispatcherCallback(void *message, int socket) + { + unsigned char *buffer = NULL; + unsigned int length = 0; + unsigned int offset = 0; + unsigned int nameLen = 0; + + ByteArray result; + vector readers; + Message response(*(Message *)message); + +// response.param1 = resource->getSECount(); +// response.data = resource->getReadersInformation(); + + readers = ServerSEService::getInstance().getReaders(); + if (readers.size() > 0) + { + size_t i; + ServerReader *reader; + + for (i = 0; i < readers.size(); i++) + { + reader = (ServerReader *)readers[i]; + + /* check se existance */ + if (reader->isSecureElementPresent() == true) + { + length += sizeof(nameLen) + strlen(reader->getName()) + sizeof(reader); + } + } + + if (length > 0) + { + buffer = new unsigned char[length]; + if (buffer == NULL) + { + SCARD_DEBUG_ERR("alloc failed"); + + return false; + } + memset(buffer, 0, length); + + for (i = 0; i < readers.size(); i++) + { + reader = (ServerReader *)readers[i]; + + /* check se existance */ + if (reader->isSecureElementPresent() == true) + { + nameLen = strlen(reader->getName()); + + memcpy(buffer + offset, &nameLen, sizeof(nameLen)); + offset += sizeof(nameLen); + + memcpy(buffer + offset, reader->getName(), nameLen); + offset += nameLen; + + memcpy(buffer + offset, &reader, sizeof(reader)); + offset += sizeof(reader); + } + } + + result.setBuffer(buffer, length); + } + } + + response.param1 = readers.size(); + response.data = result; + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + + return true; + } +#else + bool ServerSEService::dispatcherCallback(void *message, int socket) + { + int count = 0; + ByteArray info; + Message *msg = (Message *)message; + Message response(*msg); + ServerResource &resource = ServerResource::getInstance(); + + if (resource.getService(socket, msg->error) == NULL) + { + if (resource.createService(socket, msg->error) == true) + { + SCARD_DEBUG_ERR("client added : pid [%d]", msg->error); + } + else + { + SCARD_DEBUG_ERR("createClient failed"); + + response.param1 = 0; + response.error = -1; + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + + return false; + } + } + + if ((count = resource.getReadersInformation(info)) > 0) + { + response.param1 = count; + response.param2 = 0; + response.error = 0; + response.data = info; + } + else + { + SCARD_DEBUG("no secure elements"); + + response.error = -1; + } + + /* response to client */ + ServerIPC::getInstance()->sendMessage(socket, &response); + + return false; + } +#endif + + void ServerSEService::terminalCallback(void *terminal, int event, int error, void *user_param) + { + Message msg; +// Terminal *term = NULL; + + switch (event) + { + case Terminal::NOTIFY_SE_AVAILABLE : + { + /* add right se reader */ +// if ((term = ServerResource::getInstance().getTerminal((char *)terminal)) != NULL) +// { +// SCARD_DEBUG("terminal : [%s]", (char *)terminal); +// +// term->initialize(); +// } +// else +// { +// SCARD_DEBUG("unknown terminal : [%s]", (char *)terminal); +// } + + /* send all client to refresh reader */ + msg.message = msg.MSG_NOTIFY_SE_INSERTED; + msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1); + + ServerResource::getInstance().sendMessageToAllClients(msg); + } + break; + + case Terminal::NOTIFY_SE_NOT_AVAILABLE : + { + /* remove right se reader */ +// if ((term = ServerResource::getInstance().getTerminal((char *)terminal)) != NULL) +// { +// SCARD_DEBUG("terminal : [%s]", (char *)terminal); +// +// term->finalize(); +// } +// else +// { +// SCARD_DEBUG("unknown terminal : [%s]", (char *)terminal); +// } + + /* send all client to refresh reader */ + msg.message = msg.MSG_NOTIFY_SE_REMOVED; + msg.data.setBuffer((unsigned char *)terminal, strlen((char *)terminal) + 1); + + ServerResource::getInstance().sendMessageToAllClients(msg); + } + break; + + default : + break; + } + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServerSession.cpp b/server/ServerSession.cpp new file mode 100644 index 0000000..8c11e68 --- /dev/null +++ b/server/ServerSession.cpp @@ -0,0 +1,257 @@ +/* +* Copyright (c) 2012 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. +*/ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServerSession.h" +#include "ServerReader.h" +#include "ServerChannel.h" +#include "APDUHelper.h" +#include "GPSEACL.h" + +namespace smartcard_service_api +{ + ServerSession::ServerSession(ServerReader *reader, ByteArray packageCert, void *caller, Terminal *terminal):SessionHelper(reader) + { + this->caller = NULL; + this->terminal = NULL; + + if (caller == NULL || terminal == NULL) + { + SCARD_DEBUG_ERR("invalid param"); + + return; + } + + this->caller = caller; + this->terminal = terminal; + this->packageCert = packageCert; + } + + ServerSession::~ServerSession() + { + if (isClosed() == false) + closeSync(); + } + + ByteArray ServerSession::getATRSync() + { + /* call get atr to terminal */ + return atr; + } + + void ServerSession::closeSync() + { + if (isClosed() == false) + { + closed = true; + closeChannels(); + } + } + + void ServerSession::closeChannels() + { + size_t i; + + for (i = 0; i < channels.size(); i++) + { + if (channels[i] != NULL) + channels[i]->closeSync(); + } + + channels.clear(); + } + + Channel *ServerSession::openBasicChannelSync(ByteArray aid) + { + return openBasicChannelSync(aid, NULL); + } + + Channel *ServerSession::openBasicChannelSync(ByteArray aid, void *caller) + { + ServerChannel *channel = NULL; + AccessControlList *acList = NULL; + ByteArray command, result; + int channelID = 0; + int rv = 0; + + SCARD_BEGIN(); + + acList = ((ServerReader *)reader)->getAccessControlList(); + if (acList == NULL) + { + SCARD_DEBUG_ERR("acList is null"); + + return channel; + } + + if (acList->isAuthorizedAccess(aid, packageCert) == false) + { + SCARD_DEBUG_ERR("unauthorized access, aid %s, hash %s", aid.toString(), packageCert.toString()); + + return channel; + } + + /* select aid */ + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, channelID, aid); + rv = terminal->transmitSync(command, result); + if (rv == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + + if (resp.getStatus() == 0) + { + channel = new ServerChannel(this, caller, channelID, terminal); + if (channel != NULL) + { + channel->selectResponse = result; + + channels.push_back(channel); + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, result.getLength()); + } + + return channel; + } + + Channel *ServerSession::openBasicChannelSync(unsigned char *aid, unsigned int length) + { + return openBasicChannelSync(ByteArray(aid, length)); + } + + Channel *ServerSession::openBasicChannelSync(unsigned char *aid, unsigned int length, void *caller) + { + return openBasicChannelSync(ByteArray(aid, length), caller); + } + + Channel *ServerSession::openLogicalChannelSync(ByteArray aid) + { + return openLogicalChannelSync(aid, NULL); + } + + Channel *ServerSession::openLogicalChannelSync(ByteArray aid, void *caller) + { + ServerChannel *channel = NULL; + AccessControlList *acList = NULL; + ByteArray command, result; + int channelID = 1; + int rv; + + acList = ((ServerReader *)reader)->getAccessControlList(); + if (acList == NULL) + { + SCARD_DEBUG_ERR("unauthorized access, aid %s, hash %s"); + + return channel; + } + + if (acList->isAuthorizedAccess(aid, packageCert) == false) + { + SCARD_DEBUG_ERR("unauthorized access, aid %s, hash %s", aid.toString(), packageCert.toString()); + + return channel; + } + + /* open channel */ + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_OPEN_LOGICAL_CHANNEL, 0, ByteArray::EMPTY); + rv = terminal->transmitSync(command, result); + + if (rv == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + + if (resp.getStatus() == 0) + { + channelID = resp.getDataField()[0]; + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + + return channel; + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, result.getLength()); + + return channel; + } + + /* select aid */ + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_DF_NAME, channelID, aid); + rv = terminal->transmitSync(command, result); + + if (rv == 0 && result.getLength() >= 2) + { + ResponseHelper resp(result); + + if (resp.getStatus() == 0) + { + channel = new ServerChannel(this, caller, channelID, terminal); + if (channel == NULL) + { + SCARD_DEBUG_ERR("alloc failed"); + + return NULL; + } + + channel->selectResponse = result; + + channels.push_back(channel); + } + else + { + SCARD_DEBUG_ERR("status word [%d][ 0x%02X 0x%02X ]", resp.getStatus(), result[result.getLength() - 2], result[result.getLength() - 1]); + } + } + else + { + SCARD_DEBUG_ERR("select apdu is failed, rv [%d], length [%d]", rv, result.getLength()); + } + + return channel; + } + + Channel *ServerSession::openLogicalChannelSync(unsigned char *aid, unsigned int length) + { + return openLogicalChannelSync(ByteArray(aid, length), NULL); + } + + Channel *ServerSession::openLogicalChannelSync(unsigned char *aid, unsigned int length, void *caller) + { + return openLogicalChannelSync(ByteArray(aid, length), caller); + } + +} /* namespace smartcard_service_api */ diff --git a/server/ServiceInstance.cpp b/server/ServiceInstance.cpp new file mode 100644 index 0000000..618b17e --- /dev/null +++ b/server/ServiceInstance.cpp @@ -0,0 +1,197 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ServiceInstance.h" +#include "ClientInstance.h" +#include "ServerResource.h" + +namespace smartcard_service_api +{ + unsigned int ServiceInstance::openSession(Terminal *terminal, ByteArray packageCert, void *caller) + { + unsigned int handle = IntegerHandle::assignHandle(); + + ServerSession *session = new ServerSession((ServerReader *)0, packageCert, caller, terminal); + + mapSessions.insert(make_pair(handle, make_pair(session, terminal))); + + return handle; + } + + ServerSession *ServiceInstance::getSession(unsigned int session) + { + ServerSession *result = NULL; + map >::iterator item; + + if ((item = mapSessions.find(session)) != mapSessions.end()) + { + /*if (item->second.first == session)*/ + result = item->second.first; + } + + return result; + } + + Terminal *ServiceInstance::getTerminal(unsigned int session) + { + Terminal *result = NULL; + map >::iterator item; + + if ((item = mapSessions.find(session)) != mapSessions.end()) + { + result = item->second.second; + } + + return result; + } + + void ServiceInstance::closeSession(unsigned int session) + { + map >::iterator item; + + if ((item = mapSessions.find(session)) != mapSessions.end()) + { + closeChannelsBySession(session); + + item->second.first->closeSync(); + + mapSessions.erase(item); + + IntegerHandle::releaseHandle(session); + } + } + + void ServiceInstance::closeSessions() + { + map >::iterator item; + + closeChannels(); + + for (item = mapSessions.begin(); item != mapSessions.end(); item++) + { + item->second.first->closeSync(); + + IntegerHandle::releaseHandle(item->first); + } + + mapSessions.clear(); + } + + unsigned int ServiceInstance::openChannel(unsigned int session, int channelNum) + { + Terminal *terminal = getTerminal(session); + ServerChannel *channel = NULL; + unsigned int handle = -1; + + /* create ServerChannel */ + channel = new ServerChannel((ServerSession *)session, (void *)parent->getPID(), channelNum, terminal); + if (channel != NULL) + { + handle = IntegerHandle::assignHandle(); + mapChannels.insert(make_pair(handle, make_pair(session, channel))); + } + else + { + SCARD_DEBUG_ERR("alloc failed"); + } + + return handle; + } + + ServerChannel *ServiceInstance::getChannel(/*unsigned int session, */unsigned int channel) + { + ServerChannel *result = NULL; + map >::iterator item; + + if ((item = mapChannels.find(channel)) != mapChannels.end()) + { + /*if (item->second.first == session)*/ + result = item->second.second; + } + + return result; + } + + unsigned int ServiceInstance::getChannelCountBySession(unsigned int session) + { + unsigned int channelCount = 0; + map >::iterator item; + + for (item = mapChannels.begin(); item != mapChannels.end(); item++) + { + if (item->second.first == session) + channelCount++; + } + + return channelCount; + } + + void ServiceInstance::closeChannel(unsigned int channel) + { + map >::iterator item; + + if ((item = mapChannels.find(channel)) != mapChannels.end()) + { + /* destroy ServerChannel */ + delete item->second.second; + + mapChannels.erase(item); + + IntegerHandle::releaseHandle(channel); + } + } + + void ServiceInstance::closeChannelsBySession(unsigned int session) + { + size_t i; + vector list; + map >::iterator item; + + for (item = mapChannels.begin(); item != mapChannels.end(); item++) + { + if (item->second.first == session) + list.push_back(item->second.first); + } + + for (i = 0; i < list.size(); i++) + { + closeChannel(list[i]); + } + } + + void ServiceInstance::closeChannels() + { + map >::iterator item; + + for (item = mapChannels.begin(); item != mapChannels.end(); item++) + { + /* destroy ServerChannel */ + delete item->second.second; + + IntegerHandle::releaseHandle(item->first); + } + + mapChannels.clear(); + } + +} /* namespace smartcard_service_api */ diff --git a/server/include/ClientInstance.h b/server/include/ClientInstance.h new file mode 100644 index 0000000..3475c7c --- /dev/null +++ b/server/include/ClientInstance.h @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2012 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 CLIENTINSTANCE_H_ +#define CLIENTINSTANCE_H_ + +/* standard library header */ +#include +//#include + +/* SLP library header */ + +/* local header */ +#include "Message.h" +#include "ServiceInstance.h" + +namespace smartcard_service_api +{ + class ClientInstance + { + private: + void *ioChannel; + int socket; + int watchID; + int state; + int pid; + ByteArray certHash; + + map mapServices; + + inline ByteArray getCertificationHash() { return certHash; } + + public: + ClientInstance(void *ioChannel, int socket, int watchID, int state, int pid) + { + this->ioChannel = ioChannel; + this->socket = socket; + this->watchID = watchID; + this->state = state; + this->pid = pid; + } + ~ClientInstance() { removeServices(); } + + inline bool operator ==(const int &socket) const { return (this->socket == socket); } + + inline void *getIOChannel() { return ioChannel; } + inline int getSocket() { return socket; } + inline int getWatchID() { return watchID; } + inline int getState() { return state; } + + void setPID(int pid); + inline int getPID() { return pid; } + + + bool createService(unsigned int context); + ServiceInstance *getService(unsigned int context); + void removeService(unsigned int context); + void removeServices(); + + bool sendMessageToAllServices(int socket, Message &msg); + }; + +} /* namespace smartcard_service_api */ +#endif /* CLIENTINSTANCE_H_ */ diff --git a/server/include/ServerChannel.h b/server/include/ServerChannel.h new file mode 100644 index 0000000..3c3a260 --- /dev/null +++ b/server/include/ServerChannel.h @@ -0,0 +1,59 @@ +/* +* Copyright (c) 2012 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 SERVERCHANNEL_H_ +#define SERVERCHANNEL_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "Channel.h" +#include "Terminal.h" +#include "ServerSession.h" + +namespace smartcard_service_api +{ + class ServerChannel: public Channel + { + private: + Terminal *terminal; + void *caller; + + ServerChannel(ServerSession *session, void *caller, int channelNum, Terminal *terminal); + + protected: + void closeSync(); + int transmitSync(ByteArray command, ByteArray &result); + + public: + ~ServerChannel(); + + int getChannelNumber(); + + int close(closeCallback callback, void *userParam) { return -1; } + int transmit(ByteArray command, transmitCallback callback, void *userParam) { return -1; }; + + friend class ServerReader; + friend class ServerSession; + friend class ServiceInstance; + friend class ServerResource; + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERCHANNEL_H_ */ diff --git a/server/include/ServerDispatcher.h b/server/include/ServerDispatcher.h new file mode 100644 index 0000000..153c3c6 --- /dev/null +++ b/server/include/ServerDispatcher.h @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2012 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 SERVERDISPATCHER_H_ +#define SERVERDISPATCHER_H_ + +/* standard library header */ + +/* SLP library header */ + +/* local header */ +#include "DispatcherHelper.h" + +namespace smartcard_service_api +{ + class ServerIPC; + + class ServerDispatcher: public DispatcherHelper + { + private: + ServerDispatcher(); + ~ServerDispatcher(); + + void *dispatcherThreadFunc(DispatcherMsg *msg, void *data); + + public: + + static ServerDispatcher *getInstance(); + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERDISPATCHER_H_ */ diff --git a/server/include/ServerIPC.h b/server/include/ServerIPC.h new file mode 100644 index 0000000..2cd9fd4 --- /dev/null +++ b/server/include/ServerIPC.h @@ -0,0 +1,53 @@ +/* +* Copyright (c) 2012 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 SERVERIPC_H_ +#define SERVERIPC_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "IPCHelper.h" + +using namespace std; + +namespace smartcard_service_api +{ + class ServerIPC: public IPCHelper + { + private: + ServerIPC(); + ~ServerIPC(); + + bool acceptClient(); + void restartServerIPC(); + void releaseClient(void *channel, int socket, int watchID); + + int handleIOErrorCondition(void *channel, GIOCondition condition); + int handleInvalidSocketCondition(void *channel, GIOCondition condition); + int handleIncomingCondition(void *channel, GIOCondition condition); + + public: + static ServerIPC *getInstance(); + + friend class ServerResource; + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERIPC_H_ */ diff --git a/server/include/ServerReader.h b/server/include/ServerReader.h new file mode 100644 index 0000000..99f558e --- /dev/null +++ b/server/include/ServerReader.h @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2012 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 SERVERREADER_H_ +#define SERVERREADER_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Terminal.h" +#include "ReaderHelper.h" +#include "ServerSession.h" +#include "ServerChannel.h" +#include "AccessControlList.h" + +using namespace std; + +namespace smartcard_service_api +{ + class ServerSEService; + + class ServerReader : public ReaderHelper + { + private: + Terminal *terminal; + ServerChannel *adminChannel; + AccessControlList *acList; + + ServerReader(ServerSEService *seService, char *name, Terminal *terminal); + + int openSession(openSessionCallback callback, void *userData) { return -1; } + int openSession(void *caller, openSessionCallback callback, void *userData) { return -1; } + + public: + ~ServerReader(); + + void closeSessions(); + + AccessControlList *getAccessControlList(); + + ServerSession *openSessionSync(); + ServerSession *openSessionSync(ByteArray packageCert, void *caller); + + friend class ServerSEService; + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERREADER_H_ */ diff --git a/server/include/ServerResource.h b/server/include/ServerResource.h new file mode 100644 index 0000000..e01d35e --- /dev/null +++ b/server/include/ServerResource.h @@ -0,0 +1,119 @@ +/* +* Copyright (c) 2012 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 SERVERRESOURCE_H_ +#define SERVERRESOURCE_H_ + +/* standard library header */ +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Terminal.h" +#include "Lock.h" +#include "ServerIPC.h" +#include "ServerDispatcher.h" +#include "ServerReader.h" +#include "ServerSession.h" +#include "ClientInstance.h" +#include "ServiceInstance.h" + +using namespace std; + +namespace smartcard_service_api +{ + class IntegerHandle + { + private: + static unsigned int newHandle; + static set setHandles; + static PMutex mutexLock; + + public: + static const unsigned int INVALID_HANDLE = (unsigned int)-1; + + static unsigned int assignHandle(); + static void releaseHandle(unsigned int); + }; + + class ServerResource + { + private: + /* non-static member */ + vector libraries; + map mapTerminals; /* unique id <-> terminal instance map */ + map mapClients; /* client pid <-> client instance map */ + map mapACL; /* terminal instance <-> access control instance map */ + + ServerIPC *serverIPC; + ServerDispatcher *serverDispatcher; + + ServerResource(); + ~ServerResource(); + + Terminal *createInstance(void *library); + bool appendSELibrary(char *library); + void clearSELibraries(); + + static void terminalCallback(void *terminal, int event, int error, void *user_param); + + public: + /* static member */ + static ServerResource &getInstance(); + + /* non-static member */ + int loadSecureElements(); + void unloadSecureElements(); + + Terminal *getTerminal(unsigned int terminalID); + Terminal *getTerminal(const char *name); + int getReadersInformation(ByteArray &info); + bool isValidReaderHandle(unsigned int reader); + + bool createClient(void *ioChannel, int socket, int watchID, int state, int pid); + ClientInstance *getClient(int socket); + void setPID(int socket, int pid); + void removeClient(int socket); + void removeClients(); + + bool createService(int socket, unsigned int context); + ServiceInstance *getService(int socket, unsigned int context); + void removeService(int socket, unsigned int context); + void removeServices(int socket); + + unsigned int createSession(int socket, unsigned int context, unsigned int terminalID, ByteArray packageCert, void *caller); + ServerSession *getSession(int socket, unsigned int context, unsigned int sessionID); + unsigned int getChannelCount(int socket, unsigned int context, unsigned int sessionID); + void removeSession(int socket, unsigned int context, unsigned int session); + bool isValidSessionHandle(int socket, unsigned int context, unsigned int sessionID); + + unsigned int createChannel(int socket, unsigned int context, unsigned int sessionID, int channelType, ByteArray aid); + Channel *getChannel(int socket, unsigned int context, unsigned int channelID); + void removeChannel(int socket, unsigned int context, unsigned int channelID); + + AccessControlList *getAccessControlList(Terminal *terminal); + + bool sendMessageToAllClients(Message &msg); + + friend void terminalCallback(void *terminal, int event, int error, void *user_param); + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERRESOURCE_H_ */ diff --git a/server/include/ServerSEService.h b/server/include/ServerSEService.h new file mode 100644 index 0000000..2df4816 --- /dev/null +++ b/server/include/ServerSEService.h @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2012 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 SERVERSESERVICE_H_ +#define SERVERSESERVICE_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "SEServiceHelper.h" +#include "Terminal.h" +#include "ServerReader.h" + +using namespace std; + +namespace smartcard_service_api +{ + class ServerSEService : public SEServiceHelper + { + private: + vector libraries; + map mapTerminals; + + ServerSEService(); + ~ServerSEService(); + + Terminal *createInstance(void *library); + bool appendSELibrary(char *library); + + int openSELibraries(); + void closeSELibraries(); + + static void terminalCallback(void *terminal, int event, int error, void *user_param); + static bool dispatcherCallback(void *message, int socket); + + public: + static ServerSEService &getInstance(); + +#if 0 + bool isValidReaderHandle(void *handle); +#endif + friend void terminalCallback(char *name, int event, int error, void *user_param); + friend bool dispatcherCallback(void *message, int socket); + friend class ServerDispatcher; + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERSESERVICE_H_ */ diff --git a/server/include/ServerSession.h b/server/include/ServerSession.h new file mode 100644 index 0000000..9ba8041 --- /dev/null +++ b/server/include/ServerSession.h @@ -0,0 +1,79 @@ +/* +* Copyright (c) 2012 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 SERVERSESSION_H_ +#define SERVERSESSION_H_ + +/* standard library header */ +#include +#include + +/* SLP library header */ + +/* local header */ +#include "ByteArray.h" +#include "Channel.h" +#include "Terminal.h" +#include "SessionHelper.h" + +using namespace std; + +namespace smartcard_service_api +{ + class ServerReader; + + class ServerSession : public SessionHelper + { + private: + void *caller; + Terminal *terminal; + ByteArray packageCert; + + ServerSession(ServerReader *reader, ByteArray packageCert, void *caller, Terminal *terminal); + + int getATR(getATRCallback callback, void *userData){ return -1; } + int close(closeSessionCallback callback, void *userData){ return -1; } + + int openBasicChannel(ByteArray aid, openChannelCallback callback, void *userData){ return -1; } + int openBasicChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData){ return -1; } + int openLogicalChannel(ByteArray aid, openChannelCallback callback, void *userData){ return -1; } + int openLogicalChannel(unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData){ return -1; } + public: + ~ServerSession(); + + ByteArray getATRSync(); + void closeSync(); + + void closeChannels(); + + Channel *openBasicChannelSync(ByteArray aid); + Channel *openBasicChannelSync(unsigned char *aid, unsigned int length); + Channel *openBasicChannelSync(ByteArray aid, void *caller); + Channel *openBasicChannelSync(unsigned char *aid, unsigned int length, void *caller); + + Channel *openLogicalChannelSync(ByteArray aid); + Channel *openLogicalChannelSync(unsigned char *aid, unsigned int length); + Channel *openLogicalChannelSync(ByteArray aid, void *caller); + Channel *openLogicalChannelSync(unsigned char *aid, unsigned int length, void *caller); + + friend class ServerReader; + friend class ServerResource; + friend class ServiceInstance; + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVERSESSION_H_ */ diff --git a/server/include/ServiceInstance.h b/server/include/ServiceInstance.h new file mode 100644 index 0000000..8e45468 --- /dev/null +++ b/server/include/ServiceInstance.h @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2012 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 SERVICEINSTANCE_H_ +#define SERVICEINSTANCE_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "Terminal.h" +#include "ServerChannel.h" +#include "ServerSession.h" + +namespace smartcard_service_api +{ + class ClientInstance; + + class ServiceInstance + { + private: + unsigned int context; + ClientInstance *parent; + map > mapSessions; /* session unique id <-> terminal instance map */ + map > mapChannels; /* channel unique id <-> (session unique id, channel instance) map */ + + public: + ServiceInstance(ClientInstance *parent, unsigned int context) + { + this->parent = parent; + this->context = context; + } + ~ServiceInstance() { closeSessions(); }; + + inline bool operator ==(const unsigned int &context) const { return (this->context == context); } + inline bool isVaildSessionHandle(unsigned int handle) { return (mapSessions.find(handle) != mapSessions.end()); } + inline bool isVaildChannelHandle(unsigned int handle) { return (mapChannels.find(handle) != mapChannels.end()); } + inline ClientInstance *getParent() { return parent; } + + unsigned int openSession(Terminal *terminal, ByteArray packageCert, void *caller); + ServerSession *getSession(unsigned int session); + void closeSession(unsigned int session); + void closeSessions(); + + Terminal *getTerminal(unsigned int session); + + unsigned int openChannel(unsigned int session, int channelNum); + ServerChannel *getChannel(/*unsigned int session, */unsigned int channel); + unsigned int getChannelCountBySession(unsigned int session); + void closeChannel(unsigned int channel); + void closeChannelsBySession(unsigned int session); + void closeChannels(); + }; + +} /* namespace smartcard_service_api */ +#endif /* SERVICEINSTANCE_H_ */ diff --git a/server/smartcard-daemon.cpp b/server/smartcard-daemon.cpp new file mode 100644 index 0000000..ef55087 --- /dev/null +++ b/server/smartcard-daemon.cpp @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2012 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. +*/ + + +/* standard library header */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Channel.h" +#include "ServerResource.h" +#include "ServerSEService.h" + +/* definition */ +using namespace std; +using namespace smartcard_service_api; + +/* global variable */ + +ServerResource *serverResource = NULL; + +static void daemonize(void) +{ + pid_t pid, sid; + + /* already a daemon */ + if (getppid() == 1) + return; + + /* Fork off the parent process */ + pid = fork(); + if (pid < 0) + { + exit(EXIT_FAILURE); + } + + if (pid > 0) + { + exit(EXIT_SUCCESS); /*Killing the Parent Process*/ + } + + /* At this point we are executing as the child process */ + umask(0); + + /* Create a new SID for the child process */ + sid = setsid(); + if (sid < 0) + { + exit(EXIT_FAILURE); + } + + /* Change the current working directory. */ + if ((chdir("/")) < 0) + { + exit(EXIT_FAILURE); + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); +} + +int main() +{ + GMainLoop* loop = NULL; + + daemonize(); + + if (!g_thread_supported()) + { + g_thread_init(NULL); + } + + serverResource = &ServerResource::getInstance(); + ServerIPC::getInstance()->createListenSocket(); + + loop = g_main_new(TRUE); + g_main_loop_run(loop); + + return 0; +} diff --git a/test-client/CMakeLists.txt b/test-client/CMakeLists.txt new file mode 100644 index 0000000..8fe03d8 --- /dev/null +++ b/test-client/CMakeLists.txt @@ -0,0 +1,51 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(smartcard-test-client CXX) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../client/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ SRCS) + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs_test_client REQUIRED glib-2.0 gthread-2.0 gobject-2.0 security-server vconf dlog) + +FOREACH(flag ${pkgs_test_client_CFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +MESSAGE("CHECK MODULE in ${PROJECT_NAME} ${pkgs_test_client_LDFLAGS}") + +# this for NFC flag + +SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -fno-strict-aliasing -Wl,-zdefs -fvisibility=hidden") + +SET(ARM_CXXFLAGS "${ARM_CXXLAGS} -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common -fpic") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARM_CXXFLAGS}") +ENDIF() + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +#ADD_DEFINITIONS("-DSLP_DEBUG") + +ADD_DEFINITIONS("-DLOG_TAG=\"SCARD_TEST\"") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_test_client_LDFLAGS} "-L../common" "-lsmartcard-service-common" "-L../client" "-lsmartcard-service" "-pie -ldl") + +#INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/test-client/test-client.cpp b/test-client/test-client.cpp new file mode 100644 index 0000000..b0137fc --- /dev/null +++ b/test-client/test-client.cpp @@ -0,0 +1,213 @@ +/* +* Copyright (c) 2012 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 +#include +#include + +#include "Debug.h" +#include "SEService.h" +#include "Reader.h" +#include "Session.h" +#include "APDUHelper.h" + +using namespace smartcard_service_api; + +typedef struct _user_context_t +{ + Session *clientSession; + SEServiceHelper *clientService; + Channel *clientChannel; +} +user_context_t; + +/* global variable */ +GMainLoop *loop = NULL; +user_context_t user_context = { 0, }; + +void testCloseCallback(int error, void *userData); +void testTransmitCallback(unsigned char *buffer, unsigned int length, int error, void *userData); +void testOpenChannelCallback(Channel *channel, int error, void *userData); +void testGetATRCallback(unsigned char *atr, unsigned int length, int error, void *userData); +void testCloseSessionCallback(int error, void *userData); +void testOpenSessionCallback(SessionHelper *session, int error, void *userData); +void testConnectedCallback(SEServiceHelper *service, void *context); + +class TestEventHandler : public SEServiceListener +{ + void serviceConnected(SEServiceHelper *service, void *userData) + { + SCARD_BEGIN(); + testConnectedCallback(service, userData); + SCARD_END(); + } + + void eventHandler(SEServiceHelper *service, char *seName, int event, void *userData) + { + SCARD_BEGIN(); + + SCARD_DEBUG("event occured service [%p], seName[%p], event [%d]", service, seName, event); + + SCARD_END(); + } + + void errorHandler(SEServiceHelper *service, int error, void *userData) + { + SCARD_BEGIN(); + + SCARD_DEBUG("error occured service [%p], error [%d]", service, error); + + SCARD_END(); + } +}; + +TestEventHandler testEventHandler; + +void testCloseCallback(int error, void *userData) +{ + user_context_t *context = (user_context_t *)userData; + + SCARD_DEBUG("result [%d], userData [%p]", error, userData); + + context->clientService->shutdown(); +} + +void testTransmitCallback(unsigned char *buffer, unsigned int length, int error, void *userData) +{ + ByteArray response(buffer, length); + user_context_t *context = (user_context_t *)userData; + + SCARD_DEBUG("buffer [%p], length [%d], error [%d], userData [%p]", buffer, length, error, userData); + + context->clientChannel->close(testCloseCallback, userData); +} + +void testOpenChannelCallback(Channel *channel, int error, void *userData) +{ + SCARD_DEBUG("channel [%p]", channel); + + if (error == 0 && channel != NULL) + { + ByteArray response; + ByteArray data, command; + int fid = 0x00003150; + user_context_t *context = (user_context_t *)userData; + + context->clientChannel = channel; + + response = channel->getSelectResponse(); + + SCARD_DEBUG("response : %s", response.toString()); + + SCARD_DEBUG("isBasicChannel() = %s", channel->isBasicChannel() ? "Basic" : "Logical"); + SCARD_DEBUG("isClosed() = %s", channel->isClosed() ? "Closed" : "Opened"); + + data.setBuffer((unsigned char *)&fid, 2); + command = APDUHelper::generateAPDU(APDUHelper::COMMAND_SELECT_BY_ID, 0, data); + context->clientChannel->transmit(command, testTransmitCallback, userData); + } + else + { + SCARD_DEBUG_ERR("openBasicChannel failed"); + } +} + +void testGetATRCallback(unsigned char *atr, unsigned int length, int error, void *userData) +{ +// unsigned char MF[] = { 0x3F, 0x00 }; + unsigned char MF[] = { 0xA0, 0x00, 0x00, 0x00, 0x63, 0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 }; + ByteArray aid, result(atr, length); + user_context_t *context = (user_context_t *)userData; + + SCARD_DEBUG("atr[%d] : %s", result.getLength(), result.toString()); + + aid.setBuffer(MF, sizeof(MF)); + context->clientSession->openLogicalChannel(aid, testOpenChannelCallback, userData); +} + +void testCloseSessionCallback(int error, void *userData) +{ + +} + +void testOpenSessionCallback(SessionHelper *session, int error, void *userData) +{ + SCARD_DEBUG("session [%p]", session); + + if (session != NULL) + { + user_context_t *context = (user_context_t *)userData; + + context->clientSession = (Session *)session; + context->clientSession->getATR(testGetATRCallback, userData); + } + else + { + SCARD_DEBUG_ERR("openSession failed"); + } +} + +void testConnectedCallback(SEServiceHelper *service, void *userData) +{ + vector readers; + user_context_t *context = (user_context_t *)userData; + + SCARD_BEGIN(); + + if (service != NULL) + { + SCARD_DEBUG("callback called, service [%p]", service); + + context->clientService = service; + + readers = service->getReaders(); + + if (readers.size() > 0) + { + Reader *reader = NULL; + + reader = (Reader *)readers[0]; + + SCARD_DEBUG("reader [%p]", reader); + + reader->openSession(testOpenSessionCallback, userData); + } + else + { + SCARD_DEBUG_ERR("reader is empty"); + } + } + else + { + SCARD_DEBUG_ERR("service is NULL"); + } + + SCARD_END(); +} + +int main(int argv, char *args[]) +{ + SEService *service = new SEService((void *)&user_context, &testEventHandler); + + loop = g_main_new(TRUE); + g_main_loop_run(loop); + + if (service != NULL) + delete service; + + return 0; +}