[SecureElement] - Session and Channel interfaces created.
authorAndrzej Popowski <a.popowski@samsung.com>
Wed, 7 Jan 2015 10:41:37 +0000 (11:41 +0100)
committerAndrzej Popowski <a.popowski@samsung.com>
Mon, 19 Jan 2015 13:28:08 +0000 (14:28 +0100)
Change-Id: I43c5c2a07b758000c4cb7893d9830da8c858b278
Signed-off-by: Andrzej Popowski <a.popowski@samsung.com>
src/secureelement/secureelement.gyp
src/secureelement/secureelement_api.js
src/secureelement/secureelement_channel.cc [new file with mode: 0644]
src/secureelement/secureelement_channel.h [new file with mode: 0644]
src/secureelement/secureelement_instance.cc
src/secureelement/secureelement_instance.h
src/secureelement/secureelement_session.cc [new file with mode: 0644]
src/secureelement/secureelement_session.h [new file with mode: 0644]

index 6fd0308d31dfcad5ee9038c2c009d913b84f3fb2..64433572414aacaf94342d9274ab88c2b2fc4a92 100644 (file)
         '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',
index 7e5f7b2906c3130ec4c5454b089e5830cedd78d4..9935a3e745170d0fb91bb4eb8633e5e5e3a67922 100644 (file)
@@ -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 (file)
index 0000000..3a662f5
--- /dev/null
@@ -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<long>(v_command[i].get<double>());
+        }
+        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 (file)
index 0000000..b87e66d
--- /dev/null
@@ -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 <ClientChannel.h>
+#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_
index 6281c08e5e11945b5a5b284a4799cd8515e6e13c..7dd9d46dcedea017158080e2c15b59ebecc33bad 100644 (file)
@@ -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<long>(args.get("handle").get<double>());
+    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<long>(args.get("handle").get<double>());
+    SEChannel seChannel(channel_ptr);
+
+    ByteArray select_response = seChannel.getSelectResponse();
+    picojson::value result = picojson::value(picojson::array());
+    picojson::array& arr = result.get<picojson::array>();
+    for ( int i; i < select_response.size(); i++) {
+        arr.push_back(picojson::value(static_cast<double>(select_response[i])));
+    }
+    ReportSuccess( result, out);
 }
 
 void SecureElementInstance::GetReaders(
@@ -162,18 +162,138 @@ void SecureElementInstance::OpenSession(
             std::shared_ptr<picojson::value>(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<double>();
+    const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Opening basic channel");
+        try {
+            SESession seSession(session_ptr);
+            picojson::value result = seSession.openBasicChannel(v_aid);
+            ReportSuccess(result, response->get<picojson::object>());
+        } catch (const PlatformException& e) {
+            ReportError(e, response->get<picojson::object>());
+        }
+    };
+
+    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", callback_id));
+        PostMessage(response->serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Queue<picojson::value>
+        ( open, get_response, std::shared_ptr<picojson::value>(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<double>();
+    const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Opening basic channel");
+        try {
+            SESession seSession(session_ptr);
+            picojson::value result = seSession.openBasicChannel(v_aid);
+            ReportSuccess(result, response->get<picojson::object>());
+        } catch (const PlatformException& e) {
+            ReportError(e, response->get<picojson::object>());
+        }
+    };
+
+    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", callback_id));
+        PostMessage(response->serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Queue<picojson::value>
+        ( open, get_response, std::shared_ptr<picojson::value>(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<long>(args.get("handle").get<double>());
+    SESession seSession(session_ptr);
+
+    ByteArray atr_result = seSession.getATR();
+    picojson::value result = picojson::value(picojson::array());
+    picojson::array& arr = result.get<picojson::array>();
+    for ( int i; i < atr_result.size(); i++) {
+        arr.push_back(picojson::value(static_cast<double>(atr_result[i])));
+    }
+    ReportSuccess( result, out);
+}
+
+
+void SecureElementInstance::IsSessionClosed( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+    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<long>(args.get("handle").get<double>());
+    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<long>(args.get("handle").get<double>());
+    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<double>();
+    const picojson::array v_command = args.get("command").get<picojson::value::array>();
+    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open = [this, v_command, channel_ptr](const std::shared_ptr<picojson::value>& 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<picojson::array>();
+            for ( int i; i < transmit_response.size(); i++) {
+                arr.push_back(picojson::value(static_cast<double>(transmit_response[i])));
+            }
+            ReportSuccess( result, response->get<picojson::object>());
+        } catch (const PlatformException& e) {
+            ReportError( e, response->get<picojson::object>());
+        }
+    };
+
+    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", callback_id));
+        PostMessage(response->serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Queue<picojson::value>
+        ( open, get_response, std::shared_ptr<picojson::value>(new picojson::value(picojson::object())));
 }
 
 } // namespace secureelement
index 0324c7c08d61f6909c889d68e793dd29e8379f87..9f9cb01e33ce9af1d4641ae0191b1b1336484395 100644 (file)
@@ -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 (file)
index 0000000..994b6ce
--- /dev/null
@@ -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 <Session.h>
+#include <ClientChannel.h>
+#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<unsigned char>(v_aid[i].get<double>());
+    }
+    ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
+    ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openBasicChannelSync( aid_byte_array));
+    delete aid;
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+    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<unsigned char>(v_aid[i].get<double>());
+    }
+    ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
+    ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openLogicalChannelSync( aid_byte_array));
+    delete aid;
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+    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<picojson::object>();
+    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 (file)
index 0000000..a56fd10
--- /dev/null
@@ -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 <Session.h>
+#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_