1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 /* 17 * Copyright (c) 2017, The Linux Foundation. 18 */ 19 /* 20 * Contributed by: Giesecke & Devrient GmbH. 21 */ 22 23 package android.se.omapi; 24 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; 30 31 import java.io.IOException; 32 import java.util.NoSuchElementException; 33 34 /** 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. 39 * 40 * @see <a href="http://simalliance.org">SIMalliance Open Mobile API v3.0</a> 41 */ 42 public final class Session { 43 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"; 49 Session(@onNull SEService service, @NonNull ISecureElementSession session, @NonNull Reader reader)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"); 54 } 55 mService = service; 56 mReader = reader; 57 mSession = session; 58 } 59 60 /** 61 * Get the reader that provides this session. 62 * 63 * @return The Reader object. 64 */ getReader()65 public @NonNull Reader getReader() { 66 return mReader; 67 } 68 69 /** 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 72 * not available. 73 * 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. 77 */ getATR()78 public @Nullable byte[] getATR() { 79 if (!mService.isConnected()) { 80 throw new IllegalStateException("service not connected to system"); 81 } 82 try { 83 return mSession.getAtr(); 84 } catch (RemoteException e) { 85 throw new IllegalStateException(e.getMessage()); 86 } 87 } 88 89 /** 90 * Close the connection with the Secure Element. This will close any 91 * channels opened by this application with this Secure Element. 92 */ close()93 public void close() { 94 if (!mService.isConnected()) { 95 Log.e(TAG, "service not connected to system"); 96 return; 97 } 98 synchronized (mLock) { 99 try { 100 mSession.close(); 101 } catch (RemoteException e) { 102 Log.e(TAG, "Error closing session", e); 103 } 104 } 105 } 106 107 /** 108 * Tells if this session is closed. 109 * 110 * @return <code>true</code> if the session is closed, false otherwise. 111 */ isClosed()112 public boolean isClosed() { 113 try { 114 return mSession.isClosed(); 115 } catch (RemoteException e) { 116 // If there was an error here, then the session is considered close 117 return true; 118 } 119 } 120 121 /** 122 * Close any channel opened on this session. 123 */ closeChannels()124 public void closeChannels() { 125 if (!mService.isConnected()) { 126 Log.e(TAG, "service not connected to system"); 127 return; 128 } 129 130 synchronized (mLock) { 131 try { 132 mSession.closeChannels(); 133 } catch (RemoteException e) { 134 Log.e(TAG, "Error closing channels", e); 135 } 136 } 137 } 138 139 /** 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: 163 * <ul> 164 * <li>CLA = '00'</li> 165 * <li>INS = 'A4'</li> 166 * <li>P1 = '04' (Select by DF name/application identifier)</li> 167 * </ul> 168 * 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 174 * word. 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 177 * opened. 178 * The function without P2 as parameter is provided for backwards compatibility and will 179 * fall back to a select command with P2='00'. 180 * 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 187 * being closed. 188 * @throws IllegalArgumentException if the aid's length is not within 5 to 189 * 16 (inclusive). 190 * @throws SecurityException if the calling application cannot be granted 191 * access to this AID or the default Applet on this 192 * session. 193 * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be 194 * selected. 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. 198 */ openBasicChannel(@ullable byte[] aid, @Nullable byte p2)199 public @Nullable Channel openBasicChannel(@Nullable byte[] aid, @Nullable byte p2) 200 throws IOException { 201 if (!mService.isConnected()) { 202 throw new IllegalStateException("service not connected to system"); 203 } 204 205 synchronized (mLock) { 206 try { 207 ISecureElementChannel channel = mSession.openBasicChannel(aid, p2, 208 mReader.getSEService().getListener()); 209 if (channel == null) { 210 return null; 211 } 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()); 218 } else { 219 throw new IllegalStateException(e.getMessage()); 220 } 221 } catch (RemoteException e) { 222 throw new IllegalStateException(e.getMessage()); 223 } 224 } 225 } 226 227 /** 228 * This method is provided to ease the development of mobile application and for compliancy 229 * with existing applications. 230 * This method is equivalent to openBasicChannel(aid, P2=0x00) 231 * 232 * @param aid the AID of the Applet to be selected on this channel, as a 233 * byte array, or null if no Applet is to be selected. 234 * @throws IOException if there is a communication problem to the reader or 235 * the Secure Element. 236 * @throws IllegalStateException if the Secure Element session is used after 237 * being closed. 238 * @throws IllegalArgumentException if the aid's length is not within 5 to 239 * 16 (inclusive). 240 * @throws SecurityException if the calling application cannot be granted 241 * access to this AID or the default Applet on this 242 * session. 243 * @throws NoSuchElementException if the AID on the Secure Element is not available or cannot be 244 * selected. 245 * @throws UnsupportedOperationException if the given P2 parameter is not 246 * supported by the device 247 * @return an instance of Channel if available or null. 248 */ openBasicChannel(@ullable byte[] aid)249 public @Nullable Channel openBasicChannel(@Nullable byte[] aid) throws IOException { 250 return openBasicChannel(aid, (byte) 0x00); 251 } 252 253 /** 254 * Open a logical channel with the Secure Element, selecting the Applet represented by 255 * the given AID. If the AID is null, which means no Applet is to be selected on this 256 * channel, the default Applet is used. It's up to the Secure Element to choose which 257 * logical channel will be used. 258 * With previous release (V2.05) it was not possible to set P2 value, this value was always 259 * set to '00'.Except for specific needs it is recommended to keep P2 to '00'. It is 260 * recommended that the device allows all values for P2, however only the following values 261 * are mandatory: '00', '04', '08', '0C'(as defined in [2]) 262 * The implementation of the underlying SELECT command within this method shall be 263 * based on ISO 7816-4 with following options: 264 * 265 * <ul> 266 * <li>CLA = '01' to '03', '40 to 4F'</li> 267 * <li>INS = 'A4'</li> 268 * <li>P1 = '04' (Select by DF name/application identifier)</li> 269 * </ul> 270 * 271 * The select response data can be retrieved with byte[] getSelectResponse(). 272 * The API shall handle received status word as follow. If the status word indicates that the 273 * Secure Element was able to open a channel (e.g. status word '90 00' or status words 274 * referencing a warning in ISO-7816-4: '62 XX' or '63 XX') the API shall keep the 275 * channel opened and the next getSelectResponse() shall return the received status 276 * word. 277 * Other received status codes indicating that the Secure Element was able not to open a 278 * channel shall be considered as an error and the corresponding channel shall not be 279 * opened. 280 * In case of UICC it is recommended for the API to reject the opening of the logical 281 * channel without a specific AID, by always answering null to such a request. 282 * The function without P2 as parameter is provided for backwards compatibility and will 283 * fall back to a select command with P2=00. 284 * 285 * @param aid the AID of the Applet to be selected on this channel, as a 286 * byte array. 287 * @param p2 the P2 parameter of the SELECT APDU executed on this channel. 288 * @throws IOException if there is a communication problem to the reader or 289 * the Secure Element. 290 * @throws IllegalStateException if the Secure Element is used after being 291 * closed. 292 * @throws IllegalArgumentException if the aid's length is not within 5 to 293 * 16 (inclusive). 294 * @throws SecurityException if the calling application cannot be granted 295 * access to this AID or the default Applet on this 296 * session. 297 * @throws NoSuchElementException if the AID on the Secure Element is not 298 * available or cannot be selected or a logical channel is already 299 * open to a non-multiselectable Applet. 300 * @throws UnsupportedOperationException if the given P2 parameter is not 301 * supported by the device. 302 * @return an instance of Channel. Null if the Secure Element is unable to 303 * provide a new logical channel. 304 */ openLogicalChannel(@ullable byte[] aid, @Nullable byte p2)305 public @Nullable Channel openLogicalChannel(@Nullable byte[] aid, @Nullable byte p2) 306 throws IOException { 307 if (!mService.isConnected()) { 308 throw new IllegalStateException("service not connected to system"); 309 } 310 synchronized (mLock) { 311 try { 312 ISecureElementChannel channel = mSession.openLogicalChannel( 313 aid, 314 p2, 315 mReader.getSEService().getListener()); 316 if (channel == null) { 317 return null; 318 } 319 return new Channel(mService, this, channel); 320 } catch (ServiceSpecificException e) { 321 if (e.errorCode == SEService.IO_ERROR) { 322 throw new IOException(e.getMessage()); 323 } else if (e.errorCode == SEService.NO_SUCH_ELEMENT_ERROR) { 324 throw new NoSuchElementException(e.getMessage()); 325 } else { 326 throw new IllegalStateException(e.getMessage()); 327 } 328 } catch (RemoteException e) { 329 throw new IllegalStateException(e.getMessage()); 330 } 331 } 332 } 333 334 /** 335 * This method is provided to ease the development of mobile application and for compliancy 336 * with existing applications. 337 * This method is equivalent to openLogicalChannel(aid, P2=0x00) 338 * 339 * @param aid the AID of the Applet to be selected on this channel, as a 340 * byte array. 341 * @throws IOException if there is a communication problem to the reader or 342 * the Secure Element. 343 * @throws IllegalStateException if the Secure Element is used after being 344 * closed. 345 * @throws IllegalArgumentException if the aid's length is not within 5 to 346 * 16 (inclusive). 347 * @throws SecurityException if the calling application cannot be granted 348 * access to this AID or the default Applet on this 349 * session. 350 * @throws NoSuchElementException if the AID on the Secure Element is not 351 * available or cannot be selected or a logical channel is already 352 * open to a non-multiselectable Applet. 353 * @throws UnsupportedOperationException if the given P2 parameter is not 354 * supported by the device. 355 * @return an instance of Channel. Null if the Secure Element is unable to 356 * provide a new logical channel. 357 */ openLogicalChannel(@ullable byte[] aid)358 public @Nullable Channel openLogicalChannel(@Nullable byte[] aid) throws IOException { 359 return openLogicalChannel(aid, (byte) 0x00); 360 } 361 } 362