All Downloads are FREE. Search and download functionalities are using the official Maven repository.

android.se.omapi.Session Maven / Gradle / Ivy

Go to download

A library jar that provides APIs for Applications written for the Google Android Platform.

There is a newer version: 14-robolectric-10818077
Show newest version
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 (c) 2017, The Linux Foundation.
 */
/*
 * Contributed by: Giesecke & Devrient GmbH.
 */

package android.se.omapi;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.util.Log;

import java.io.IOException;
import java.util.NoSuchElementException;

/**
 * Instances of this class represent a connection session to one of the Secure
 * Elements available on the device. These objects can be used to get a
 * communication channel with an Applet in the Secure Element.
 * This channel can be the basic channel or a logical channel.
 *
 * @see SIMalliance Open Mobile API  v3.0
 */
public final class Session {

    private final Object mLock = new Object();
    private final SEService mService;
    private final Reader mReader;
    private final ISecureElementSession mSession;
    private static final String TAG = "OMAPI.Session";

    Session(@NonNull SEService service, @NonNull ISecureElementSession session,
            @NonNull Reader reader) {
        if (service == null || reader == null || session == null) {
            throw new IllegalArgumentException("Parameters cannot be null");
        }
        mService = service;
        mReader = reader;
        mSession = session;
    }

    /**
     * Get the reader that provides this session.
     *
     * @return The Reader object.
     */
    public @NonNull Reader getReader() {
        return mReader;
    }

