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) 2015-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 33 /** 34 * Instances of this class represent an ISO/IEC 7816-4 channel opened to a 35 * Secure Element. It can be either a logical channel or the basic channel. They 36 * can be used to send APDUs to the secure element. Channels are opened by 37 * calling the Session.openBasicChannel(byte[]) or 38 * Session.openLogicalChannel(byte[]) methods. 39 * 40 * @see <a href="http://globalplatform.org">GlobalPlatform Open Mobile API</a> 41 */ 42 public final class Channel implements java.nio.channels.Channel { 43 44 private static final String TAG = "OMAPI.Channel"; 45 private Session mSession; 46 private final ISecureElementChannel mChannel; 47 private final SEService mService; 48 private final Object mLock = new Object(); 49 Channel(@onNull SEService service, @NonNull Session session, @NonNull ISecureElementChannel channel)50 Channel(@NonNull SEService service, @NonNull Session session, 51 @NonNull ISecureElementChannel channel) { 52 if (service == null || session == null || channel == null) { 53 throw new IllegalArgumentException("Parameters cannot be null"); 54 } 55 mService = service; 56 mSession = session; 57 mChannel = channel; 58 } 59 60 /** 61 * Closes this channel to the Secure Element. If the method is called when 62 * the channel is already closed, this method will be ignored. The close() 63 * method shall wait for completion of any pending transmit(byte[] command) 64 * before closing the channel. 65 */ close()66 public void close() { 67 if (isOpen()) { 68 synchronized (mLock) { 69 try { 70 mChannel.close(); 71 } catch (Exception e) { 72 Log.e(TAG, "Error closing channel", e); 73 } 74 } 75 } 76 } 77 78 /** 79 * Tells if this channel is open. 80 * 81 * @return <code>false</code> if the channel is closed or in case of an error. 82 * <code>true</code> otherwise. 83 */ isOpen()84 public boolean isOpen() { 85 if (!mService.isConnected()) { 86 Log.e(TAG, "service not connected to system"); 87 return false; 88 } 89 try { 90 return !mChannel.isClosed(); 91 } catch (RemoteException e) { 92 Log.e(TAG, "Exception in isClosed()"); 93 return false; 94 } 95 } 96 97 /** 98 * Returns a boolean telling if this channel is the basic channel. 99 * 100 * @return <code>true</code> if this channel is a basic channel. <code>false</code> if 101 * this channel is a logical channel. 102 */ isBasicChannel()103 public boolean isBasicChannel() { 104 if (!mService.isConnected()) { 105 throw new IllegalStateException("service not connected to system"); 106 } 107 try { 108 return mChannel.isBasicChannel(); 109 } catch (RemoteException e) { 110 throw new IllegalStateException(e.getMessage()); 111 } 112 } 113 114 /** 115 * Transmit an APDU command (as per ISO/IEC 7816-4) to the Secure Element. The 116 * underlying layers generate as many TPDUs as necessary to transport this APDU. The 117 * API shall ensure that all available data returned from Secure Element, including 118 * concatenated responses, are retrieved and made available to the calling application. If a 119 * warning status code is received the API wont check for further response data but will 120 * return all data received so far and the warning status code.<br> 121 * The transport part is invisible from the application. The generated response is the 122 * response of the APDU which means that all protocols related responses are handled 123 * inside the API or the underlying implementation.<br> 124 * The transmit method shall support extended length APDU commands independently of 125 * the coding within the ATR.<br> 126 * For status word '61 XX' the API or underlying implementation shall issue a GET 127 * RESPONSE command as specified by ISO 7816-4 standard with LE=XX; for the status 128 * word '6C XX', the API or underlying implementation shall reissue the input command 129 * with LE=XX. For other status words, the API (or underlying implementation) shall return 130 * the complete response including data and status word to the device application. The API 131 * (or underlying implementation) shall not handle internally the received status words. The 132 * channel shall not be closed even if the Secure Element answered with an error code. 133 * The system ensures the synchronization between all the concurrent calls to this method, 134 * and that only one APDU will be sent at a time, irrespective of the number of TPDUs that 135 * might be required to transport it to the SE. The entire APDU communication to this SE is 136 * locked to the APDU.<br> 137 * The channel information in the class byte in the APDU will be ignored. The system will 138 * add any required information to ensure the APDU is transported on this channel. 139 * The only restrictions on the set of commands that can be sent is defined below, the API 140 * implementation shall be able to send all other commands: <br> 141 * <ul> 142 * <li>MANAGE_CHANNEL commands are not allowed.</li> 143 * <li>SELECT by DF Name (p1=04) are not allowed.</li> 144 * <li>CLA bytes with channel numbers are de-masked.</li> 145 * </ul> 146 * 147 * @param command the APDU command to be transmitted, as a byte array. 148 * 149 * @return the response received, as a byte array. The returned byte array contains the data 150 * bytes in the following order: 151 * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>] 152 * 153 * @throws IOException if there is a communication problem to the reader or the Secure Element. 154 * @throws IllegalStateException if the channel is used after being closed. 155 * @throws IllegalArgumentException if the command byte array is less than 4 bytes long. 156 * @throws IllegalArgumentException if Lc byte is inconsistent with length of the byte array. 157 * @throws IllegalArgumentException if CLA byte is invalid according to [2] (0xff). 158 * @throws IllegalArgumentException if INS byte is invalid according to [2] (0x6x or 0x9x). 159 * @throws SecurityException if the command is filtered by the security policy. 160 * @throws NullPointerException if command is NULL. 161 */ transmit(@onNull byte[] command)162 public @NonNull byte[] transmit(@NonNull byte[] command) throws IOException { 163 if (!mService.isConnected()) { 164 throw new IllegalStateException("service not connected to system"); 165 } 166 synchronized (mLock) { 167 try { 168 byte[] response = mChannel.transmit(command); 169 if (response == null) { 170 throw new IOException("Error in communicating with Secure Element"); 171 } 172 return response; 173 } catch (ServiceSpecificException e) { 174 throw new IOException(e.getMessage()); 175 } catch (RemoteException e) { 176 throw new IllegalStateException(e.getMessage()); 177 } 178 } 179 } 180 181 /** 182 * Get the session that has opened this channel. 183 * 184 * @return the session object this channel is bound to. 185 */ getSession()186 public @NonNull Session getSession() { 187 return mSession; 188 } 189 190 /** 191 * Returns the data as received from the application select command inclusively the status word 192 * received at applet selection. 193 * The returned byte array contains the data bytes in the following order: 194 * [<first data byte>, ..., <last data byte>, <sw1>, <sw2>] 195 * @return The data as returned by the application select command inclusively the status word. 196 * Only the status word if the application select command has no returned data. 197 * Returns null if an application select command has not been performed or the selection 198 * response can not be retrieved by the reader implementation. 199 */ getSelectResponse()200 public @Nullable byte[] getSelectResponse() { 201 if (!mService.isConnected()) { 202 throw new IllegalStateException("service not connected to system"); 203 } 204 205 byte[] response; 206 try { 207 response = mChannel.getSelectResponse(); 208 } catch (RemoteException e) { 209 throw new IllegalStateException(e.getMessage()); 210 } 211 212 if (response != null && response.length == 0) { 213 response = null; 214 } 215 return response; 216 } 217 218 /** 219 * Performs a selection of the next Applet on this channel that matches to the partial AID 220 * specified in the openBasicChannel(byte[] aid) or openLogicalChannel(byte[] aid) method. 221 * This mechanism can be used by a device application to iterate through all Applets 222 * matching to the same partial AID. 223 * If selectNext() returns true a new Applet was successfully selected on this channel. 224 * If no further Applet exists with matches to the partial AID this method returns false 225 * and the already selected Applet stays selected. <br> 226 * 227 * Since the API cannot distinguish between a partial and full AID the API shall rely on the 228 * response of the Secure Element for the return value of this method. <br> 229 * The implementation of the underlying SELECT command within this method shall use 230 * the same values as the corresponding openBasicChannel(byte[] aid) or 231 * openLogicalChannel(byte[] aid) command with the option: <br> 232 * P2='02' (Next occurrence) <br> 233 * The select response stored in the Channel object shall be updated with the APDU 234 * response of the SELECT command. 235 236 * @return <code>true</code> if new Applet was selected on this channel. 237 <code>false</code> he already selected Applet stays selected on this channel. 238 * 239 * @throws IOException if there is a communication problem to the reader or the Secure Element. 240 * @throws IllegalStateException if the channel is used after being closed. 241 * @throws UnsupportedOperationException if this operation is not supported by the card. 242 */ selectNext()243 public boolean selectNext() throws IOException { 244 if (!mService.isConnected()) { 245 throw new IllegalStateException("service not connected to system"); 246 } 247 try { 248 synchronized (mLock) { 249 return mChannel.selectNext(); 250 } 251 } catch (ServiceSpecificException e) { 252 throw new IOException(e.getMessage()); 253 } catch (RemoteException e) { 254 throw new IllegalStateException(e.getMessage()); 255 } 256 } 257 } 258