From a7847848870d576cd63ec721c3aaa3529bd27607 Mon Sep 17 00:00:00 2001 From: Jihoon Jung Date: Wed, 28 Sep 2016 16:02:17 +0900 Subject: [PATCH] Smartcard structure refactoring : capi layer - remove smartcard client library layer Change-Id: Idf28232ae62c1d7f0b968448065bf9ae2b1dde5e --- CMakeLists.txt | 7 +- include/ClientChannel.h | 101 +++ include/ClientGDBus.h | 36 ++ include/Reader.h | 87 +++ include/SEService.h | 135 ++++ include/SEServiceListener.h | 42 ++ include/Session.h | 157 +++++ include/smartcard-service.h | 29 + packaging/capi-network-smartcard.spec | 3 +- src/ClientChannel.cpp | 624 ++++++++++++++++++ src/ClientGDBus.cpp | 45 ++ src/Reader.cpp | 370 +++++++++++ src/SEService.cpp | 756 ++++++++++++++++++++++ src/Session.cpp | 889 ++++++++++++++++++++++++++ 14 files changed, 3277 insertions(+), 4 deletions(-) create mode 100644 include/ClientChannel.h create mode 100644 include/ClientGDBus.h create mode 100755 include/Reader.h create mode 100644 include/SEService.h create mode 100644 include/SEServiceListener.h create mode 100644 include/Session.h create mode 100644 include/smartcard-service.h create mode 100644 src/ClientChannel.cpp create mode 100755 src/ClientGDBus.cpp create mode 100644 src/Reader.cpp create mode 100755 src/SEService.cpp create mode 100644 src/Session.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index dc1354b..f22c146 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(service "network") SET(submodule "smartcard") # for package file -SET(dependents "dlog glib-2.0 gio-2.0 capi-base-common smartcard-service smartcard-service-common capi-system-info") +SET(dependents "dlog glib-2.0 gio-2.0 capi-base-common smartcard-service-common capi-system-info") SET(pc_dependents "capi-base-common") SET(fw_name "${project_prefix}-${service}-${submodule}") @@ -29,10 +29,13 @@ INCLUDE(FindPkgConfig) pkg_check_modules(${fw_name} REQUIRED ${dependents}) FOREACH(flag ${${fw_name}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") ENDFOREACH(flag) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS} -fPIC -Wall -Werror") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") ADD_DEFINITIONS("-DTIZEN_DEBUG") @@ -43,7 +46,7 @@ ENDIF(TIZEN_SMARTCARD_SUPPORT) SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIBDIR}") -SET(SOURCES src/smartcard.c) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCES) ADD_LIBRARY(${fw_name} SHARED ${SOURCES}) diff --git a/include/ClientChannel.h b/include/ClientChannel.h new file mode 100644 index 0000000..a4e75ee --- /dev/null +++ b/include/ClientChannel.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CLIENTCHANNEL_H_ +#define CLIENTCHANNEL_H_ + +/* standard library header */ +#include + +/* 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; + void *proxy; + + ClientChannel(void *context, Session *session, int channelNum, + const ByteArray &selectResponse, void *handle); + ~ClientChannel(); + + static void channel_transmit_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + static void channel_close_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + + public: + int close(closeChannelCallback callback, void *userParam); + int transmit(const ByteArray &command, + transmitCallback callback, void *userParam); + bool selectNext(){ return false; } + + void closeSync() + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorSecurity &, ErrorIllegalParameter &); + int transmitSync(const ByteArray &command, ByteArray &result) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + void *getHandle(){ return handle; } + + friend class Session; + }; +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int channel_is_basic_channel(channel_h handle, bool* is_basic_channel); +int channel_is_closed(channel_h handle, bool* is_closed ); +int channel_get_session(channel_h handle, int *session_handle); +int channel_close_sync(channel_h handle); +int channel_transmit_sync(channel_h handle, unsigned char *command, + unsigned int cmd_len, unsigned char **response, unsigned int *resp_len); +int channel_get_select_response(channel_h handle, + unsigned char **buffer, size_t* length); +int channel_get_transmit_response(channel_h handle, + unsigned char **buffer, size_t* length); +int channel_select_next(channel_h hChannel, bool *pSuccess); +//// + +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); +unsigned int channel_get_select_response_length(channel_h handle); +void channel_destroy_instance(channel_h handle) __attribute__((deprecated)); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CLIENTCHANNEL_H_ */ diff --git a/include/ClientGDBus.h b/include/ClientGDBus.h new file mode 100644 index 0000000..c111874 --- /dev/null +++ b/include/ClientGDBus.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CLIENTGDBUS_H_ +#define CLIENTGDBUS_H_ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "GDBusHelper.h" +#include "smartcard-service-gdbus.h" + +namespace smartcard_service_api +{ + class ClientGDBus + { + }; +} /* namespace smartcard_service_api */ + +#endif /* CLIENTGDBUS_H_ */ diff --git a/include/Reader.h b/include/Reader.h new file mode 100755 index 0000000..876d0b8 --- /dev/null +++ b/include/Reader.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef READER_H_ +#define READER_H_ + +/* standard library header */ +#include +#include + +/* 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; + void *proxy; + + Reader(void *context, const char *name, void *handle); + ~Reader(); + + inline void unavailable() { present = false; } + static void reader_open_session_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + + public: + void closeSessions() + throw(ErrorIO &, ErrorIllegalState &); + + int openSession(openSessionCallback callback, void *userData); + SessionHelper *openSessionSync() + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + void *getHandle(){ return handle; } + + friend class SEService; + }; +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int reader_get_name(reader_h handle, char** reader_name); +int reader_is_secure_element_present(reader_h handle, bool* is_present); +int reader_open_session_sync(reader_h handle, int *session_handle); +int reader_close_sessions(reader_h handle); +/// + +int reader_open_session(reader_h handle, reader_open_session_cb callback, + void *userData); +se_service_h reader_get_se_service(reader_h handle); +__attribute__((deprecated)) void reader_destroy_instance(reader_h handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* READER_H_ */ diff --git a/include/SEService.h b/include/SEService.h new file mode 100644 index 0000000..e6aa87c --- /dev/null +++ b/include/SEService.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SESERVICE_H_ +#define SESERVICE_H_ + +/* standard library header */ +#include +#include + +/* 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: + unsigned int handle; + void *context; + serviceConnected handler; + SEServiceListener *listener; + + se_service_event_cb event_handler; + void *event_handler_context; + + void *proxy; + const char *version; + + SEService(); + + void addReader(unsigned int handle, const char *name); + bool parseReaderInformation(unsigned int count, const ByteArray &data); + bool parseReaderInformation(GVariant *variant); + + bool _initialize() + throw(ErrorIO &); + bool initialize(void *context, serviceConnected handler) + throw(ErrorIO &, ErrorIllegalParameter &); + bool initialize(void *context, SEServiceListener *listener) + throw(ErrorIO &, ErrorIllegalParameter &); + int _initialize_sync() + throw(ErrorIO &, ExceptionBase &); + int _initialize_sync_do_not_throw_exception(); + bool initializeSync(void *context) + throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &); + + static void reader_inserted(GObject *source_object, + guint reader_id, gchar *reader_name, + gpointer user_data); + static void reader_removed(GObject *source_object, + guint reader_id, gchar *reader_name, + gpointer user_data); + static void se_service_shutdown_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + static void se_service_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + + public: + SEService(void *user_data, serviceConnected handler) + throw(ErrorIO &, ErrorIllegalParameter &); + SEService(void *user_data, SEServiceListener *listener) + throw(ErrorIO &, ErrorIllegalParameter &); + SEService(void *user_data) + throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &); + ~SEService(); + + static SEService *createInstance(void *user_data, SEServiceListener *listener) + throw(ErrorIO &, ErrorIllegalParameter &); + static SEService *createInstance(void *user_data, serviceConnected handler) + throw(ErrorIO &, ErrorIllegalParameter &); + + void setEventHandler(se_service_event_cb cb, void *context); + void shutdown(); + void shutdownSync(); + const char *getVersion() const { return version; } + }; +} /* 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); + +se_service_h se_service_create_instance_sync(void *user_data, int* result); +int se_service_get_version(se_service_h handle, char **version_str); +int se_service_get_readers_count(se_service_h handle); +int se_service_get_readers(se_service_h handle, int **readers, int *count); + +bool se_service_is_connected(se_service_h handle); +void se_service_shutdown(se_service_h handle); + +void se_service_set_event_handler(se_service_h handle, se_service_event_cb event_handler, void *user_data); +void se_service_unset_event_handler(se_service_h handle); + +int se_service_destroy_instance(se_service_h handle); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SESERVICE_H_ */ diff --git a/include/SEServiceListener.h b/include/SEServiceListener.h new file mode 100644 index 0000000..9cfc01b --- /dev/null +++ b/include/SEServiceListener.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef 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/include/Session.h b/include/Session.h new file mode 100644 index 0000000..7d530e3 --- /dev/null +++ b/include/Session.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SESSION_H_ +#define SESSION_H_ + +/* standard library header */ +#include + +/* 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; + void *proxy; + + Session(void *context, Reader *reader, void *handle); + ~Session(); + + int openChannel(int id, const ByteArray &aid, openChannelCallback callback, void *userData); + + Channel *openChannelSync(int id, const ByteArray &aid) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openChannelSync(int id, const ByteArray &aid, unsigned char P2) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + static void session_get_atr_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + static void session_open_channel_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + static void session_close_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data); + + public: + void closeChannels() + throw(ErrorIO &, ErrorIllegalState &); + + int getATR(getATRCallback callback, void *userData); + int close(closeSessionCallback callback, void *userData); + + int openBasicChannel(const ByteArray &aid, openChannelCallback callback, void *userData); + int openBasicChannel(const unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData); + int openLogicalChannel(const ByteArray &aid, openChannelCallback callback, void *userData); + int openLogicalChannel(const unsigned char *aid, unsigned int length, openChannelCallback callback, void *userData); + + const ByteArray getATRSync() + throw(ExceptionBase &, ErrorIO &, ErrorSecurity &, + ErrorIllegalState &, ErrorIllegalParameter &); + + void closeSync() + throw(ExceptionBase &, ErrorIO &, ErrorSecurity &, + ErrorIllegalState &, ErrorIllegalParameter &); + + Channel *openBasicChannelSync(const ByteArray &aid) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openBasicChannelSync(const unsigned char *aid, unsigned int length) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openLogicalChannelSync(const ByteArray &aid) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openLogicalChannelSync(const unsigned char *aid, unsigned int length) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openBasicChannelSync(const ByteArray &aid, unsigned char P2) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openBasicChannelSync(const unsigned char *aid, unsigned int length, unsigned char P2) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openLogicalChannelSync(const ByteArray &aid, unsigned char P2) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + Channel *openLogicalChannelSync(const unsigned char *aid, unsigned int length, unsigned char P2) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &); + + size_t getChannelCount() const; + void *getHandle(){ return handle; } + + friend class Reader; + }; +} /* namespace smartcard_service_api */ +#endif /* __cplusplus */ + +/* export C API */ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +int session_get_reader(session_h handle, int* reader_handle); +int session_is_closed(session_h handle, bool* is_closed); +int session_close_channels(session_h handle); +int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length); +int session_close_sync(session_h handle); +int session_open_basic_channel_sync(session_h handle, unsigned char *aid, + unsigned int length, unsigned char P2, int* channel_handle); +int session_open_logical_channel_sync(session_h handle, unsigned char *aid, + unsigned int length, unsigned char P2, int* channel_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); +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); +size_t session_get_channel_count(session_h handle); +__attribute__((deprecated)) void session_destroy_instance(session_h handle); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SESSION_H_ */ diff --git a/include/smartcard-service.h b/include/smartcard-service.h new file mode 100644 index 0000000..354e11f --- /dev/null +++ b/include/smartcard-service.h @@ -0,0 +1,29 @@ +/* + * 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_SERVICE_H_ +#define SMARTCARD_SERVICE_H_ + +#include "smartcard-types.h" +#ifdef __cplusplus +#include "Exception.h" +#endif +#include "SEService.h" +#include "Reader.h" +#include "Session.h" +#include "ClientChannel.h" + +#endif /* SMARTCARD_SERVICE_H_ */ diff --git a/packaging/capi-network-smartcard.spec b/packaging/capi-network-smartcard.spec index 4e4c7df..2e0f2ad 100755 --- a/packaging/capi-network-smartcard.spec +++ b/packaging/capi-network-smartcard.spec @@ -1,6 +1,6 @@ Name: capi-network-smartcard Summary: A Smartcard library in Native API -Version: 0.0.7 +Version: 0.0.8 Release: 1 Group: Network & Connectivity/Smartcard License: Apache-2.0 @@ -9,7 +9,6 @@ BuildRequires: cmake BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gobject-2.0) -BuildRequires: pkgconfig(smartcard-service) BuildRequires: pkgconfig(smartcard-service-common) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(capi-system-info) diff --git a/src/ClientChannel.cpp b/src/ClientChannel.cpp new file mode 100644 index 0000000..c7e9dd4 --- /dev/null +++ b/src/ClientChannel.cpp @@ -0,0 +1,624 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ +#include +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "ClientChannel.h" +#include "ReaderHelper.h" +#include "APDUHelper.h" +#include "ClientGDBus.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + ClientChannel::ClientChannel(void *context, Session *session, + int channelNum, const ByteArray &selectResponse, void *handle) + : Channel(session) + { + this->channelNum = -1; + this->handle = NULL; + this->context = NULL; + + if (handle == NULL) + { + _ERR("ClientIPC::getInstance() failed"); + + return; + } + + this->channelNum = channelNum; + this->handle = handle; + this->selectResponse = selectResponse; + this->context = context; + + /* init default context */ + GError *error = NULL; + + proxy = smartcard_service_channel_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.SmartcardService", + "/org/tizen/SmartcardService/Channel", + NULL, &error); + if (proxy == NULL) + { + _ERR("Can not create proxy : %s", error->message); + g_error_free(error); + return; + } + } + + ClientChannel::~ClientChannel() + { + closeSync(); + } + + void ClientChannel::channel_transmit_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + CallbackParam *param = (CallbackParam *)user_data; + transmitCallback callback; + gint result; + GVariant *var_response; + GError *error = NULL; + ByteArray response; + + _INFO("MSG_REQUEST_TRANSMIT"); + + if (param == NULL) { + _ERR("null parameter!!!"); + return; + } + + callback = (transmitCallback)param->callback; + + if (smartcard_service_channel_call_transmit_finish( + SMARTCARD_SERVICE_CHANNEL(source_object), + &result, &var_response, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + GDBusHelper::convertVariantToByteArray(var_response, response); + } else { + _ERR("smartcard_service_channel_call_transmit failed, [%d]", result); + } + } else { + _ERR("smartcard_service_channel_call_transmit failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (callback != NULL) { + callback(response.getBuffer(), + response.size(), + result, param->user_param); + } + + delete param; + } + + void ClientChannel::channel_close_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + CallbackParam *param = (CallbackParam *)user_data; + ClientChannel *channel; + closeChannelCallback callback; + gint result; + GError *error = NULL; + + _INFO("MSG_REQUEST_CLOSE_CHANNEL"); + + if (param == NULL) { + _ERR("null parameter!!!"); + return; + } + + channel = (ClientChannel *)param->instance; + callback = (closeChannelCallback)param->callback; + + if (smartcard_service_channel_call_close_channel_finish( + SMARTCARD_SERVICE_CHANNEL(source_object), + &result, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + channel->channelNum = -1; + } else { + _ERR("smartcard_service_channel_call_close_channel failed, [%d]", result); + } + } else { + _ERR("smartcard_service_channel_call_close_channel failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (callback != NULL) { + callback(result, param->user_param); + } + + delete param; + } + + void ClientChannel::closeSync() + throw(ExceptionBase &, ErrorIO &, ErrorSecurity &, + ErrorIllegalState &, ErrorIllegalParameter &) + { + if (isClosed() == false) + { + if (getSession()->getReader()->isSecureElementPresent() == true) + { + gint ret; + GError *error = NULL; + + + if (proxy == NULL) { + _ERR("dbus proxy is not initialized yet"); + throw ErrorIllegalState(SCARD_ERROR_NOT_INITIALIZED); + } + + if (smartcard_service_channel_call_close_channel_sync( + (SmartcardServiceChannel *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + &ret, NULL, &error) == true) { + if (ret == SCARD_ERROR_OK) { + channelNum = -1; + } else { + _ERR("smartcard_service_channel_call_close_channel_sync failed, [%d]", ret); + THROW_ERROR(ret); + } + } else { + _ERR("smartcard_service_channel_call_close_channel_sync failed, [%s]", error->message); + g_error_free(error); + + throw ErrorIO(SCARD_ERROR_IPC_FAILED); + } + } + else + { + _INFO("unavailable channel"); + } + } + } + + int ClientChannel::close(closeChannelCallback callback, void *userParam) + { + int result = SCARD_ERROR_OK; + + if (isClosed() == false) + { + if (getSession()->getReader()->isSecureElementPresent() == true) + { + CallbackParam *param = new CallbackParam(); + + param->instance = this; + param->callback = (void *)callback; + param->user_param = userParam; + + smartcard_service_channel_call_close_channel( + (SmartcardServiceChannel *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), NULL, + &ClientChannel::channel_close_cb, param); + } + else + { + _ERR("unavailable channel"); + result = SCARD_ERROR_ILLEGAL_STATE; + } + } + + return result; + } + + int ClientChannel::transmitSync(const ByteArray &command, ByteArray &result) + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + int rv = SCARD_ERROR_OK; + + if (getSession()->getReader()->isSecureElementPresent() == true) + { + GVariant *var_command = NULL, *var_response = NULL; + GError *error = NULL; + + var_command = GDBusHelper::convertByteArrayToVariant(command); + + if (smartcard_service_channel_call_transmit_sync( + (SmartcardServiceChannel *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + var_command, &rv, &var_response, + NULL, &error) == true) { + + if (rv == SCARD_ERROR_OK) { + GDBusHelper::convertVariantToByteArray(var_response, transmitResponse); + result = transmitResponse; + } else { + _ERR("smartcard_service_session_call_transmit failed, [%d]", rv); + THROW_ERROR(rv); + } + } else { + _ERR("smartcard_service_session_call_transmit failed, [%s]", error->message); + g_error_free(error); + + throw ErrorIO(SCARD_ERROR_IPC_FAILED); + } + } + else + { + _ERR("unavailable channel"); + throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE); + } + + return rv; + } + + int ClientChannel::transmit(const ByteArray &command, transmitCallback callback, void *userParam) + { + int result; + + if (getSession()->getReader()->isSecureElementPresent() == true) + { + GVariant *var_command; + CallbackParam *param = new CallbackParam(); + + param->instance = this; + param->callback = (void *)callback; + param->user_param = userParam; + + var_command = GDBusHelper::convertByteArrayToVariant(command); + + smartcard_service_channel_call_transmit( + (SmartcardServiceChannel *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + var_command, NULL, + &ClientChannel::channel_transmit_cb, param); + + result = SCARD_ERROR_OK; + } + else + { + _ERR("unavailable channel"); + result = SCARD_ERROR_ILLEGAL_STATE; + } + + 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 \ + { \ + _ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API int channel_close_sync(channel_h handle) +{ + int result = SCARD_ERROR_OK; + + CHANNEL_EXTERN_BEGIN; + + try + { + channel->closeSync(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_transmit_sync(channel_h handle, unsigned char *command, + unsigned int cmd_len, unsigned char **response, unsigned int *resp_len) +{ + int result = SCARD_ERROR_OK; + + if (command == NULL || cmd_len == 0 || response == NULL || resp_len == NULL) + return SCARD_ERROR_UNKNOWN; + + CHANNEL_EXTERN_BEGIN; + + try + { + ByteArray temp, resp; + + temp.assign(command, cmd_len); + channel->transmitSync(temp, resp); + + if (resp.size() > 0) + { + *response = (unsigned char *)calloc(resp.size(), sizeof(unsigned char)); + *resp_len = resp.size(); + memcpy(*response, resp.getBuffer(), *resp_len); + } + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *resp_len = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *resp_len = 0; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_is_basic_channel(channel_h handle, bool* is_basic_channel) +{ + int result = SCARD_ERROR_OK; + + CHANNEL_EXTERN_BEGIN; + + try + { + *is_basic_channel = channel->isBasicChannel(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_is_closed(channel_h handle, bool* is_closed) +{ + int result = SCARD_ERROR_OK; + + CHANNEL_EXTERN_BEGIN; + + try + { + *is_closed = channel->isClosed(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_get_select_response(channel_h handle, + unsigned char **buffer, size_t *length) +{ + int result = SCARD_ERROR_OK; + + CHANNEL_EXTERN_BEGIN; + + try + { + ByteArray response = channel->getSelectResponse(); + uint8_t* get_buffer = response.getBuffer(); + + *length = response.size(); + + if (*length > 0) + { + *buffer = (unsigned char *)calloc(*length, sizeof(unsigned char)); + if(*buffer == NULL || get_buffer == NULL) + { + *length = 0; + return SCARD_ERROR_NOT_ENOUGH_RESOURCE; + } + + memcpy(*buffer, get_buffer, *length); + } + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *length = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *length = 0; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_get_transmit_response(channel_h handle, + unsigned char **buffer, size_t *length) +{ + int result = SCARD_ERROR_OK; + + CHANNEL_EXTERN_BEGIN; + + try + { + ByteArray response; + + response = channel->getTransmitResponse(); + + *length = response.size(); + + if (*length > 0) + { + *buffer = (unsigned char *)calloc(*length, sizeof(unsigned char)); + memcpy(*buffer, response.getBuffer(), *length); + } + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *length = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *length = 0; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_get_session(channel_h handle, int *session_handle) +{ + int result = SCARD_ERROR_OK; + session_h session = NULL; + + CHANNEL_EXTERN_BEGIN; + + try + { + session = channel->getSession(); + *session_handle = (long)session; + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_select_next(channel_h handle, bool *pSuccess) +{ + int result = SCARD_ERROR_OK; + + CHANNEL_EXTERN_BEGIN; + + try + { + *pSuccess = channel->selectNext(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + 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().size(); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API int channel_close(channel_h handle, channel_close_cb callback, void *userParam) +{ + int result = -1; + + CHANNEL_EXTERN_BEGIN; + result = channel->close((closeChannelCallback)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.assign(command, length); + result = channel->transmit(temp, (transmitCallback)callback, userParam); + CHANNEL_EXTERN_END; + + return result; +} + +EXTERN_API void channel_destroy_instance(channel_h handle) +{ + /* do nothing */ +} diff --git a/src/ClientGDBus.cpp b/src/ClientGDBus.cpp new file mode 100755 index 0000000..8a3bb8b --- /dev/null +++ b/src/ClientGDBus.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ +#include + +/* SLP library header */ + +/* local header */ +#include "smartcard-types.h" +#include "Debug.h" +#include "ByteArray.h" +#include "ClientGDBus.h" + +using namespace std; + +/* below functions will be called when dlopen or dlclose is called */ +void __attribute__ ((constructor)) lib_init() +{ + /* remove for deprecated-declarations build warning: glib ver > 2.36 */ +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init(); +#endif +} + +void __attribute__ ((destructor)) lib_fini() +{ +} + +namespace smartcard_service_api +{ +} /* namespace smartcard_service_api */ diff --git a/src/Reader.cpp b/src/Reader.cpp new file mode 100644 index 0000000..887d896 --- /dev/null +++ b/src/Reader.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* standard library header */ +#include +#include +#include + +/* SLP library header */ + +/* local header */ +#include "Debug.h" +#include "Reader.h" +#include "Session.h" +#include "ClientGDBus.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +namespace smartcard_service_api +{ + Reader::Reader(void *context, const char *name, void *handle) : + ReaderHelper(name), context(context), handle(handle) + { + _BEGIN(); + + if (context == NULL || handle == NULL) + { + _ERR("invalid param"); + + return; + } + + /* init default context */ + GError *error = NULL; + + proxy = smartcard_service_reader_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.SmartcardService", + "/org/tizen/SmartcardService/Reader", + NULL, &error); + if (proxy == NULL) + { + _ERR("Can not create proxy : %s", error->message); + g_error_free(error); + return; + } + + present = true; + + _END(); + } + + Reader::~Reader() + { + size_t i; + + closeSessions(); + + for (i = 0; i < sessions.size(); i++) + { + delete (Session *)sessions[i]; + } + + sessions.clear(); + } + + void Reader::closeSessions() + throw(ErrorIO &, ErrorIllegalState &) + { + size_t i; + + for (i = 0; i < sessions.size(); i++) + { + sessions[i]->closeSync(); + } + } + + SessionHelper *Reader::openSessionSync() + throw(ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + Session *session = NULL; + + if (isSecureElementPresent() == true) + { + gint result; + GError *error = NULL; + guint session_id; + + if (smartcard_service_reader_call_open_session_sync( + (SmartcardServiceReader *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + &result, &session_id, NULL, &error) == true) { + if (result == SCARD_ERROR_OK) { + /* create new instance of channel */ + session = new Session(context, this, + GUINT_TO_POINTER(session_id)); + if (session != NULL) { + sessions.push_back(session); + } else { + _ERR("Session creating instance failed"); + + THROW_ERROR(SCARD_ERROR_OUT_OF_MEMORY); + } + } else { + _ERR("smartcard_service_reader_call_open_session_sync failed, [%d]", result); + + THROW_ERROR(result); + } + } else { + _ERR("smartcard_service_reader_call_open_session_sync failed, [%s]", error->message); + g_error_free(error); + + THROW_ERROR(SCARD_ERROR_IPC_FAILED); + } + } + else + { + _ERR("unavailable reader"); + throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE); + } + + return session; + } + + void Reader::reader_open_session_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + CallbackParam *param = (CallbackParam *)user_data; + Reader *reader; + openSessionCallback callback; + Session *session = NULL; + gint result; + guint handle; + GError *error = NULL; + + _INFO("MSG_REQUEST_OPEN_SESSION"); + + if (param == NULL) { + _ERR("null parameter!!!"); + return; + } + + reader = (Reader *)param->instance; + callback = (openSessionCallback)param->callback; + + if (smartcard_service_reader_call_open_session_finish( + SMARTCARD_SERVICE_READER(source_object), + &result, &handle, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + /* create new instance of channel */ + session = new Session(reader->context, reader, + GUINT_TO_POINTER(handle)); + if (session != NULL) { + reader->sessions.push_back(session); + } else { + _ERR("Session creating instance failed"); + + result = SCARD_ERROR_OUT_OF_MEMORY; + } + } else { + _ERR("smartcard_service_reader_call_open_session failed, [%d]", result); + } + } else { + _ERR("smartcard_service_reader_call_open_session failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (callback != NULL) { + callback(session, result, param->user_param); + } + + delete param; + } + int Reader::openSession(openSessionCallback callback, void *userData) + { + int result; + + _BEGIN(); + + if (isSecureElementPresent() == true) + { + CallbackParam *param = new CallbackParam(); + + param->instance = this; + param->callback = (void *)callback; + param->user_param = userData; + + smartcard_service_reader_call_open_session( + (SmartcardServiceReader *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + NULL, &Reader::reader_open_session_cb, param); + + result = SCARD_ERROR_OK; + } + else + { + _ERR("unavailable reader"); + result = SCARD_ERROR_ILLEGAL_STATE; + } + + _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 \ + { \ + _ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API int reader_get_name(reader_h handle, char** reader_name) +{ + int result = SCARD_ERROR_OK; + + READER_EXTERN_BEGIN; + + try + { + *reader_name = g_strdup(reader->getName()); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + READER_EXTERN_END; + + return result; +} + +EXTERN_API int reader_is_secure_element_present(reader_h handle, bool* is_present) +{ + int result = SCARD_ERROR_OK; + + READER_EXTERN_BEGIN; + + try + { + *is_present = reader->isSecureElementPresent(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + READER_EXTERN_END; + + return result; +} + +EXTERN_API int reader_open_session_sync(reader_h handle, int *session_handle) +{ + session_h session; + int result = SCARD_ERROR_OK; + + READER_EXTERN_BEGIN; + + try + { + session = (session_h)reader->openSessionSync(); + *session_handle = (long)session; + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *session_handle = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *session_handle = 0; + } + + READER_EXTERN_END; + + return result; +} + +EXTERN_API int reader_close_sessions(reader_h handle) +{ + int result = SCARD_ERROR_OK; + + READER_EXTERN_BEGIN; + + try + { + reader->closeSessions(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + READER_EXTERN_END; + + return result; +} + + +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 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_destroy_instance(reader_h handle) +{ +} diff --git a/src/SEService.cpp b/src/SEService.cpp new file mode 100755 index 0000000..d810f44 --- /dev/null +++ b/src/SEService.cpp @@ -0,0 +1,756 @@ +/* + * 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 + +/* local header */ +#include "Debug.h" +#include "SEService.h" +#include "ClientChannel.h" +#include "Reader.h" +#include "ClientGDBus.h" + +#ifndef EXTERN_API +#define EXTERN_API __attribute__((visibility("default"))) +#endif + +#define SHUTDOWN_DELAY 500000 /* us */ +#define VERSION "3.2" + +namespace smartcard_service_api +{ + SEService::SEService() : SEServiceHelper(), + handle(-1), context(NULL), handler(NULL), listener(NULL), + version(VERSION) + { + proxy = NULL; + } + + SEService::SEService(void *user_data, serviceConnected handler) + throw(ErrorIO &, ErrorIllegalParameter &) : + SEServiceHelper(), handle(-1), + listener(NULL), version(VERSION) + { + initialize(user_data, handler); + } + + SEService::SEService(void *user_data, SEServiceListener *listener) + throw(ErrorIO &, ErrorIllegalParameter &) : + SEServiceHelper(), handle(-1), + handler(NULL), version(VERSION) + { + initialize(user_data, listener); + } + + SEService::SEService(void *user_data) + throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &) : + SEServiceHelper(), handle(-1), + handler(NULL), version(VERSION) + { + initializeSync(user_data); + } + + SEService::~SEService() + { + try + { + size_t i; + + shutdownSync(); + + for (i = 0; i < readers.size(); i++) + { + delete (Reader *)readers[i]; + } + + readers.clear(); + } + catch (ExceptionBase &e) + { + _ERR("EXCEPTION : %s", e.what()); + } + catch (...) + { + _ERR("EXCEPTION!!!"); + } + } + + SEService *SEService::createInstance(void *user_data, + SEServiceListener *listener) + throw(ErrorIO &, ErrorIllegalParameter &) + { + return new SEService(user_data, listener); + } + + SEService *SEService::createInstance(void *user_data, + serviceConnected handler) + throw(ErrorIO &, ErrorIllegalParameter &) + { + return new SEService(user_data, handler); + } + + void SEService::reader_inserted(GObject *source_object, + guint reader_id, gchar *reader_name, gpointer user_data) + { + Reader *reader = NULL; + SEService *service = (SEService *)user_data; + + _INFO("[MSG_NOTIFY_SE_INSERTED]"); + + /* add readers */ + reader = new Reader(service->context, + reader_name, GUINT_TO_POINTER(reader_id)); + if (reader != NULL) + { + service->readers.push_back(reader); + } + else + { + _ERR("alloc failed"); + } + + if (service->listener != NULL) + { + service->listener->eventHandler(service, + reader_name, 1, service->context); + } + else if (service->event_handler != NULL) + { + service->event_handler(reader_id, 1, service->context); + } + else + { + _DBG("listener is null"); + } + } + + void SEService::reader_removed(GObject *source_object, + guint reader_id, gchar *reader_name, gpointer user_data) + { + SEService *service = (SEService *)user_data; + size_t i; + + _INFO("[MSG_NOTIFY_SE_REMOVED]"); + + for (i = 0; i < service->readers.size(); i++) + { + if (((Reader *)service->readers[i])->handle == + GUINT_TO_POINTER(reader_id)) + { + ((Reader *)service->readers[i])->unavailable(); + break; + } + } + + if (service->listener != NULL) + { + service->listener->eventHandler(service, + reader_name, 2, service->context); + } + else if (service->event_handler != NULL) + { + service->event_handler(reader_id, 2, service->context); + } + else + { + _DBG("listener is null"); + } + } + + void SEService::se_service_shutdown_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + SEService *service = (SEService *)user_data; + gint result; + GError *error = NULL; + + if (smartcard_service_se_service_call_shutdown_finish( + SMARTCARD_SERVICE_SE_SERVICE(source_object), + &result, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + service->connected = false; + } else { + _ERR("smartcard_service_se_service_call_shutdown failed, [%d]", result); + } + } else { + _ERR("smartcard_service_se_service_call_shutdown failed, [%s]", error->message); + g_error_free(error); + } + } + + void SEService::se_service_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + SEService *service = (SEService *)user_data; + gint result; + guint handle; + GVariant *readers = NULL; + GError *error = NULL; + + if (service == NULL) { + _ERR("null parameter!!!"); + return; + } + + if (smartcard_service_se_service_call_se_service_finish( + SMARTCARD_SERVICE_SE_SERVICE(source_object), + &result, &handle, &readers, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + service->connected = true; + service->handle = handle; + service->parseReaderInformation(readers); + } + } else { + _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (service->handler != NULL) { + service->handler(service, service->context); + } else if (service->listener != NULL) { + if (result == SCARD_ERROR_OK) { + service->listener->serviceConnected(service, service->context); + } else { + service->listener->errorHandler(service, result, service->context); + } + } + } + + void SEService::shutdown() + { + shutdownSync(); + } + + void SEService::shutdownSync() + { + if (connected == true) + { + uint32_t i; + + for (i = 0; i < readers.size(); i++) + { + readers[i]->closeSessions(); + } + + gint result; + GError *error = NULL; + + if (smartcard_service_se_service_call_shutdown_sync( + (SmartcardServiceSeService *)proxy, + handle, + &result, + NULL, + &error) == false) { + _ERR("smartcard_service_se_service_call_shutdown_sync failed, [%s]", error->message); + + g_error_free(error); + } + + /* wait at least 500ms */ + usleep(SHUTDOWN_DELAY); + + connected = false; + } + } + + bool SEService::_initialize() throw(ErrorIO &) + { + bool result = false; + + _BEGIN(); + + /* init default context */ + GError *error = NULL; + + proxy = smartcard_service_se_service_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.SmartcardService", + "/org/tizen/SmartcardService/SeService", + NULL, &error); + if (proxy == NULL) + { + _ERR("Can not create proxy : %s", error->message); + g_error_free(error); + return false; + } + + g_signal_connect(proxy, "reader-inserted", + G_CALLBACK(&SEService::reader_inserted), this); + + g_signal_connect(proxy, "reader-removed", + G_CALLBACK(&SEService::reader_removed), this); + + /* request reader */ + smartcard_service_se_service_call_se_service( + (SmartcardServiceSeService *)proxy, + NULL, + &SEService::se_service_cb, + this); + + _END(); + + return result; + } + + int SEService::_initialize_sync_do_not_throw_exception() + { + gint result; + guint handle; + GError *error = NULL; + GVariant *readers = NULL; + SEService *service = (SEService *)this; + + _BEGIN(); + + /* init default context */ + + proxy = smartcard_service_se_service_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.SmartcardService", + "/org/tizen/SmartcardService/SeService", + NULL, &error); + if (proxy == NULL) + { + _ERR("Can not create proxy : %s", error->message); + g_error_free(error); + return false; + } + + g_signal_connect(proxy, "reader-inserted", + G_CALLBACK(&SEService::reader_inserted), this); + + g_signal_connect(proxy, "reader-removed", + G_CALLBACK(&SEService::reader_removed), this); + + /* request reader */ + if(smartcard_service_se_service_call_se_service_sync( + (SmartcardServiceSeService *)proxy, &result, &handle, &readers, NULL, &error) == true) + { + if (result == SCARD_ERROR_OK) + { + service->connected = true; + service->handle = handle; + service->parseReaderInformation(readers); + } + else + { + _ERR("Initialize error : %d", result); + } + } + + if (service->handler != NULL) { + service->handler(service, service->context); + } else if (service->listener != NULL) { + if (result == SCARD_ERROR_OK) { + service->listener->serviceConnected(service, service->context); + } else { + service->listener->errorHandler(service, result, service->context); + } + } + + _END(); + + return result; + } + + int SEService::_initialize_sync() throw(ErrorIO &, ExceptionBase &) + { + gint result; + guint handle; + GError *error = NULL; + GVariant *readers = NULL; + SEService *service = (SEService *)this; + + _BEGIN(); + + /* init default context */ + + proxy = smartcard_service_se_service_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.SmartcardService", + "/org/tizen/SmartcardService/SeService", + NULL, &error); + if (proxy == NULL) + { + _ERR("Can not create proxy : %s", error->message); + g_error_free(error); + return false; + } + + g_signal_connect(proxy, "reader-inserted", + G_CALLBACK(&SEService::reader_inserted), this); + + g_signal_connect(proxy, "reader-removed", + G_CALLBACK(&SEService::reader_removed), this); + + /* request reader */ + if(smartcard_service_se_service_call_se_service_sync( + (SmartcardServiceSeService *)proxy, &result, &handle, &readers, NULL, &error) == true) + { + if (result == SCARD_ERROR_OK) + { + service->connected = true; + service->handle = handle; + service->parseReaderInformation(readers); + } + else + { + throw ExceptionBase(result); + } + } + else + { + _ERR("smartcard_service_se_service_call_se_service failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + _END(); + + return result; + } + + bool SEService::initialize(void *context, serviceConnected handler) + throw(ErrorIO &, ErrorIllegalParameter &) + { + if (context == NULL) + { + throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM); + } + + this->context = context; + this->handler = handler; + + return _initialize(); + } + + bool SEService::initialize(void *context, SEServiceListener *listener) + throw(ErrorIO &, ErrorIllegalParameter &) + { + if (context == NULL) + { + throw ErrorIllegalParameter(SCARD_ERROR_ILLEGAL_PARAM); + } + + this->context = context; + this->listener = listener; + + return _initialize_sync_do_not_throw_exception(); + } + + bool SEService::initializeSync(void *context) + throw(ErrorIO &, ErrorIllegalParameter &, ExceptionBase &) + { + this->context = context; + + _initialize_sync(); + return true; + } + + void SEService::setEventHandler(se_service_event_cb cb, void *context) + { + this->event_handler = cb; + this->event_handler_context = context; + } + + bool SEService::parseReaderInformation(GVariant *variant) + { + Reader *reader = NULL; + + GVariantIter *iter; + guint handle; + gchar *name; + + g_variant_get(variant, "a(us)", &iter); + + while (g_variant_iter_loop(iter, "(us)", &handle, &name) == true) + { + SECURE_LOGD("Reader : name [%s], handle [%08x]", name, handle); + + /* add readers */ + reader = new Reader((void *)this->handle, name, GUINT_TO_POINTER(handle)); + if (reader == NULL) + { + _ERR("alloc failed"); + continue; + } + + readers.push_back(reader); + } + + g_variant_iter_free(iter); + + return true; + } + + bool SEService::parseReaderInformation(unsigned int count, + const ByteArray &data) + { + size_t i; + unsigned int offset = 0; + unsigned int len = 0; + void *handle = NULL; + Reader *reader = NULL; + char name[100]; + const uint8_t *buffer = NULL; + + + for (i = 0; i < count && offset < data.size(); i++) + { + memset(name, 0, sizeof(name)); + + buffer = data.getBuffer(offset); + if(buffer == NULL) + continue; + + memcpy(&len, buffer, sizeof(len)); + offset += sizeof(len); + + buffer = data.getBuffer(offset); + if(buffer == NULL) + return false; + + memcpy(name, buffer, len); + offset += len; + + buffer = data.getBuffer(offset); + if(buffer == NULL) + return false; + + memcpy(&handle, buffer, sizeof(handle)); + offset += sizeof(handle); + + SECURE_LOGD("Reader [%d] : name [%s], handle [%p]", i, name, handle); + + /* add readers */ + reader = new Reader(context, name, handle); + if (reader == NULL) + { + _ERR("alloc failed"); + continue; + } + + readers.push_back(reader); + } + + return true; + } +} /* 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 \ + { \ + _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; + + try + { + service = new SEService(user_data, (serviceConnected)callback); + } + catch (...) + { + service = NULL; + } + + 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; + + try + { + service = new SEService(user_data, (serviceConnected)connected); + } + catch (...) + { + service = NULL; + } + + return (se_service_h)service; +} + +EXTERN_API se_service_h se_service_create_instance_sync(void *user_data, + int *result) +{ + SEService *service; + + try + { + service = new SEService(user_data); + } + catch (ExceptionBase &e) + { + *result = e.getErrorCode(); + service = NULL; + } + catch (...) + { + *result = SCARD_ERROR_UNKNOWN; + service = NULL; + } + + return (se_service_h)service; +} + +EXTERN_API int se_service_get_version(se_service_h handle, char **version_str) +{ + int ret = 0; + + SE_SERVICE_EXTERN_BEGIN; + + *version_str = g_strdup(service->getVersion()); + + SE_SERVICE_EXTERN_END; + + return ret; +} + +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 int se_service_get_readers(se_service_h handle, int **readers, int *count) +{ + int result = 0; + + SE_SERVICE_EXTERN_BEGIN; + + vector temp_readers; + size_t i; + int temp = 0; + + temp_readers = service->getReaders(); + if(temp_readers.size() > 0) + { + *readers = (int *)calloc(temp_readers.size(), sizeof(int)); + + if(*readers == NULL) + { + *count = 0; + return SCARD_ERROR_NOT_ENOUGH_RESOURCE; + } + + for (i = 0; i < temp_readers.size(); i++) + { + if (temp_readers[i]->isSecureElementPresent()) + { + (*readers)[i] = (long)temp_readers[i]; + temp++; + } + } + *count = temp; + } + else + { + *count = 0; + } + + 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->shutdownSync(); + + SE_SERVICE_EXTERN_END; +} + +EXTERN_API void se_service_set_event_handler(se_service_h handle, + se_service_event_cb event_handler, void *user_data) +{ + SE_SERVICE_EXTERN_BEGIN; + + service->setEventHandler(event_handler, user_data); + + SE_SERVICE_EXTERN_END; +} + +EXTERN_API void se_service_unset_event_handler(se_service_h handle) +{ + SE_SERVICE_EXTERN_BEGIN; + + service->setEventHandler(NULL, NULL); + + SE_SERVICE_EXTERN_END; +} + +EXTERN_API int se_service_destroy_instance(se_service_h handle) +{ + int result = 0; + + SE_SERVICE_EXTERN_BEGIN; + + delete service; + + SE_SERVICE_EXTERN_END; + + return result; +} diff --git a/src/Session.cpp b/src/Session.cpp new file mode 100644 index 0000000..412bc6a --- /dev/null +++ b/src/Session.cpp @@ -0,0 +1,889 @@ +/* + * 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 "Session.h" +#include "Reader.h" +#include "ClientChannel.h" +#include "ClientGDBus.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) + { + _ERR("handle is null"); + + return; + } + + this->context = context; + this->handle = handle; + + /* init default context */ + GError *error = NULL; + + proxy = smartcard_service_session_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.tizen.SmartcardService", + "/org/tizen/SmartcardService/Session", + NULL, &error); + if (proxy == NULL) + { + _ERR("Can not create proxy : %s", error->message); + g_error_free(error); + return; + } + + closed = false; + } + + Session::~Session() + { + size_t i; + + closeSync(); + + for (i = 0; i < channels.size(); i++) + { + delete (ClientChannel *)channels[i]; + } + + channels.clear(); + } + + void Session::closeChannels() throw (ErrorIO &, ErrorIllegalState &) + { + size_t i; + + for (i = 0; i < channels.size(); i++) + { + channels[i]->closeSync(); + } + } + + void Session::session_get_atr_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + CallbackParam *param = (CallbackParam *)user_data; + Session *session; + getATRCallback callback; + gint result; + GVariant *var_atr; + GError *error = NULL; + ByteArray atr; + + _INFO("MSG_REQUEST_GET_ATR"); + + if (param == NULL) { + _ERR("null parameter!!!"); + return; + } + + session = (Session *)param->instance; + callback = (getATRCallback)param->callback; + + if (smartcard_service_session_call_get_atr_finish( + SMARTCARD_SERVICE_SESSION(source_object), + &result, &var_atr, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + GDBusHelper::convertVariantToByteArray(var_atr, atr); + + session->atr = atr; + } else { + _ERR("smartcard_service_session_call_get_atr failed, [%d]", result); + } + } else { + _ERR("smartcard_service_session_call_get_atr failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (callback != NULL) { + callback(atr.getBuffer(), + atr.size(), result, param->user_param); + } + + delete param; + } + + void Session::session_open_channel_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + CallbackParam *param = (CallbackParam *)user_data; + Session *session; + openChannelCallback callback; + gint result = SCARD_ERROR_UNKNOWN; + gint channel_number; + guint channel_id; + GVariant *var_response; + GError *error = NULL; + Channel *channel = NULL; + + _INFO("MSG_REQUEST_OPEN_CHANNEL"); + + if (param == NULL) { + _ERR("null parameter!!!"); + return; + } + + session = (Session *)param->instance; + callback = (openChannelCallback)param->callback; + + if (smartcard_service_session_call_open_channel_finish( + SMARTCARD_SERVICE_SESSION(source_object), + &result, &channel_id, &channel_number, &var_response, + res, &error) == true) { + if (result == SCARD_ERROR_OK) { + ByteArray response; + + GDBusHelper::convertVariantToByteArray( + var_response, response); + + /* create new instance of channel */ + channel = new ClientChannel(session->context, + session, channel_id, + response, (void *)channel_id); + if (channel != NULL) { + session->channels.push_back(channel); + } else { + _ERR("alloc failed"); + + result = SCARD_ERROR_OUT_OF_MEMORY; + } + } else { + _ERR("smartcard_service_session_call_open_channel failed, [%d]", result); + } + } else { + _ERR("smartcard_service_session_call_open_channel failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (callback != NULL) { + callback(channel, result, param->user_param); + } + + delete param; + } + + void Session::session_close_cb(GObject *source_object, + GAsyncResult *res, gpointer user_data) + { + CallbackParam *param = (CallbackParam *)user_data; + Session *session; + closeSessionCallback callback; + gint result; + GError *error = NULL; + + _INFO("MSG_REQUEST_CLOSE_SESSION"); + + if (param == NULL) { + _ERR("null parameter!!!"); + return; + } + + session = (Session *)param->instance; + callback = (closeSessionCallback)param->callback; + + if (smartcard_service_session_call_close_session_finish( + SMARTCARD_SERVICE_SESSION(source_object), + &result, res, &error) == true) { + if (result == SCARD_ERROR_OK) { + session->closed = true; + } else { + _ERR("smartcard_service_session_call_close_session failed, [%d]", result); + } + } else { + _ERR("smartcard_service_session_call_close_session failed, [%s]", error->message); + g_error_free(error); + + result = SCARD_ERROR_IPC_FAILED; + } + + if (callback != NULL) { + callback(result, param->user_param); + } + + delete param; + } + + const ByteArray Session::getATRSync() + throw (ExceptionBase &, ErrorIO &, ErrorSecurity &, + ErrorIllegalState &, ErrorIllegalParameter &) + { + ByteArray result; + + if (getReader()->isSecureElementPresent() == true) + { + if (atr.isEmpty() == true) + { + gint ret; + GVariant *var_atr = NULL; + GError *error = NULL; + + if (smartcard_service_session_call_get_atr_sync( + (SmartcardServiceSession *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + &ret, &var_atr, NULL, &error) == true) { + if (ret == SCARD_ERROR_OK) { + GDBusHelper::convertVariantToByteArray(var_atr, result); + + atr = result; + } else { + _ERR("smartcard_service_session_call_get_atr_sync failed, [%d]", ret); + + THROW_ERROR(ret); + } + } else { + _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message); + g_error_free(error); + + THROW_ERROR(SCARD_ERROR_IPC_FAILED); + } + } + + result = atr; + } + else + { + _ERR("unavailable session"); + throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE); + } + + return result; + } + + int Session::getATR(getATRCallback callback, void *userData) + { + int result; + + if (getReader()->isSecureElementPresent() == true) + { + if (atr.isEmpty() == true) + { + CallbackParam *param = new CallbackParam(); + + param->instance = this; + param->callback = (void *)callback; + param->user_param = userData; + + smartcard_service_session_call_get_atr( + (SmartcardServiceSession *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), NULL, + &Session::session_get_atr_cb, param); + + result = SCARD_ERROR_OK; + } + else + { + result = SCARD_ERROR_OK; + + /* TODO : invoke callback directly */ + callback(atr.getBuffer(), + atr.size(), 0, userData); + } + } + else + { + _ERR("unavailable session"); + result = SCARD_ERROR_ILLEGAL_STATE; + } + + return result; + } + + void Session::closeSync() + throw (ExceptionBase &, ErrorIO &, ErrorSecurity &, + ErrorIllegalState &, ErrorIllegalParameter &) + { + if (isClosed() == false) + { + closed = true; + closeChannels(); + + gint ret; + GError *error = NULL; + + if (smartcard_service_session_call_close_session_sync( + (SmartcardServiceSession *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + &ret, NULL, &error) == true) { + if (ret == SCARD_ERROR_OK) { + closed = true; + } else { + _ERR("smartcard_service_session_call_close_session_sync failed, [%d]", ret); + + THROW_ERROR(ret); + } + } else { + _ERR("smartcard_service_session_call_get_atr_sync failed, [%s]", error->message); + g_error_free(error); + + THROW_ERROR(SCARD_ERROR_IPC_FAILED); + } + } + } + + int Session::close(closeSessionCallback callback, void *userData) + { + int result = SCARD_ERROR_OK; + + if (isClosed() == false) + { + closed = true; + closeChannels(); + + CallbackParam *param = new CallbackParam(); + + param->instance = this; + param->callback = (void *)callback; + param->user_param = userData; + + smartcard_service_session_call_close_session( + (SmartcardServiceSession *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), NULL, + &Session::session_close_cb, param); + } + + return result; + } + + size_t Session::getChannelCount() const + { + size_t count = 0; + + if (getReader()->isSecureElementPresent() == true) + { + count = channels.size(); + } + else + { + _ERR("unavailable session"); + throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE); + } + + return count; + } + Channel *Session::openChannelSync(int id, const ByteArray &aid) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + return openChannelSync(id, aid, 0x00); + } + + Channel *Session::openChannelSync(int id, const ByteArray &aid, unsigned char P2) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + Channel *channel = NULL; + + if (getReader()->isSecureElementPresent() == true) + { + gint ret; + GVariant *var_aid = NULL, *var_response = NULL; + guint channel_id; + gint channel_number; + GError *error = NULL; + + var_aid = GDBusHelper::convertByteArrayToVariant(aid); + + if (smartcard_service_session_call_open_channel_sync( + (SmartcardServiceSession *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + (guint)id, var_aid, (guint8)P2, &ret, &channel_id, &channel_number, + &var_response, NULL, &error) == true) { + if (ret == SCARD_ERROR_OK && channel_id != 0) { + ByteArray response; + + GDBusHelper::convertVariantToByteArray( + var_response, response); + + /* create new instance of channel */ + channel = new ClientChannel(context, + this, channel_number, + response, (void *)channel_id); + if (channel != NULL) + { + channels.push_back(channel); + } + else + { + _ERR("alloc failed"); + + THROW_ERROR(SCARD_ERROR_OUT_OF_MEMORY); + } + } else { + _ERR("smartcard_service_session_call_open_channel_sync failed, [%d]", ret); + + THROW_ERROR(ret); + } + } else { + _ERR("smartcard_service_session_call_open_channel_sync failed, [%s]", error->message); + g_error_free(error); + + THROW_ERROR(SCARD_ERROR_IPC_FAILED); + } + } + else + { + _ERR("unavailable session"); + + throw ErrorIllegalState(SCARD_ERROR_UNAVAILABLE); + } + + return (Channel *)channel; + } + + int Session::openChannel(int id, const ByteArray &aid, openChannelCallback callback, void *userData) + { + int result; + + if (getReader()->isSecureElementPresent() == true) + { + GVariant *var_aid; + + CallbackParam *param = new CallbackParam(); + + param->instance = this; + param->callback = (void *)callback; + param->user_param = userData; + + var_aid = GDBusHelper::convertByteArrayToVariant(aid); + + smartcard_service_session_call_open_channel( + (SmartcardServiceSession *)proxy, + GPOINTER_TO_UINT(context), + GPOINTER_TO_UINT(handle), + (guint)id, var_aid, 0, NULL, + &Session::session_open_channel_cb, param); + + result = SCARD_ERROR_OK; + } + else + { + _ERR("unavailable session"); + result = SCARD_ERROR_ILLEGAL_STATE; + } + + return result; + } + + Channel *Session::openBasicChannelSync(const ByteArray &aid) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + return openChannelSync(0, aid, 0x00); + } + + Channel *Session::openBasicChannelSync(const ByteArray &aid, unsigned char P2) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + return openChannelSync(0, aid, P2); + } + + Channel *Session::openBasicChannelSync(const unsigned char *aid, unsigned int length) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + ByteArray temp(aid, length); + + return openBasicChannelSync(temp, 0x00); + } + + Channel *Session::openBasicChannelSync(const unsigned char *aid, unsigned int length, unsigned char P2) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + ByteArray temp(aid, length); + + return openBasicChannelSync(temp, P2); + } + + int Session::openBasicChannel(const ByteArray &aid, openChannelCallback callback, void *userData) + { + return openChannel(0, aid, callback, userData); + } + + int Session::openBasicChannel(const unsigned char *aid, unsigned int length, + openChannelCallback callback, void *userData) + { + ByteArray temp(aid, length); + + return openBasicChannel(temp, callback, userData); + } + + Channel *Session::openLogicalChannelSync(const ByteArray &aid) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + return openChannelSync(1, aid, 0x00); + } + + Channel *Session::openLogicalChannelSync(const ByteArray &aid, unsigned char P2) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + return openChannelSync(1, aid, P2); + } + + Channel *Session::openLogicalChannelSync(const unsigned char *aid, unsigned int length) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + ByteArray temp(aid, length); + + return openLogicalChannelSync(temp, 0x00); + } + + Channel *Session::openLogicalChannelSync(const unsigned char *aid, unsigned int length, unsigned char P2) + throw (ExceptionBase &, ErrorIO &, ErrorIllegalState &, + ErrorIllegalParameter &, ErrorSecurity &) + { + ByteArray temp(aid, length); + + return openLogicalChannelSync(temp, P2); + } + + int Session::openLogicalChannel(const ByteArray &aid, openChannelCallback callback, void *userData) + { + return openChannel(1, aid, callback, userData); + } + + int Session::openLogicalChannel(const unsigned char *aid, unsigned int length, + openChannelCallback callback, void *userData) + { + ByteArray temp(aid, length); + + return openLogicalChannel(temp, callback, userData); + } +} /* namespace smartcard_service_api */ + +/* export C API */ +#define SESSION_EXTERN_BEGIN \ + if (handle != NULL) \ + { \ + Session *session = (Session *)handle; + +#define SESSION_EXTERN_END \ + } \ + else \ + { \ + _ERR("Invalid param"); \ + } + +using namespace smartcard_service_api; + +EXTERN_API int session_get_reader(session_h handle, int* reader_handle) +{ + int result = SCARD_ERROR_OK; + reader_h reader = NULL; + + SESSION_EXTERN_BEGIN; + + try + { + reader = session->getReader(); + *reader_handle = (long)reader; + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *reader_handle = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *reader_handle = 0; + } + + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_is_closed(session_h handle, bool* is_closed) +{ + int result = SCARD_ERROR_OK; + + SESSION_EXTERN_BEGIN; + + try + { + *is_closed = session->isClosed(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_close_channels(session_h handle) +{ + int result = SCARD_ERROR_OK; + + SESSION_EXTERN_BEGIN; + + try + { + session->closeChannels(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_get_atr_sync(session_h handle, unsigned char **buffer, unsigned int *length) +{ + ByteArray temp; + int result = SCARD_ERROR_OK; + + SESSION_EXTERN_BEGIN; + + try + { + temp = session->getATRSync(); + + if (temp.size() > 0) + { + *buffer = (unsigned char *)calloc(temp.size(), sizeof(char)); + *length = temp.size(); + + memcpy(*buffer, temp.getBuffer(), *length); + } + } + catch (ErrorIllegalState &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + + if(result == SCARD_ERROR_OPERATION_NOT_SUPPORTED) + { + *length = 0; + result = SCARD_ERROR_OK; + } + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *length = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *length = 0; + } + + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_close_sync(session_h handle) +{ + int result = SCARD_ERROR_OK; + + SESSION_EXTERN_BEGIN; + + try + { + session->closeSync(); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + } + + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_open_basic_channel_sync(session_h handle, unsigned char *aid, + unsigned int length, unsigned char P2, int* channel_handle) +{ + int result = SCARD_ERROR_OK; + + SESSION_EXTERN_BEGIN; + + try + { + *channel_handle = (long)session->openBasicChannelSync(aid, length, P2); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *channel_handle = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *channel_handle = 0; + } + + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API int session_open_logical_channel_sync(session_h handle, unsigned char *aid, + unsigned int length, unsigned char P2, int* channel_handle) +{ + int result = SCARD_ERROR_OK; + + SESSION_EXTERN_BEGIN; + + try + { + *channel_handle = (long)session->openLogicalChannelSync(aid, length, P2); + } + catch (ExceptionBase &e) + { + _ERR("Error occur : %s\n", e.what()); + result = e.getErrorCode(); + *channel_handle = 0; + } + catch (...) + { + _ERR("Error occur : unknown error\n"); + result = SCARD_ERROR_UNKNOWN; + *channel_handle = 0; + } + + SESSION_EXTERN_END; + + return result; +} + +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 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 size_t session_get_channel_count(session_h handle) +{ + size_t result = 0; + + SESSION_EXTERN_BEGIN; + result = session->getChannelCount(); + SESSION_EXTERN_END; + + return result; +} + +EXTERN_API void session_destroy_instance(session_h handle) +{ +} + -- 2.34.1