    /**
     * Get the Answer to Reset of this Secure Element. 
* The returned byte array can be null if the ATR for this Secure Element is * not available. * * @throws IllegalStateException if there was an error connecting to SE or * if the service was not connected. * @return the ATR as a byte array or null. */ public @Nullable byte[] getATR() { if (!mService.isConnected()) { throw new IllegalStateException("service not connected to system"); } try { return mSession.getAtr(); } catch (RemoteException e) { throw new IllegalStateException(e.getMessage()); } } /** * Close the connection with the Secure Element. This will close any * channels opened by this application with this Secure Element. */ public void close() { if (!mService.isConnected()) { Log.e(TAG, "service not connected to system"); return; } synchronized (mLock) { try { mSession.close(); } catch (RemoteException e) { Log.e(TAG, "Error closing session", e); } } } /** * Tells if this session is closed. * * @return true if the session is closed, false otherwise. */ public boolean isClosed() { try { return mSession.isClosed(); } catch (RemoteException e) { // If there was an error here, then the session is considered close return true; } } /** * Close any channel opened on this session. */ public void closeChannels() { if (!mService.isConnected()) { Log.e(TAG, "service not connected to system"); return; } synchronized (mLock) { try { mSession.closeChannels(); } catch (RemoteException e) { Log.e(TAG, "Error closing channels", e); } } } /** * Get an access to the basic channel, as defined in the ISO/IEC 7816-4 specification (the * one that has number 0). The obtained object is an instance of the Channel class. * If the AID is null, it means no Applet is to be selected on this channel and the default * Applet is used. If the AID is defined then the corresponding Applet is selected. * Once this channel has been opened by a device application, it is considered as "locked" * by this device application, and other calls to this method will return null, until the * channel is closed. Some Secure Elements (like the UICC) might always keep the basic channel * locked (i.e. return null to applications), to prevent access to the basic channel, while * some other might return a channel object implementing some kind of filtering on the * commands, restricting the set of accepted command to a smaller set. * It is recommended for the UICC to reject the opening of the basic channel to a specific * applet, by always answering null to such a request. * For other Secure Elements, the recommendation is to accept opening the basic channel * on the default applet until another applet is selected on the basic channel. As there is no * other way than a reset to select again the default applet, the implementation of the * transport API should guarantee that the openBasicChannel(null) command will return * null until a reset occurs. * With previous release (V2.05) it was not possible to set P2 value, this value was always * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is * recommended that the device allows all values for P2, however only the following values * are mandatory: '00', '04', '08', '0C'(as defined in [2]) * The implementation of the underlying SELECT command within this method shall be * based on ISO 7816-4 with following options: *
    *
  • CLA = '00'
  • *
  • INS = 'A4'
  • *
  • P1 = '04' (Select by DF name/application identifier)
  • *
* * The select response data can be retrieved with byte[] getSelectResponse(). * The API shall handle received status word as follow. If the status word indicates that the * Secure Element was able to open a channel (e.g. status word '90 00' or status words * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the * channel opened and the next getSelectResponse() shall return the received status * word. * Other received status codes indicating that the Secure Element was able not to open a * channel shall be considered as an error and the corresponding channel shall not be * opened. * The function without P2 as parameter is provided for backwards compatibility and will * fall back to a select command with P2='00'. * * @param aid the AID of the Applet to be selected on this channel, as a * byte array, or null if no Applet is to be selected. * @param p2 the P2 parameter of the SELECT APDU executed on this channel. * @throws IOException if there is a communication problem to the reader or * the Secure Element. * @throws IllegalStateException if the Secure Element session is used after * being closed. * @throws IllegalArgumentException if the aid's length is not within 5 to * 16 (inclusive). * @throws SecurityException if the calling application cannot be granted * access to this AID or the default Applet on this * session. * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be * selected. * @throws UnsupportedOperationException if the given P2 parameter is not * supported by the device * @return an instance of Channel if available or null. */ public @Nullable Channel openBasicChannel(@Nullable byte[] aid, @Nullable byte p2) throws IOException { if (!mService.isConnected()) { throw new IllegalStateException("service not connected to system"); } synchronized (mLock) { try { ISecureElementChannel channel = mSession.openBasicChannel(aid, p2, mReader.getSEService().getListener()); if (channel == null) { return null; } return new Channel(mService, this, channel); } catch (ServiceSpecificException e) { if (e.errorCode == SEService.IO_ERROR) { throw new IOException(e.getMessage()); } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) { throw new NoSuchElementException(e.getMessage()); } else { throw new IllegalStateException(e.getMessage()); } } catch (RemoteException e) { throw new IllegalStateException(e.getMessage()); } } } /** * This method is provided to ease the development of mobile application and for compliancy * with existing applications. * This method is equivalent to openBasicChannel(aid, P2=0x00) * * @param aid the AID of the Applet to be selected on this channel, as a * byte array, or null if no Applet is to be selected. * @throws IOException if there is a communication problem to the reader or * the Secure Element. * @throws IllegalStateException if the Secure Element session is used after * being closed. * @throws IllegalArgumentException if the aid's length is not within 5 to * 16 (inclusive). * @throws SecurityException if the calling application cannot be granted * access to this AID or the default Applet on this * session. * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be * selected. * @throws UnsupportedOperationException if the given P2 parameter is not * supported by the device * @return an instance of Channel if available or null. */ public @Nullable Channel openBasicChannel(@Nullable byte[] aid) throws IOException { return openBasicChannel(aid, (byte) 0x00); } /** * Open a logical channel with the Secure Element, selecting the Applet represented by * the given AID. If the AID is null, which means no Applet is to be selected on this * channel, the default Applet is used. It's up to the Secure Element to choose which * logical channel will be used. * With previous release (V2.05) it was not possible to set P2 value, this value was always * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is * recommended that the device allows all values for P2, however only the following values * are mandatory: '00', '04', '08', '0C'(as defined in [2]) * The implementation of the underlying SELECT command within this method shall be * based on ISO 7816-4 with following options: * *
    *
  • CLA = '01' to '03', '40 to 4F'
  • *
  • INS = 'A4'
  • *
  • P1 = '04' (Select by DF name/application identifier)
  • *
* * The select response data can be retrieved with byte[] getSelectResponse(). * The API shall handle received status word as follow. If the status word indicates that the * Secure Element was able to open a channel (e.g. status word '90 00' or status words * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the * channel opened and the next getSelectResponse() shall return the received status * word. * Other received status codes indicating that the Secure Element was able not to open a * channel shall be considered as an error and the corresponding channel shall not be * opened. * In case of UICC it is recommended for the API to reject the opening of the logical * channel without a specific AID, by always answering null to such a request. * The function without P2 as parameter is provided for backwards compatibility and will * fall back to a select command with P2=00. * * @param aid the AID of the Applet to be selected on this channel, as a * byte array. * @param p2 the P2 parameter of the SELECT APDU executed on this channel. * @throws IOException if there is a communication problem to the reader or * the Secure Element. * @throws IllegalStateException if the Secure Element is used after being * closed. * @throws IllegalArgumentException if the aid's length is not within 5 to * 16 (inclusive). * @throws SecurityException if the calling application cannot be granted * access to this AID or the default Applet on this * session. * @throws NoSuchElementException if the AID on the Secure Element is not * available or cannot be selected or a logical channel is already * open to a non-multiselectable Applet. * @throws UnsupportedOperationException if the given P2 parameter is not * supported by the device. * @return an instance of Channel. Null if the Secure Element is unable to * provide a new logical channel. */ public @Nullable Channel openLogicalChannel(@Nullable byte[] aid, @Nullable byte p2) throws IOException { if (!mService.isConnected()) { throw new IllegalStateException("service not connected to system"); } synchronized (mLock) { try { ISecureElementChannel channel = mSession.openLogicalChannel( aid, p2, mReader.getSEService().getListener()); if (channel == null) { return null; } return new Channel(mService, this, channel); } catch (ServiceSpecificException e) { if (e.errorCode == SEService.IO_ERROR) { throw new IOException(e.getMessage()); } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) { throw new NoSuchElementException(e.getMessage()); } else { throw new IllegalStateException(e.getMessage()); } } catch (RemoteException e) { throw new IllegalStateException(e.getMessage()); } } } /** * This method is provided to ease the development of mobile application and for compliancy * with existing applications. * This method is equivalent to openLogicalChannel(aid, P2=0x00) * * @param aid the AID of the Applet to be selected on this channel, as a * byte array. * @throws IOException if there is a communication problem to the reader or * the Secure Element. * @throws IllegalStateException if the Secure Element is used after being * closed. * @throws IllegalArgumentException if the aid's length is not within 5 to * 16 (inclusive). * @throws SecurityException if the calling application cannot be granted * access to this AID or the default Applet on this * session. * @throws NoSuchElementException if the AID on the Secure Element is not * available or cannot be selected or a logical channel is already * open to a non-multiselectable Applet. * @throws UnsupportedOperationException if the given P2 parameter is not * supported by the device. * @return an instance of Channel. Null if the Secure Element is unable to * provide a new logical channel. */ public @Nullable Channel openLogicalChannel(@Nullable byte[] aid) throws IOException { return openLogicalChannel(aid, (byte) 0x00); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy