Terminal.java revision a726b469d3c61c4dab20aefa75408d363431bf6a
1ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/* 2ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Copyright (C) 2017 The Android Open Source Project 3ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 4ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Licensed under the Apache License, Version 2.0 (the "License"); 5ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * you may not use this file except in compliance with the License. 6ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * You may obtain a copy of the License at 7ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 8ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * http://www.apache.org/licenses/LICENSE-2.0 9ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 10ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Unless required by applicable law or agreed to in writing, software 11ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * distributed under the License is distributed on an "AS IS" BASIS, 12ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * See the License for the specific language governing permissions and 14ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * limitations under the License. 15ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 16ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/* 17ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Copyright (c) 2015-2017, The Linux Foundation. 18ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 19ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 20ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/* 21ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Contributed by: Giesecke & Devrient GmbH. 22ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 23ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 24ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepackage com.android.se; 25ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 26ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.Context; 27ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.content.pm.PackageManager; 28ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.ISecureElement; 29ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.ISecureElementHalCallback; 30ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.LogicalChannelResponse; 31ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.hardware.secure_element.V1_0.SecureElementStatus; 3257ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Nakaimport android.os.Build; 33ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.RemoteException; 34ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.ServiceSpecificException; 35ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementListener; 36ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementReader; 37ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementSession; 38ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.SEService; 39ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.util.Log; 40ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 41ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.SecureElementService.SecureElementSession; 42ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.internal.ByteArrayConverter; 43ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.AccessControlEnforcer; 44ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.ChannelAccess; 45ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport java.io.IOException; 47ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.PrintWriter; 48ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.ArrayList; 49ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Collection; 50ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.HashMap; 51ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Map; 52b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Nakaimport java.util.MissingResourceException; 53ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.NoSuchElementException; 54ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 55ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/** 56ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Each Terminal represents a Secure Element. 57ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Communicates to the SE via SecureElement HAL. 58ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 59ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepublic class Terminal { 60ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 61ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final String mTag; 62ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>(); 63ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final Object mLock = new Object(); 64ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final String mName; 65ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean mIsConnected = false; 66ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private Context mContext; 67ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private boolean mDefaultApplicationSelectedOnBasicChannel = true; 68ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 6957ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Naka private static final boolean DEBUG = Build.IS_DEBUGGABLE; 70ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 71ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ISecureElement mSEHal; 72ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 73ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** For each Terminal there will be one AccessController object. */ 74ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private AccessControlEnforcer mAccessControlEnforcer; 75ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 76ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() { 77ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 78ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void onStateChange(boolean state) { 79ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 80ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "OnStateChange:" + state); 81ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mIsConnected = state; 82ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!state) { 83ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer != null) { 84ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.reset(); 85ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 86ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 87a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka try { 88a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka initializeAccessControl(); 89a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (Exception e) { 90a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // ignore 91a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } 92e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi synchronized (mLock) { 93e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi mDefaultApplicationSelectedOnBasicChannel = true; 94e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 95ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 96ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 97ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 98ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }; 99ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 100ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public Terminal(String name, Context context, ISecureElement seHal) { 101ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (seHal == null) { 102ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("ISecureElement cannot be null "); 103ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 104ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mContext = context; 105ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mName = name; 106ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mTag = "SecureElement-Terminal-" + getName(); 107ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal = seHal; 108ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 109ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue seHal.init(mHalCallback); 110ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 111ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 112ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 113ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 114ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ArrayList<Byte> byteArrayToArrayList(byte[] array) { 115ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<Byte> list = new ArrayList<Byte>(); 116ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (array == null) { 117ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return list; 118ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 119ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 120ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Byte b : array) { 121ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue list.add(b); 122ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 123ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return list; 124ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 125ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 126ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private byte[] arrayListToByteArray(ArrayList<Byte> list) { 127ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Byte[] byteArray = list.toArray(new Byte[list.size()]); 128ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int i = 0; 129ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] result = new byte[list.size()]; 130ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Byte b : byteArray) { 131ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue result[i++] = b.byteValue(); 132ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 133ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return result; 134ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 135ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 136ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 137ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Closes the given channel 138ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 139ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void closeChannel(Channel channel) { 140ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (channel == null) { 141ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return; 142ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 143fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi if (mIsConnected) { 144ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 145ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte status = mSEHal.closeChannel((byte) channel.getChannelNumber()); 146fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi /* For Basic Channels, errors are expected. 147fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi * Underlying implementations use this call as an indication when there 148fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi * aren't any users actively using the channel, and the chip can go 149fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi * into low power state. 150fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi */ 151fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) { 152ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error closing channel " + channel.getChannelNumber()); 153ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 154ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 155ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Exception in closeChannel() " + e); 156ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 157ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 158ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 159ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.remove(channel.getChannelNumber(), channel); 160ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mChannels.get(channel.getChannelNumber()) != null) { 161ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Removing channel failed"); 162ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 163ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 164ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 165ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 166ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 167ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * This method is called in SecureElementService:onDestroy to clean up 168ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * all open channels. 169ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 170ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public synchronized void closeChannels() { 171ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Collection<Channel> col = mChannels.values(); 172ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel[] channelList = col.toArray(new Channel[col.size()]); 173ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Channel channel : channelList) { 174ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue closeChannel(channel); 175ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 176ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 177ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 178ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public String getName() { 179ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mName; 180ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 181ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 182ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 183ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns the ATR of the Secure Element, or null if not available. 184ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 185ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public byte[] getAtr() { 186ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!mIsConnected) { 187ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 188ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 189ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 190ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 191ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<Byte> responseList = mSEHal.getAtr(); 192ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (responseList.isEmpty()) { 193ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 194ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 195ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return arrayListToByteArray(responseList); 196ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 197ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Exception in getAtr()" + e); 198ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 199ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 200ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 201ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 202ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 203ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Selects the default application on the basic channel. 204ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 205ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * If there is an exception selecting the default application, select 206ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * is performed with the default access control aid. 207ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 208ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void selectDefaultApplication() { 209ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 210ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue select(null); 211ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (NoSuchElementException e) { 212ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (getAccessControlEnforcer() != null) { 213ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 214ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue select(mAccessControlEnforcer.getDefaultAccessControlAid()); 215ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception ignore) { 216ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 217ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 2183878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } catch (Exception ignore) { 219ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 220ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 221ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 2223878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka private void select(byte[] aid) throws IOException { 223ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int commandSize = (aid == null ? 0 : aid.length) + 5; 224ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectCommand = new byte[commandSize]; 225ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[0] = 0x00; 226ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[1] = (byte) 0xA4; 227ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[2] = 0x04; 228ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[3] = 0x00; 229ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length != 0) { 230ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[4] = (byte) aid.length; 231ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(aid, 0, selectCommand, 5, aid.length); 232ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 233ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[4] = 0x00; 234ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 235ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = transmit(selectCommand); 236ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse.length < 2) { 237ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse = null; 238ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NoSuchElementException("Response length is too small"); 239ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 240e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi int sw1 = selectResponse[selectResponse.length - 2] & 0xFF; 241e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi int sw2 = selectResponse[selectResponse.length - 1] & 0xFF; 242ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (sw1 != 0x90 || sw2 != 0x00) { 243ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse = null; 244ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NoSuchElementException("Status word is incorrect"); 245ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 246ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 247ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 248ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 249ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a Basic Channel with the given AID and P2 paramters 250ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 251ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2, 2525091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka ISecureElementListener listener, String packageName, int pid) throws IOException, 2535091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka NoSuchElementException { 254ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length == 0) { 255ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue aid = null; 256ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 257ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("AID out of range"); 2583e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } else if (!mIsConnected) { 2593e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("Secure Element is not connected"); 260ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 261ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 262ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.w(mTag, "Enable access control on basic channel for " + packageName); 263b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka ChannelAccess channelAccess; 264b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka try { 265a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka channelAccess = setUpChannelAccess(aid, packageName, pid); 266b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } catch (MissingResourceException e) { 267b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka return null; 268b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } 269ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 270ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 271ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mChannels.get(0) != null) { 272ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "basic channel in use"); 273ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 274ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 275ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) { 276ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "default application is not selected"); 277ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 278ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 279ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 280ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<byte[]> responseList = new ArrayList<byte[]>(); 281ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 2823e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 2833e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka try { 2843e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2, 2853e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka new ISecureElement.openBasicChannelCallback() { 2863e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka @Override 2873e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public void onValues(ArrayList<Byte> responseObject, byte halStatus) { 2883e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka status[0] = halStatus; 2893e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka responseList.add(arrayListToByteArray(responseObject)); 2903e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka return; 2913e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 2923e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka }); 2933e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (RemoteException e) { 2943e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException(e.getMessage()); 2953e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 2963e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 297ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = responseList.get(0); 298ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 299ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 300ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 301ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new UnsupportedOperationException("OpenBasicChannel() failed"); 302ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.IOERROR) { 3033e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("OpenBasicChannel() failed"); 304e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 3055091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka throw new NoSuchElementException("OpenBasicChannel() failed"); 306ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 307e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi 308ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel basicChannel = new Channel(session, this, 0, selectResponse, 309ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue listener); 310ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.setChannelAccess(channelAccess); 311ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 312ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectedAid = getSelectedAid(selectResponse); 313ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectedAid != null) { 314ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.hasSelectedAid(true, selectedAid); 315ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 316ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.hasSelectedAid((aid != null) ? true : false, aid); 317ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 318ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 319ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null) { 320ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mDefaultApplicationSelectedOnBasicChannel = false; 321ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 322ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.put(0, basicChannel); 323ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return basicChannel; 324ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 325ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 326ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 327ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 328ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a logical Channel without Channel Access initialization. 329ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 3305091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException, 3315091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka NoSuchElementException { 332ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0); 333ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 334ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 335ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 336ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a logical Channel with AID. 337ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 3383e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, 3395091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka ISecureElementListener listener, String packageName, int pid) throws IOException, 3405091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka NoSuchElementException { 341ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length == 0) { 342ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue aid = null; 343ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 344ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("AID out of range"); 345ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (!mIsConnected) { 3463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("Secure Element is not connected"); 347ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 348ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 349ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = null; 350ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (packageName != null) { 351ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.w(mTag, "Enable access control on logical channel for " + packageName); 352b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka try { 353a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka channelAccess = setUpChannelAccess(aid, packageName, pid); 354b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } catch (MissingResourceException e) { 355b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka return null; 356b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } 357ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 358ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 359ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 360ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 361ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 3623e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 3633e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka try { 3643e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2, 3653e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka new ISecureElement.openLogicalChannelCallback() { 3663e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka @Override 3673e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public void onValues(LogicalChannelResponse response, byte halStatus) { 3683e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka status[0] = halStatus; 3693e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka responseArray[0] = response; 3703e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka return; 3713e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 3723e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka }); 3733e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (RemoteException e) { 3743e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException(e.getMessage()); 3753e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 3763e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 377ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 378ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 379ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 380ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new UnsupportedOperationException("OpenLogicalChannel() failed"); 381ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.IOERROR) { 3823e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("OpenLogicalChannel() failed"); 383ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 3845091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka throw new NoSuchElementException("OpenLogicalChannel() failed"); 385ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 386ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) { 387ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 388ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 389ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int channelNumber = responseArray[0].channelNumber; 390ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse); 391ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel logicalChannel = new Channel(session, this, channelNumber, 392ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse, listener); 393ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.setChannelAccess(channelAccess); 394ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 395ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectedAid = selectedAid = getSelectedAid(selectResponse); 396ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectedAid != null) { 397ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.hasSelectedAid(true, selectedAid); 398ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 399ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.hasSelectedAid((aid != null) ? true : false, aid); 400ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 401ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 402ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.put(channelNumber, logicalChannel); 403ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return logicalChannel; 404ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 405ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 406ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 407ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 408ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns true if the given AID can be selected on the Terminal 409ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 410ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isAidSelectable(byte[] aid) { 411ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid == null) { 412ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NullPointerException("aid must not be null"); 413ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (!mIsConnected) { 414ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Secure Element is not connected"); 415ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 416ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 417ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 418ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 419ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 420ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 421ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 422ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00, 423ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue new ISecureElement.openLogicalChannelCallback() { 424ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 425ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void onValues(LogicalChannelResponse response, byte halStatus) { 426ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue status[0] = halStatus; 427ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue responseArray[0] = response; 428ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return; 429ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 430ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }); 431ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.SUCCESS) { 432ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal.closeChannel(responseArray[0].channelNumber); 433ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return true; 434ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 435ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 436ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 437ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error in isAidSelectable() returning false" + e); 438ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 439ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 440ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 441ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 442ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 443ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 444ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Transmits the specified command and returns the response. 445ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 446ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * @param cmd the command APDU to be transmitted. 447ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * @return the response received. 448ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 4493878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka public byte[] transmit(byte[] cmd) throws IOException { 450ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!mIsConnected) { 451ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Secure Element is not connected"); 4523878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException("Secure Element is not connected"); 453ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 454ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 455ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] rsp = transmitInternal(cmd); 456ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int sw1 = rsp[rsp.length - 2] & 0xFF; 457ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int sw2 = rsp[rsp.length - 1] & 0xFF; 458ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 459ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (sw1 == 0x6C) { 460ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue cmd[cmd.length - 1] = rsp[rsp.length - 1]; 461ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue rsp = transmitInternal(cmd); 462ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (sw1 == 0x61) { 463ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue do { 464ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] getResponseCmd = new byte[]{ 465ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2 466ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }; 467ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] tmp = transmitInternal(getResponseCmd); 468ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] aux = rsp; 469ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue rsp = new byte[aux.length + tmp.length - 2]; 470ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(aux, 0, rsp, 0, aux.length - 2); 471ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length); 472ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue sw1 = rsp[rsp.length - 2] & 0xFF; 473ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue sw2 = rsp[rsp.length - 1] & 0xFF; 474ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } while (sw1 == 0x61); 475ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 476ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return rsp; 477ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 478ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 4793878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka private byte[] transmitInternal(byte[] cmd) throws IOException { 4803878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka ArrayList<Byte> response; 4813878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka try { 4823878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka response = mSEHal.transmit(byteArrayToArrayList(cmd)); 4833878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } catch (RemoteException e) { 4843878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException(e.getMessage()); 4853878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } 486ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (response.isEmpty()) { 4873878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException("Error in transmit()"); 488ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 489ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] rsp = arrayListToByteArray(response); 49057ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Naka if (DEBUG) { 491ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd)); 492ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp)); 493ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 494ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return rsp; 495ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 496ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 497ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 498ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Checks if the application is authorized to receive the transaction event. 499ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 500a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid, 501a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka String[] packageNames) { 502a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka boolean checkRefreshTag = true; 503ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 504a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka try { 505a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka initializeAccessControl(); 506a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // Just finished to initialize the access control enforcer. 507a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // It is too much to check the refresh tag in this case. 508a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka checkRefreshTag = false; 509a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (Exception e) { 510a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 511a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka return null; 512a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } 513ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 514ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setPackageManager(packageManager); 515ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 516ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 517ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 518ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames, 519ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue checkRefreshTag); 520ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception e) { 521ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 522ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 523ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 524ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 525ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 526ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 527ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 528ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns true if the Secure Element is present 529ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 530ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isSecureElementPresent() { 531ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 532ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mSEHal.isCardPresent(); 533ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 534ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error in isSecureElementPresent() " + e); 535ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 536ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 537ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 538ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 539ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 540ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Initialize the Access Control and set up the channel access. 541ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 542a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid) 543a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka throws IOException, MissingResourceException { 544a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka boolean checkRefreshTag = true; 545ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 546ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue initializeAccessControl(); 547a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // Just finished to initialize the access control enforcer. 548a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // It is too much to check the refresh tag in this case. 549a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka checkRefreshTag = false; 550ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 551ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); 552ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 553ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 554ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 555ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = 556ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setUpChannelAccess(aid, packageName, 557ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue checkRefreshTag); 558ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue channelAccess.setCallingPid(pid); 559ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return channelAccess; 560a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (IOException | MissingResourceException e) { 561b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka throw e; 562ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception e) { 563ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new SecurityException("Exception in setUpChannelAccess()" + e); 564ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 565ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 566ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 567ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 568ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 569ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Initializes the Access Control for this Terminal 570ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 571a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka private synchronized void initializeAccessControl() throws IOException, 572a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka MissingResourceException { 573ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 574ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 575ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer = new AccessControlEnforcer(this); 576ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 577a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka try { 578a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka mAccessControlEnforcer.initialize(); 579a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (IOException | MissingResourceException e) { 580a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // Retrieving access rules failed because of an IO error happened between 581a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // the terminal and the secure element or the lack of a logical channel available. 582a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // It might be a temporary failure, so the terminal shall attempt to cache 583a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // the access rules again later. 584a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka mAccessControlEnforcer = null; 585a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka throw e; 586a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } 587ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 588ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 589ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 590ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public AccessControlEnforcer getAccessControlEnforcer() { 591ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mAccessControlEnforcer; 592ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 593ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 594ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private byte[] getSelectedAid(byte[] selectResponse) { 595ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectedAid = null; 596ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if ((selectResponse != null && selectResponse.length >= 2) 597ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue && (selectResponse.length == (selectResponse[1] + 4)) 598ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue && // header(2) + SW(2) 599ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ((selectResponse[0] == (byte) 0x62) 600ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue || (selectResponse[0] == (byte) 0x6F))) { // FCP or FCI template 601ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int nextTlv = 2; 602ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue while (selectResponse.length > nextTlv) { 603ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse[nextTlv] == (byte) 0x84) { 604ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse.length >= (nextTlv + selectResponse[nextTlv + 1] + 2)) { 605ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectedAid = new byte[selectResponse[nextTlv + 1]]; 606ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy( 607ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse, nextTlv + 2, selectedAid, 0, 608ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse[nextTlv + 1]); 609ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 610ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue break; 611ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 612ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue nextTlv += 2 + selectResponse[nextTlv + 1]; 613ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 614ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 615ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 616ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return selectedAid; 617ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 618ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 619ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** Dump data for debug purpose . */ 620ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void dump(PrintWriter writer) { 621ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName); 622ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 623ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 624ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("mIsConnected:" + mIsConnected); 625ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 626ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 627ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /* Dump the list of currunlty openned channels */ 628ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("List of open channels:"); 629ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 630ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Channel channel : mChannels.values()) { 631ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("channel " + channel.getChannelNumber() + ": "); 632ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("package: " + channel.getChannelAccess().getPackageName()); 633ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("pid: " + channel.getChannelAccess().getCallingPid()); 634ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("aid selected: " + channel.hasSelectedAid()); 635ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("basic channel: " + channel.isBasicChannel()); 636ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 637ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 638ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 639ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 640ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /* Dump ACE data */ 641ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer != null) { 642ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.dump(writer); 643ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 644ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 645ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 646ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue // Implementation of the SecureElement Reader interface according to OMAPI. 647ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue final class SecureElementReader extends ISecureElementReader.Stub { 648ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 649ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final SecureElementService mService; 650ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final ArrayList<SecureElementSession> mSessions = 651ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue new ArrayList<SecureElementSession>(); 652ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 653ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue SecureElementReader(SecureElementService service) { 654ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mService = service; 655ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 656ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 657ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public byte[] getAtr() { 658ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this.getAtr(); 659ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 660ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 661ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 662ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isSecureElementPresent() throws RemoteException { 663ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this.isSecureElementPresent(); 664ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 665ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 666ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 667ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void closeSessions() { 668ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 669ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue while (mSessions.size() > 0) { 670ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 671ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.get(0).close(); 672ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception ignore) { 673ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 674ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 675ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.clear(); 676ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 677ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 678ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 679ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void removeSession(SecureElementSession session) { 680ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (session == null) { 681ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NullPointerException("session is null"); 682ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 683ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.remove(session); 684e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi synchronized (mLock) { 685e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi if (mSessions.size() == 0) { 686e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi mDefaultApplicationSelectedOnBasicChannel = true; 687e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 688e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 689ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 690ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 691ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 692ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public ISecureElementSession openSession() throws RemoteException { 693ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!isSecureElementPresent()) { 694ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new ServiceSpecificException(SEService.IO_ERROR, 695ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue "Secure Element is not present."); 696ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 697ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 698ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 699ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue SecureElementSession session = mService.new SecureElementSession(this); 700ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.add(session); 701ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return session; 702ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 703ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 704ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 705ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Terminal getTerminal() { 706ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this; 707ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 708ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 709ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue} 710