diff options
Diffstat (limited to 'dom/secureelement/gonk/UiccConnector.js')
-rw-r--r-- | dom/secureelement/gonk/UiccConnector.js | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/dom/secureelement/gonk/UiccConnector.js b/dom/secureelement/gonk/UiccConnector.js deleted file mode 100644 index 517303de2..000000000 --- a/dom/secureelement/gonk/UiccConnector.js +++ /dev/null @@ -1,360 +0,0 @@ -/* Copyright 2012 Mozilla Foundation and Mozilla contributors - * - * 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. - */ - -/* Copyright © 2014, Deutsche Telekom, Inc. */ - -"use strict"; - -/* globals Components, XPCOMUtils, SE, dump, libcutils, Services, - iccService, SEUtils */ - -const { interfaces: Ci, utils: Cu, results: Cr } = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/systemlibs.js"); - -XPCOMUtils.defineLazyGetter(this, "SE", function() { - let obj = {}; - Cu.import("resource://gre/modules/se_consts.js", obj); - return obj; -}); - -// set to true in se_consts.js to see debug messages -var DEBUG = SE.DEBUG_CONNECTOR; -function debug(s) { - if (DEBUG) { - dump("-*- UiccConnector: " + s + "\n"); - } -} - -XPCOMUtils.defineLazyModuleGetter(this, "SEUtils", - "resource://gre/modules/SEUtils.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "iccService", - "@mozilla.org/icc/iccservice;1", - "nsIIccService"); - -const UICCCONNECTOR_CONTRACTID = - "@mozilla.org/secureelement/connector/uicc;1"; -const UICCCONNECTOR_CID = - Components.ID("{8e040e5d-c8c3-4c1b-ac82-c00d25d8c4a4}"); -const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown"; - -// TODO: Bug 1118099 - Add multi-sim support. -// In the Multi-sim, there is more than one client. -// For now, use default clientID as 0. Ideally, SE parent process would like to -// know which clients (uicc slot) are connected to CLF over SWP interface. -const PREFERRED_UICC_CLIENTID = - libcutils.property_get("ro.moz.se.def_client_id", "0"); - -/** - * 'UiccConnector' object is a wrapper over iccService's channel management - * related interfaces that implements nsISecureElementConnector interface. - */ -function UiccConnector() { - this._init(); -} - -UiccConnector.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsISecureElementConnector, - Ci.nsIIccListener]), - classID: UICCCONNECTOR_CID, - classInfo: XPCOMUtils.generateCI({ - classID: UICCCONNECTOR_CID, - contractID: UICCCONNECTOR_CONTRACTID, - classDescription: "UiccConnector", - interfaces: [Ci.nsISecureElementConnector, - Ci.nsIIccListener, - Ci.nsIObserver] - }), - - _SEListeners: [], - _isPresent: false, - - _init: function() { - Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); - let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID); - icc.registerListener(this); - - // Update the state in order to avoid race condition. - // By this time, 'notifyCardStateChanged (with proper card state)' - // may have occurred already before this module initialization. - this._updatePresenceState(); - }, - - _shutdown: function() { - Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID); - icc.unregisterListener(this); - }, - - _updatePresenceState: function() { - let uiccNotReadyStates = [ - Ci.nsIIcc.CARD_STATE_UNKNOWN, - Ci.nsIIcc.CARD_STATE_ILLEGAL, - Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS, - Ci.nsIIcc.CARD_STATE_PERMANENT_BLOCKED, - Ci.nsIIcc.CARD_STATE_UNDETECTED - ]; - - let cardState = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID).cardState; - let uiccPresent = cardState !== null && - uiccNotReadyStates.indexOf(cardState) == -1; - - if (this._isPresent === uiccPresent) { - return; - } - - debug("Uicc presence changed " + this._isPresent + " -> " + uiccPresent); - this._isPresent = uiccPresent; - this._SEListeners.forEach((listener) => { - listener.notifySEPresenceChanged(SE.TYPE_UICC, this._isPresent); - }); - }, - - // See GP Spec, 11.1.4 Class Byte Coding - _setChannelToCLAByte: function(cla, channel) { - if (channel < SE.LOGICAL_CHANNEL_NUMBER_LIMIT) { - // b7 = 0 indicates the first interindustry class byte coding - cla = (cla & 0x9C) & 0xFF | channel; - } else if (channel < SE.SUPPLEMENTARY_LOGICAL_CHANNEL_NUMBER_LIMIT) { - // b7 = 1 indicates the further interindustry class byte coding - cla = (cla & 0xB0) & 0xFF | 0x40 | (channel - SE.LOGICAL_CHANNEL_NUMBER_LIMIT); - } else { - debug("Channel number must be within [0..19]"); - return SE.ERROR_GENERIC; - } - return cla; - }, - - _doGetOpenResponse: function(channel, length, callback) { - // Le value is set. It means that this is a request for all available - // response bytes. - let cla = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE, channel); - this.exchangeAPDU(channel, cla, SE.INS_GET_RESPONSE, 0x00, 0x00, - null, length, { - notifyExchangeAPDUResponse: function(sw1, sw2, response) { - debug("GET Response : " + response); - if (callback) { - callback({ - error: SE.ERROR_NONE, - sw1: sw1, - sw2: sw2, - response: response - }); - } - }, - - notifyError: function(reason) { - debug("Failed to get open response: " + - ", Rejected with Reason : " + reason); - if (callback) { - callback({ error: SE.ERROR_INVALIDAPPLICATION, reason: reason }); - } - } - }); - }, - - _doIccExchangeAPDU: function(channel, cla, ins, p1, p2, p3, - data, appendResp, callback) { - let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID); - icc.iccExchangeAPDU(channel, cla & 0xFC, ins, p1, p2, p3, data, { - notifyExchangeAPDUResponse: (sw1, sw2, response) => { - debug("sw1 : " + sw1 + ", sw2 : " + sw2 + ", response : " + response); - - // According to ETSI TS 102 221 , Section 7.2.2.3.1, - // Enforce 'Procedure bytes' checks before notifying the callback. - // Note that 'Procedure bytes'are special cases. - // There is no need to handle '0x60' procedure byte as it implies - // no-action from SE stack perspective. This procedure byte is not - // notified to application layer. - if (sw1 === 0x6C) { - // Use the previous command header with length as second procedure - // byte (SW2) as received and repeat the procedure. - - // Recursive! and Pass empty response '' as args, since '0x6C' - // procedure does not have to deal with appended responses. - this._doIccExchangeAPDU(channel, cla, ins, p1, p2, - sw2, data, "", callback); - } else if (sw1 === 0x61) { - // Since the terminal waited for a second procedure byte and - // received it (sw2), send a GET RESPONSE command header to the UICC - // with a maximum length of 'XX', where 'XX' is the value of the - // second procedure byte (SW2). - - let claWithChannel = this._setChannelToCLAByte(SE.CLA_GET_RESPONSE, - channel); - - // Recursive, with GET RESPONSE bytes and '0x61' procedure IS interested - // in appended responses. Pass appended response and note that p3=sw2. - this._doIccExchangeAPDU(channel, claWithChannel, SE.INS_GET_RESPONSE, - 0x00, 0x00, sw2, null, - (response ? response + appendResp : appendResp), - callback); - } else if (callback) { - callback.notifyExchangeAPDUResponse(sw1, sw2, response); - } - }, - - notifyError: (reason) => { - debug("Failed to trasmit C-APDU over the channel # : " + channel + - ", Rejected with Reason : " + reason); - if (callback) { - callback.notifyError(reason); - } - } - }); - }, - - /** - * nsISecureElementConnector interface methods. - */ - - /** - * Opens a channel on a default clientId - */ - openChannel: function(aid, callback) { - if (!this._isPresent) { - callback.notifyError(SE.ERROR_NOTPRESENT); - return; - } - - // TODO: Bug 1118106: Handle Resource management / leaks by persisting - // the newly opened channel in some persistent storage so that when this - // module gets restarted (say after opening a channel) in the event of - // some erroneous conditions such as gecko restart /, crash it can read - // the persistent storage to check if there are any held resources - // (opened channels) and close them. - let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID); - icc.iccOpenChannel(aid, { - notifyOpenChannelSuccess: (channel) => { - this._doGetOpenResponse(channel, 0x00, function(result) { - if (callback) { - callback.notifyOpenChannelSuccess(channel, result.response); - } - }); - }, - - notifyError: (reason) => { - debug("Failed to open the channel to AID : " + aid + - ", Rejected with Reason : " + reason); - if (callback) { - callback.notifyError(reason); - } - } - }); - }, - - /** - * Transmit the C-APDU (command) on default clientId. - */ - exchangeAPDU: function(channel, cla, ins, p1, p2, data, le, callback) { - if (!this._isPresent) { - callback.notifyError(SE.ERROR_NOTPRESENT); - return; - } - - if (data && data.length % 2 !== 0) { - callback.notifyError("Data should be a hex string with length % 2 === 0"); - return; - } - - cla = this._setChannelToCLAByte(cla, channel); - let lc = data ? data.length / 2 : 0; - let p3 = lc || le; - - if (lc && (le !== -1)) { - data += SEUtils.byteArrayToHexString([le]); - } - - // Pass empty response '' as args as we are not interested in appended - // responses yet! - debug("exchangeAPDU on Channel # " + channel); - this._doIccExchangeAPDU(channel, cla, ins, p1, p2, p3, data, "", - callback); - }, - - /** - * Closes the channel on default clientId. - */ - closeChannel: function(channel, callback) { - if (!this._isPresent) { - callback.notifyError(SE.ERROR_NOTPRESENT); - return; - } - - let icc = iccService.getIccByServiceId(PREFERRED_UICC_CLIENTID); - icc.iccCloseChannel(channel, { - notifyCloseChannelSuccess: function() { - debug("closeChannel successfully closed the channel # : " + channel); - if (callback) { - callback.notifyCloseChannelSuccess(); - } - }, - - notifyError: function(reason) { - debug("Failed to close the channel # : " + channel + - ", Rejected with Reason : " + reason); - if (callback) { - callback.notifyError(reason); - } - } - }); - }, - - registerListener: function(listener) { - if (this._SEListeners.indexOf(listener) !== -1) { - throw Cr.NS_ERROR_UNEXPECTED; - } - - this._SEListeners.push(listener); - // immediately notify listener about the current state - listener.notifySEPresenceChanged(SE.TYPE_UICC, this._isPresent); - }, - - unregisterListener: function(listener) { - let idx = this._SEListeners.indexOf(listener); - if (idx !== -1) { - this._SEListeners.splice(idx, 1); - } - }, - - /** - * nsIIccListener interface methods. - */ - notifyStkCommand: function() {}, - - notifyStkSessionEnd: function() {}, - - notifyIccInfoChanged: function() {}, - - notifyCardStateChanged: function() { - debug("Card state changed, updating UICC presence."); - this._updatePresenceState(); - }, - - /** - * nsIObserver interface methods. - */ - - observe: function(subject, topic, data) { - if (topic === NS_XPCOM_SHUTDOWN_OBSERVER_ID) { - this._shutdown(); - } - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UiccConnector]); |