2 * Copyright (C) 2017 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * Copyright (c) 2017, The Linux Foundation.
20 * Contributed by: Giesecke & Devrient GmbH.
23 package android.se.omapi;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.os.RemoteException;
28 import android.os.ServiceSpecificException;
29 import android.util.Log;
31 import java.io.IOException;
32 import java.util.NoSuchElementException;
35 * Instances of this class represent a connection session to one of the Secure
36 * Elements available on the device. These objects can be used to get a
37 * communication channel with an Applet in the Secure Element.
38 * This channel can be the basic channel or a logical channel.
40 * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v3.0</a>
42 public class Session {
44 private final Object mLock = new Object();
45 private final SEService mService;
46 private final Reader mReader;
47 private final ISecureElementSession mSession;
48 private static final String TAG = "OMAPI.Session";
50 Session(@NonNull SEService service, @NonNull ISecureElementSession session,
51 @NonNull Reader reader) {
52 if (service == null || reader == null || session == null) {
53 throw new IllegalArgumentException("Parameters cannot be null");
61 * Get the reader that provides this session.
63 * @return The Reader object.
65 public @NonNull Reader getReader() {
70 * Get the Answer to Reset of this Secure Element. <br>
71 * The returned byte array can be null if the ATR for this Secure Element is
74 * @throws IllegalStateException if there was an error connecting to SE or
75 * if the service was not connected.
76 * @return the ATR as a byte array or null.
78 public @Nullable byte[] getATR() {
79 if (!mService.isConnected()) {
80 throw new IllegalStateException("service not connected to system");
83 return mSession.getAtr();
84 } catch (RemoteException e) {
85 throw new IllegalStateException(e.getMessage());
90 * Close the connection with the Secure Element. This will close any
91 * channels opened by this application with this Secure Element.
94 if (!mService.isConnected()) {
95 Log.e(TAG, "service not connected to system");
98 synchronized (mLock) {
101 } catch (RemoteException e) {
102 Log.e(TAG, "Error closing session", e);
108 * Tells if this session is closed.
110 * @return <code>true</code> if the session is closed, false otherwise.
112 public boolean isClosed() {
114 return mSession.isClosed();
115 } catch (RemoteException e) {
116 // If there was an error here, then the session is considered close
122 * Close any channel opened on this session.
124 public void closeChannels() {
125 if (!mService.isConnected()) {
126 Log.e(TAG, "service not connected to system");
130 synchronized (mLock) {
132 mSession.closeChannels();
133 } catch (RemoteException e) {
134 Log.e(TAG, "Error closing channels", e);
140 * Get an access to the basic channel, as defined in the ISO/IEC 7816-4 specification (the
141 * one that has number 0). The obtained object is an instance of the Channel class.
142 * If the AID is null, it means no Applet is to be selected on this channel and the default
143 * Applet is used. If the AID is defined then the corresponding Applet is selected.
144 * Once this channel has been opened by a device application, it is considered as "locked"
145 * by this device application, and other calls to this method will return null, until the
146 * channel is closed. Some Secure Elements (like the UICC) might always keep the basic channel
147 * locked (i.e. return null to applications), to prevent access to the basic channel, while
148 * some other might return a channel object implementing some kind of filtering on the
149 * commands, restricting the set of accepted command to a smaller set.
150 * It is recommended for the UICC to reject the opening of the basic channel to a specific
151 * applet, by always answering null to such a request.
152 * For other Secure Elements, the recommendation is to accept opening the basic channel
153 * on the default applet until another applet is selected on the basic channel. As there is no
154 * other way than a reset to select again the default applet, the implementation of the
155 * transport API should guarantee that the openBasicChannel(null) command will return
156 * null until a reset occurs.
157 * With previous release (V2.05) it was not possible to set P2 value, this value was always
158 * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is
159 * recommended that the device allows all values for P2, however only the following values
160 * are mandatory: '00', '04', '08', '0C'(as defined in [2])
161 * The implementation of the underlying SELECT command within this method shall be
162 * based on ISO 7816-4 with following options:
164 * <li>CLA = '00'</li>
165 * <li>INS = 'A4'</li>
166 * <li>P1 = '04' (Select by DF name/application identifier)</li>
169 * The select response data can be retrieved with byte[] getSelectResponse().
170 * The API shall handle received status word as follow. If the status word indicates that the
171 * Secure Element was able to open a channel (e.g. status word '90 00' or status words
172 * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the
173 * channel opened and the next getSelectResponse() shall return the received status
175 * Other received status codes indicating that the Secure Element was able not to open a
176 * channel shall be considered as an error and the corresponding channel shall not be
178 * The function without P2 as parameter is provided for backwards compatibility and will
179 * fall back to a select command with P2='00'.
181 * @param aid the AID of the Applet to be selected on this channel, as a
182 * byte array, or null if no Applet is to be selected.
183 * @param p2 the P2 parameter of the SELECT APDU executed on this channel.
184 * @throws IOException if there is a communication problem to the reader or
185 * the Secure Element.
186 * @throws IllegalStateException if the Secure Element session is used after
188 * @throws IllegalArgumentException if the aid's length is not within 5 to
190 * @throws SecurityException if the calling application cannot be granted
191 * access to this AID or the default Applet on this
193 * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be
195 * @throws UnsupportedOperationException if the given P2 parameter is not
196 * supported by the device
197 * @return an instance of Channel if available or null.
199 public @Nullable Channel openBasicChannel(@Nullable byte[] aid, @Nullable byte p2)
201 if (!mService.isConnected()) {
202 throw new IllegalStateException("service not connected to system");
205 synchronized (mLock) {
207 ISecureElementChannel channel = mSession.openBasicChannel(aid, p2,
208 mReader.getSEService().getListener());
209 if (channel == null) {
212 return new Channel(mService, this, channel);
213 } catch (ServiceSpecificException e) {
214 if (e.errorCode == SEService.IO_ERROR) {
215 throw new IOException(e.getMessage());
216 } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) {
217 throw new NoSuchElementException(e.getMessage());
219 throw new IllegalStateException(e.getMessage());
221 } catch (RemoteException e) {
222 throw new IllegalStateException(e.getMessage());
228 * Open a logical channel with the Secure Element, selecting the Applet represented by
229 * the given AID. If the AID is null, which means no Applet is to be selected on this
230 * channel, the default Applet is used. It's up to the Secure Element to choose which
231 * logical channel will be used.
232 * With previous release (V2.05) it was not possible to set P2 value, this value was always
233 * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is
234 * recommended that the device allows all values for P2, however only the following values
235 * are mandatory: '00', '04', '08', '0C'(as defined in [2])
236 * The implementation of the underlying SELECT command within this method shall be
237 * based on ISO 7816-4 with following options:
240 * <li>CLA = '01' to '03', '40 to 4F'</li>
241 * <li>INS = 'A4'</li>
242 * <li>P1 = '04' (Select by DF name/application identifier)</li>
245 * The select response data can be retrieved with byte[] getSelectResponse().
246 * The API shall handle received status word as follow. If the status word indicates that the
247 * Secure Element was able to open a channel (e.g. status word '90 00' or status words
248 * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the
249 * channel opened and the next getSelectResponse() shall return the received status
251 * Other received status codes indicating that the Secure Element was able not to open a
252 * channel shall be considered as an error and the corresponding channel shall not be
254 * In case of UICC it is recommended for the API to reject the opening of the logical
255 * channel without a specific AID, by always answering null to such a request.
256 * The function without P2 as parameter is provided for backwards compatibility and will
257 * fall back to a select command with P2=00.
259 * @param aid the AID of the Applet to be selected on this channel, as a
261 * @param p2 the P2 parameter of the SELECT APDU executed on this channel.
262 * @throws IOException if there is a communication problem to the reader or
263 * the Secure Element.
264 * @throws IllegalStateException if the Secure Element is used after being
266 * @throws IllegalArgumentException if the aid's length is not within 5 to
268 * @throws SecurityException if the calling application cannot be granted
269 * access to this AID or the default Applet on this
271 * @throws NoSuchElementException if the AID on the Secure Element is not
272 * available or cannot be selected or a logical channel is already
273 * open to a non-multiselectable Applet.
274 * @throws UnsupportedOperationException if the given P2 parameter is not
275 * supported by the device.
276 * @return an instance of Channel. Null if the Secure Element is unable to
277 * provide a new logical channel.
279 public @Nullable Channel openLogicalChannel(@Nullable byte[] aid, @Nullable byte p2)
281 if (!mService.isConnected()) {
282 throw new IllegalStateException("service not connected to system");
284 synchronized (mLock) {
286 ISecureElementChannel channel = mSession.openLogicalChannel(
289 mReader.getSEService().getListener());
290 if (channel == null) {
293 return new Channel(mService, this, channel);
294 } catch (ServiceSpecificException e) {
295 if (e.errorCode == SEService.IO_ERROR) {
296 throw new IOException(e.getMessage());
297 } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) {
298 throw new NoSuchElementException(e.getMessage());
300 throw new IllegalStateException(e.getMessage());
302 } catch (RemoteException e) {
303 throw new IllegalStateException(e.getMessage());