From: Andrzej Popowski Date: Wed, 7 Jan 2015 10:41:37 +0000 (+0100) Subject: [SecureElement] - Session and Channel interfaces created. X-Git-Tag: submit/tizen_tv/20150603.064601~1^2~589 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e08ca89e60fa371aa92cf1cd44b10584c7115d9c;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [SecureElement] - Session and Channel interfaces created. Change-Id: I43c5c2a07b758000c4cb7893d9830da8c858b278 Signed-off-by: Andrzej Popowski --- diff --git a/src/secureelement/secureelement.gyp b/src/secureelement/secureelement.gyp index 6fd0308d..64433572 100644 --- a/src/secureelement/secureelement.gyp +++ b/src/secureelement/secureelement.gyp @@ -15,7 +15,11 @@ 'secureelement_seservice.cc', 'secureelement_seservice.h', 'secureelement_reader.cc', - 'secureelement_reader.h' + 'secureelement_reader.h', + 'secureelement_session.cc', + 'secureelement_session.h', + 'secureelement_channel.cc', + 'secureelement_channel.h', ], 'includes': [ '../common/pkg-config.gypi', diff --git a/src/secureelement/secureelement_api.js b/src/secureelement/secureelement_api.js index 7e5f7b29..9935a3e7 100644 --- a/src/secureelement/secureelement_api.js +++ b/src/secureelement/secureelement_api.js @@ -90,61 +90,128 @@ Reader.prototype.closeSessions = function() { native_.call('SEReader_closeSessions', callArgs); }; -//////////////////Session///////////////// +//////////////////Channel///////////////// -function Session() { - var handle = null; +function Channel( channel_handle, is_basic_channel) { Object.defineProperties(this, { - isClosed: {value: false, writable: false, enumerable: true} + _handle: { enumerable: false, configurable: false, set: function() {}, get: function() { return channel_handle }}, + isBasicChannel: { enumerable: true, configurable: false, set: function() {}, get: function() { return is_basic_channel }} }); } -Session.prototype.openBasicChannel = function() { - var args = validator_.validateArgs(arguments, [ - { name: "aid", type: types_.ARRAY, values: types_.BYTE }, - { name: "successCallback", type: types_.FUNCTION }, - { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true } - ]); +Channel.prototype.close = function() { + var callArgs = { handle: this._handle }; + native_.callSync('SEChannel_close', callArgs); }; -Session.prototype.openLogicalChannel = function() { +Channel.prototype.transmit = function() { var args = validator_.validateArgs(arguments, [ - { name: "aid", type: types_.ARRAY, values: types_.BYTE }, + { name: "command", type: types_.ARRAY, values: types_.BYTE }, { name: "successCallback", type: types_.FUNCTION }, { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true } ]); -} -Session.prototype.getATR = function() { -} + var callback = function(result) { + if ( native_.isFailure(result)) { + native_.callIfPossible( args.errorCallback, native_.getErrorObject(result)); + } else { + var result_obj = native_.getResultObject(result); + args.successCallback(result_obj.response); + } + } -Session.prototype.close = function() { + var callArgs = { + handle: this._handle, + command: args.command + }; + + native_.call('SEChannel_transmit', callArgs, callback); } -Session.prototype.closeChannels = function() { +Channel.prototype.getSelectResponse = function() { + var callArgs = { handle: this._handle }; + native_.callSync('SEChannel_getSelectResponse', callArgs); } -//////////////////Channel///////////////// +//////////////////Session///////////////// -function Channel() { - var handle = null; +function Session(session_handle) { Object.defineProperties(this, { - isBasicChannel: {value: false, writable: false, enumerable: true} + isClosed: { configurable: false, + enumerable: true, + set: function() {}, + get: function() { var callArgs = { _handle: session_handle }; return native_.callSync('SESession_isClosed', callArgs); }}, + _handle: { enumerable: false, + configurable: false, + set: function() {}, + get: function() { return session_handle }} }); } -Channel.prototype.close = function() { +Session.prototype.openBasicChannel = function() { + var args = validator_.validateArgs(arguments, [ + { name: "aid", type: types_.ARRAY, values: types_.BYTE }, + { name: "successCallback", type: types_.FUNCTION }, + { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true } + ]); + + var callback = function(result) { + if ( native_.isFailure(result)) { + native_.callIfPossible( args.errorCallback, native_.getErrorObject(result)); + } else { + var result_obj = native_.getResultObject(result); + var channel = new Channel( result_obj.handle, result_obj.isBasicChannel); + args.successCallback(channel); + } + } + + var callArgs = { + handle: this._handle, + aid: args.aid + }; + + native_.call('SESession_openBasicChannel', callArgs, callback); }; -Channel.prototype.transmit = function() { +Session.prototype.openLogicalChannel = function() { var args = validator_.validateArgs(arguments, [ - { name: "command", type: types_.ARRAY, values: types_.BYTE }, + { name: "aid", type: types_.ARRAY, values: types_.BYTE }, { name: "successCallback", type: types_.FUNCTION }, { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true } ]); + + var callback = function(result) { + if ( native_.isFailure(result)) { + native_.callIfPossible( args.errorCallback, native_.getErrorObject(result)); + } else { + var result_obj = native_.getResultObject(result); + var channel = new Channel( result_obj.handle, result_obj.isBasicChannel); + args.successCallback(channel); + } + } + + var callArgs = { + handle: this._handle, + aid: args.aid + }; + + native_.call('SESession_openLogicalChannel', callArgs, callback); } -Channel.prototype.getSelectResponse = function() { +Session.prototype.getATR = function() { + var callArgs = { handle: this._handle }; + return native_.callSync('SESession_getATR', callArgs); } +Session.prototype.close = function() { + var callArgs = { handle: this._handle }; + native_.callSync('SESession_close', callArgs); +} + +Session.prototype.closeChannels = function() { + var callArgs = { handle: this._handle }; + native_.callSync('SESession_closeChannels', callArgs); +} + + exports = new SEService(); diff --git a/src/secureelement/secureelement_channel.cc b/src/secureelement/secureelement_channel.cc new file mode 100644 index 00000000..3a662f57 --- /dev/null +++ b/src/secureelement/secureelement_channel.cc @@ -0,0 +1,46 @@ +// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "common/picojson.h" +#include "common/logger.h" +#include "secureelement_channel.h" + +using namespace smartcard_service_api; + +namespace extension { +namespace secureelement { + +void SEChannel::close() { + LoggerD("Entered"); + if (m_channel_ptr && !m_channel_ptr->isClosed()) { + m_channel_ptr->closeSync(); + } +} + + +ByteArray SEChannel::transmit(const picojson::array& v_command) { + ByteArray response; + if ( m_channel_ptr) { + uint8_t* command = new uint8_t[v_command.size()]; + for ( int i = 0; i < v_command.size(); i++) { + command[i] = (uint8_t) static_cast(v_command[i].get()); + } + ByteArray ba_command(command, v_command.size()); + delete [] command; + m_channel_ptr->transmitSync( ba_command, response); + } + return response; +} + + +ByteArray SEChannel::getSelectResponse() { + ByteArray response; + if ( m_channel_ptr) { + response = m_channel_ptr->getSelectResponse(); + } + return response; +} + +} // secureelement +} // extension diff --git a/src/secureelement/secureelement_channel.h b/src/secureelement/secureelement_channel.h new file mode 100644 index 00000000..b87e66d7 --- /dev/null +++ b/src/secureelement/secureelement_channel.h @@ -0,0 +1,28 @@ +// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SECUREELEMENT_CHANNEL_H_ +#define SECUREELEMENT_CHANNEL_H_ + +#include +#include "common/picojson.h" + +namespace extension { +namespace secureelement { + +class SEChannel { +public: + SEChannel( smartcard_service_api::ClientChannel* channel_ptr) : m_channel_ptr(channel_ptr) {}; + virtual ~SEChannel() {}; + void close(); + smartcard_service_api::ByteArray transmit(const picojson::array& v_command); + smartcard_service_api::ByteArray getSelectResponse(); +private: + smartcard_service_api::ClientChannel* m_channel_ptr; +}; + +} // secureelement +} // extension + +#endif // SECUREELEMENT_CHANNEL_H_ diff --git a/src/secureelement/secureelement_instance.cc b/src/secureelement/secureelement_instance.cc index 6281c08e..7dd9d46d 100644 --- a/src/secureelement/secureelement_instance.cc +++ b/src/secureelement/secureelement_instance.cc @@ -12,6 +12,8 @@ #include "common/task-queue.h" #include "secureelement_reader.h" +#include "secureelement_session.h" +#include "secureelement_channel.h" namespace extension { namespace secureelement { @@ -37,6 +39,7 @@ SecureElementInstance::SecureElementInstance() { REGISTER_SYNC("SEReader_isPresent", IsPresent); REGISTER_SYNC("SEReader_closeSessions", CloseSessions); REGISTER_SYNC("SESession_getATR", GetATR); + REGISTER_SYNC("SESession_isClosed", IsSessionClosed); REGISTER_SYNC("SESession_close", CloseSession); REGISTER_SYNC("SESession_closeChannels", CloseChannels); REGISTER_SYNC("SEChannel_close", CloseChannel); @@ -99,29 +102,26 @@ void SecureElementInstance::CloseSessions( ReportSuccess(out); } -void SecureElementInstance::GetATR( - const picojson::value& args, picojson::object& out) { - -} - -void SecureElementInstance::CloseSession( - const picojson::value& args, picojson::object& out) { - -} - -void SecureElementInstance::CloseChannels( - const picojson::value& args, picojson::object& out) { - +void SecureElementInstance::CloseChannel( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + ClientChannel* channel_ptr = (ClientChannel*) static_cast(args.get("handle").get()); + SEChannel seChannel(channel_ptr); + seChannel.close(); + ReportSuccess(out); } -void SecureElementInstance::CloseChannel( - const picojson::value& args, picojson::object& out) { - -} - -void SecureElementInstance::GetSelectResponse( - const picojson::value& args, picojson::object& out) { - +void SecureElementInstance::GetSelectResponse( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + ClientChannel* channel_ptr = (ClientChannel*) static_cast(args.get("handle").get()); + SEChannel seChannel(channel_ptr); + + ByteArray select_response = seChannel.getSelectResponse(); + picojson::value result = picojson::value(picojson::array()); + picojson::array& arr = result.get(); + for ( int i; i < select_response.size(); i++) { + arr.push_back(picojson::value(static_cast(select_response[i]))); + } + ReportSuccess( result, out); } void SecureElementInstance::GetReaders( @@ -162,18 +162,138 @@ void SecureElementInstance::OpenSession( std::shared_ptr(new picojson::value(picojson::object()))); } -void SecureElementInstance::OpenBasicChannel( - const picojson::value& args, picojson::object& out) { +// Session functions + +void SecureElementInstance::OpenBasicChannel( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + const double callback_id = args.get("callbackId").get(); + const picojson::array v_aid = args.get("aid").get(); + Session* session_ptr = (Session*) static_cast(args.get("handle").get()); + + auto open = [this, v_aid, session_ptr](const std::shared_ptr& response) -> void { + LoggerD("Opening basic channel"); + try { + SESession seSession(session_ptr); + picojson::value result = seSession.openBasicChannel(v_aid); + ReportSuccess(result, response->get()); + } catch (const PlatformException& e) { + ReportError(e, response->get()); + } + }; + + auto get_response = [this, callback_id](const std::shared_ptr& response) -> void { + LoggerD("Getting response"); + picojson::object& obj = response->get(); + obj.insert(std::make_pair("callbackId", callback_id)); + PostMessage(response->serialize().c_str()); + }; + + TaskQueue::GetInstance().Queue + ( open, get_response, std::shared_ptr(new picojson::value(picojson::object()))); } -void SecureElementInstance::OpenLogicalChannel( - const picojson::value& args, picojson::object& out) { +void SecureElementInstance::OpenLogicalChannel( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + const double callback_id = args.get("callbackId").get(); + const picojson::array v_aid = args.get("aid").get(); + Session* session_ptr = (Session*) static_cast(args.get("handle").get()); + + auto open = [this, v_aid, session_ptr](const std::shared_ptr& response) -> void { + LoggerD("Opening basic channel"); + try { + SESession seSession(session_ptr); + picojson::value result = seSession.openBasicChannel(v_aid); + ReportSuccess(result, response->get()); + } catch (const PlatformException& e) { + ReportError(e, response->get()); + } + }; + + auto get_response = [this, callback_id](const std::shared_ptr& response) -> void { + LoggerD("Getting response"); + picojson::object& obj = response->get(); + obj.insert(std::make_pair("callbackId", callback_id)); + PostMessage(response->serialize().c_str()); + }; + + TaskQueue::GetInstance().Queue + ( open, get_response, std::shared_ptr(new picojson::value(picojson::object()))); } -void SecureElementInstance::Transmit( - const picojson::value& args, picojson::object& out) { +void SecureElementInstance::GetATR( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + Session* session_ptr = (Session*) static_cast(args.get("handle").get()); + SESession seSession(session_ptr); + + ByteArray atr_result = seSession.getATR(); + picojson::value result = picojson::value(picojson::array()); + picojson::array& arr = result.get(); + for ( int i; i < atr_result.size(); i++) { + arr.push_back(picojson::value(static_cast(atr_result[i]))); + } + ReportSuccess( result, out); +} + + +void SecureElementInstance::IsSessionClosed( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + Session* session_ptr = (Session*) static_cast(args.get("handle").get()); + SESession seSession(session_ptr); + picojson::value result = seSession.isClosed(); + ReportSuccess( result, out); +} + + +void SecureElementInstance::CloseSession( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + Session* session_ptr = (Session*) static_cast(args.get("handle").get()); + SESession seSession(session_ptr); + seSession.close(); + ReportSuccess(out); +} + + +void SecureElementInstance::CloseChannels( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + Session* session_ptr = (Session*) static_cast(args.get("handle").get()); + SESession seSession(session_ptr); + seSession.closeChannels(); + ReportSuccess(out); +} + +void SecureElementInstance::Transmit( const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + const double callback_id = args.get("callbackId").get(); + const picojson::array v_command = args.get("command").get(); + ClientChannel* channel_ptr = (ClientChannel*) static_cast(args.get("handle").get()); + + auto open = [this, v_command, channel_ptr](const std::shared_ptr& response) -> void { + LoggerD("Transmit APDDU command to secure element"); + try { + SEChannel seChannel(channel_ptr); + ByteArray transmit_response = seChannel.transmit(v_command); + picojson::value result = picojson::value(picojson::array()); + picojson::array& arr = result.get(); + for ( int i; i < transmit_response.size(); i++) { + arr.push_back(picojson::value(static_cast(transmit_response[i]))); + } + ReportSuccess( result, response->get()); + } catch (const PlatformException& e) { + ReportError( e, response->get()); + } + }; + + auto get_response = [this, callback_id](const std::shared_ptr& response) -> void { + LoggerD("Getting response"); + picojson::object& obj = response->get(); + obj.insert(std::make_pair("callbackId", callback_id)); + PostMessage(response->serialize().c_str()); + }; + + TaskQueue::GetInstance().Queue + ( open, get_response, std::shared_ptr(new picojson::value(picojson::object()))); } } // namespace secureelement diff --git a/src/secureelement/secureelement_instance.h b/src/secureelement/secureelement_instance.h index 0324c7c0..9f9cb01e 100644 --- a/src/secureelement/secureelement_instance.h +++ b/src/secureelement/secureelement_instance.h @@ -35,6 +35,7 @@ private: void OpenBasicChannel(const picojson::value& args, picojson::object& out); void OpenLogicalChannel(const picojson::value& args, picojson::object& out); void GetATR(const picojson::value& args, picojson::object& out); + void IsSessionClosed(const picojson::value& args, picojson::object& out); void CloseSession(const picojson::value& args, picojson::object& out); void CloseChannels(const picojson::value& args, picojson::object& out); diff --git a/src/secureelement/secureelement_session.cc b/src/secureelement/secureelement_session.cc new file mode 100644 index 00000000..994b6ceb --- /dev/null +++ b/src/secureelement/secureelement_session.cc @@ -0,0 +1,90 @@ +// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include "common/picojson.h" +#include "common/logger.h" +#include "secureelement_session.h" + +using namespace smartcard_service_api; + +namespace extension { +namespace secureelement { + +picojson::value SESession::openBasicChannel(const picojson::array& v_aid) { + LoggerD("Entered"); + + unsigned char* aid = new unsigned char[v_aid.size()]; + for ( int i = 0; i < v_aid.size(); i++) { + aid[i] = static_cast(v_aid[i].get()); + } + ByteArray aid_byte_array( aid, (unsigned int) v_aid.size()); + ClientChannel* channel_ptr = static_cast(m_session_ptr->openBasicChannelSync( aid_byte_array)); + delete aid; + + picojson::value result = picojson::value(picojson::object()); + picojson::object& obj = result.get(); + obj.insert(std::make_pair("handle", (double) (long) channel_ptr)); + obj.insert(std::make_pair("isBasicChannel", channel_ptr->isBasicChannel())); + + return result; +} + + +picojson::value SESession::openLogicalChannel(const picojson::array& v_aid) { + LoggerD("Entered"); + + unsigned char* aid = new unsigned char[v_aid.size()]; + for ( int i = 0; i < v_aid.size(); i++) { + aid[i] = static_cast(v_aid[i].get()); + } + ByteArray aid_byte_array( aid, (unsigned int) v_aid.size()); + ClientChannel* channel_ptr = static_cast(m_session_ptr->openLogicalChannelSync( aid_byte_array)); + delete aid; + + picojson::value result = picojson::value(picojson::object()); + picojson::object& obj = result.get(); + obj.insert(std::make_pair("handle", (double) (long) channel_ptr)); + obj.insert(std::make_pair("isBasicChannel", channel_ptr->isBasicChannel())); + + return result; +} + + +picojson::value SESession::isClosed() { + LoggerD("Entered"); + bool is_closed = m_session_ptr->isClosed(); + picojson::value result = picojson::value(picojson::object()); + picojson::object& obj = result.get(); + obj.insert(std::make_pair("isClosed", is_closed)); + return result; +} + + +void SESession::close() { + if ( m_session_ptr) { + m_session_ptr->closeSync(); + } +} + + +ByteArray SESession::getATR() { + ByteArray response; + if ( m_session_ptr) { + response = m_session_ptr->getATRSync(); + } + return response; +} + + +void SESession::closeChannels() { + if ( m_session_ptr) { + m_session_ptr->closeChannels(); + } +} + + +} // secureelement +} // extension diff --git a/src/secureelement/secureelement_session.h b/src/secureelement/secureelement_session.h new file mode 100644 index 00000000..a56fd10d --- /dev/null +++ b/src/secureelement/secureelement_session.h @@ -0,0 +1,33 @@ +// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SECUREELEMENT_SESSION_H_ +#define SECUREELEMENT_SESSION_H_ + +#include +#include "common/picojson.h" +#include "common/logger.h" + +namespace extension { +namespace secureelement { + +class SESession { +public: + SESession(smartcard_service_api::Session* session_ptr) : m_session_ptr(session_ptr) {}; + ~SESession() {}; + picojson::value openBasicChannel( const picojson::array& v_aid); + picojson::value openLogicalChannel( const picojson::array& v_aid); + picojson::value isClosed(); + void close(); + smartcard_service_api::ByteArray getATR(); + void closeChannels(); +private: + smartcard_service_api::Session* m_session_ptr; + void* m_user_data; +}; + +} // secureelement +} // extension + +#endif // SECUREELEMENT_SESSION_H_