Terminal.java revision 3878ce67ae4810258882c749f4dcbf508e6ad9ed
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; 32ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.RemoteException; 33ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.ServiceSpecificException; 34ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementListener; 35ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementReader; 36ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementSession; 37ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.SEService; 38ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.util.Log; 39ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 40ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.SecureElementService.SecureElementSession; 41ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.internal.ByteArrayConverter; 42ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.AccessControlEnforcer; 43ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.ChannelAccess; 44ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 453e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport java.io.IOException; 46ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.PrintWriter; 47ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.ArrayList; 48ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Collection; 49ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.HashMap; 50ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Map; 51ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.NoSuchElementException; 52ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 53ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/** 54ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Each Terminal represents a Secure Element. 55ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Communicates to the SE via SecureElement HAL. 56ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 57ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepublic class Terminal { 58ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 59ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final String mTag; 60ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>(); 61ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final Object mLock = new Object(); 62ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final String mName; 63ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean mIsConnected = false; 64ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private Context mContext; 65ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private boolean mDefaultApplicationSelectedOnBasicChannel = true; 66ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 67ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private boolean mDebug = true; 68ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 69ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ISecureElement mSEHal; 70ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 71ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** For each Terminal there will be one AccessController object. */ 72ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private AccessControlEnforcer mAccessControlEnforcer; 73ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 74ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() { 75ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 76ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void onStateChange(boolean state) { 77ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 78ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "OnStateChange:" + state); 79ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mIsConnected = state; 80ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!state) { 81ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer != null) { 82ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.reset(); 83ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 84ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 85ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue initializeAccessControl(); 86e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi synchronized (mLock) { 87e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi mDefaultApplicationSelectedOnBasicChannel = true; 88e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 89ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 90ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 91ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 92ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }; 93ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 94ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public Terminal(String name, Context context, ISecureElement seHal) { 95ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (seHal == null) { 96ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("ISecureElement cannot be null "); 97ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 98ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mContext = context; 99ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mName = name; 100ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mTag = "SecureElement-Terminal-" + getName(); 101ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal = seHal; 102ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 103ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue seHal.init(mHalCallback); 104ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 105ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 106ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 107ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 108ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ArrayList<Byte> byteArrayToArrayList(byte[] array) { 109ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<Byte> list = new ArrayList<Byte>(); 110ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (array == null) { 111ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return list; 112ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 113ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 114ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Byte b : array) { 115ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue list.add(b); 116ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 117ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return list; 118ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 119ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 120ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private byte[] arrayListToByteArray(ArrayList<Byte> list) { 121ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Byte[] byteArray = list.toArray(new Byte[list.size()]); 122ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int i = 0; 123ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] result = new byte[list.size()]; 124ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Byte b : byteArray) { 125ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue result[i++] = b.byteValue(); 126ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 127ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return result; 128ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 129ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 130ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 131ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Closes the given channel 132ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 133ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void closeChannel(Channel channel) { 134ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (channel == null) { 135ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return; 136ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 137ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mIsConnected && !channel.isBasicChannel()) { 138ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 139ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte status = mSEHal.closeChannel((byte) channel.getChannelNumber()); 140ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status != SecureElementStatus.SUCCESS) { 141ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error closing channel " + channel.getChannelNumber()); 142ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 143ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 144ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Exception in closeChannel() " + e); 145ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 146ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 147ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 148ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.remove(channel.getChannelNumber(), channel); 149ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mChannels.get(channel.getChannelNumber()) != null) { 150ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Removing channel failed"); 151ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 152ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 153ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 154ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 155ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 156ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * This method is called in SecureElementService:onDestroy to clean up 157ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * all open channels. 158ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 159ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public synchronized void closeChannels() { 160ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Collection<Channel> col = mChannels.values(); 161ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel[] channelList = col.toArray(new Channel[col.size()]); 162ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Channel channel : channelList) { 163ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue closeChannel(channel); 164ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 165ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 166ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 167ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public String getName() { 168ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mName; 169ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 170ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 171ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 172ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns the ATR of the Secure Element, or null if not available. 173ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 174ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public byte[] getAtr() { 175ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!mIsConnected) { 176ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 177ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 178ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 179ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 180ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<Byte> responseList = mSEHal.getAtr(); 181ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (responseList.isEmpty()) { 182ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 183ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 184ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return arrayListToByteArray(responseList); 185ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 186ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Exception in getAtr()" + e); 187ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 188ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 189ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 190ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 191ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 192ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Selects the default application on the basic channel. 193ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 194ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * If there is an exception selecting the default application, select 195ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * is performed with the default access control aid. 196ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 197ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void selectDefaultApplication() { 198ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 199ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue select(null); 200ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (NoSuchElementException e) { 201ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (getAccessControlEnforcer() != null) { 202ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 203ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue select(mAccessControlEnforcer.getDefaultAccessControlAid()); 204ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception ignore) { 205ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 206ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 2073878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } catch (Exception ignore) { 208ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 209ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 210ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 2113878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka private void select(byte[] aid) throws IOException { 212ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int commandSize = (aid == null ? 0 : aid.length) + 5; 213ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectCommand = new byte[commandSize]; 214ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[0] = 0x00; 215ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[1] = (byte) 0xA4; 216ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[2] = 0x04; 217ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[3] = 0x00; 218ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length != 0) { 219ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[4] = (byte) aid.length; 220ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(aid, 0, selectCommand, 5, aid.length); 221ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 222ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[4] = 0x00; 223ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 224ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = transmit(selectCommand); 225ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse.length < 2) { 226ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse = null; 227ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NoSuchElementException("Response length is too small"); 228ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 229e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi int sw1 = selectResponse[selectResponse.length - 2] & 0xFF; 230e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi int sw2 = selectResponse[selectResponse.length - 1] & 0xFF; 231ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (sw1 != 0x90 || sw2 != 0x00) { 232ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse = null; 233ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NoSuchElementException("Status word is incorrect"); 234ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 235ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 236ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 237ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 238ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a Basic Channel with the given AID and P2 paramters 239ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 240ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2, 2413e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka ISecureElementListener listener, String packageName, int pid) throws IOException { 242ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length == 0) { 243ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue aid = null; 244ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 245ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("AID out of range"); 2463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } else if (!mIsConnected) { 2473e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("Secure Element is not connected"); 248ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 249ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 250ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.w(mTag, "Enable access control on basic channel for " + packageName); 251ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = setUpChannelAccess(aid, packageName, true, pid); 252ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 253ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 254ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mChannels.get(0) != null) { 255ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "basic channel in use"); 256ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 257ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 258ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) { 259ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "default application is not selected"); 260ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 261ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 262ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 263ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<byte[]> responseList = new ArrayList<byte[]>(); 264ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 2653e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 2663e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka try { 2673e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2, 2683e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka new ISecureElement.openBasicChannelCallback() { 2693e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka @Override 2703e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public void onValues(ArrayList<Byte> responseObject, byte halStatus) { 2713e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka status[0] = halStatus; 2723e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka responseList.add(arrayListToByteArray(responseObject)); 2733e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka return; 2743e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 2753e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka }); 2763e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (RemoteException e) { 2773e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException(e.getMessage()); 2783e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 2793e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 280ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = responseList.get(0); 281ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 282ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 283ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 284ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new UnsupportedOperationException("OpenBasicChannel() failed"); 285ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.IOERROR) { 2863e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("OpenBasicChannel() failed"); 287e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 288e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, 289e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi "OpenBasicChannel() failed"); 290ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 291e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi 292ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel basicChannel = new Channel(session, this, 0, selectResponse, 293ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue listener); 294ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.setChannelAccess(channelAccess); 295ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 296ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectedAid = getSelectedAid(selectResponse); 297ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectedAid != null) { 298ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.hasSelectedAid(true, selectedAid); 299ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 300ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.hasSelectedAid((aid != null) ? true : false, aid); 301ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 302ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 303ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null) { 304ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mDefaultApplicationSelectedOnBasicChannel = false; 305ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 306ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.put(0, basicChannel); 307ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return basicChannel; 308ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 309ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 310ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 311ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 312ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a logical Channel without Channel Access initialization. 313ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 3143e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException { 315ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0); 316ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 317ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 318ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 319ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a logical Channel with AID. 320ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 3213e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, 3223e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka ISecureElementListener listener, String packageName, int pid) throws IOException { 323ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length == 0) { 324ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue aid = null; 325ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 326ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("AID out of range"); 327ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (!mIsConnected) { 3283e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("Secure Element is not connected"); 329ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 330ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 331ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = null; 332ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (packageName != null) { 333ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.w(mTag, "Enable access control on logical channel for " + packageName); 334ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue channelAccess = setUpChannelAccess(aid, packageName, true, pid); 335ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 336ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 337ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 338ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 339ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 3403e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 3413e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka try { 3423e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2, 3433e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka new ISecureElement.openLogicalChannelCallback() { 3443e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka @Override 3453e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public void onValues(LogicalChannelResponse response, byte halStatus) { 3463e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka status[0] = halStatus; 3473e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka responseArray[0] = response; 3483e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka return; 3493e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 3503e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka }); 3513e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (RemoteException e) { 3523e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException(e.getMessage()); 3533e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 3543e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 355ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 356ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 357ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 358ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new UnsupportedOperationException("OpenLogicalChannel() failed"); 359ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.IOERROR) { 3603e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("OpenLogicalChannel() failed"); 361ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 362ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, 363ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue "OpenLogicalChannel() failed"); 364ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 365ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) { 366ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 367ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 368ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int channelNumber = responseArray[0].channelNumber; 369ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse); 370ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel logicalChannel = new Channel(session, this, channelNumber, 371ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse, listener); 372ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.setChannelAccess(channelAccess); 373ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 374ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectedAid = selectedAid = getSelectedAid(selectResponse); 375ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectedAid != null) { 376ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.hasSelectedAid(true, selectedAid); 377ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 378ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.hasSelectedAid((aid != null) ? true : false, aid); 379ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 380ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 381ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.put(channelNumber, logicalChannel); 382ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return logicalChannel; 383ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 384ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 385ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 386ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 387ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns true if the given AID can be selected on the Terminal 388ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 389ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isAidSelectable(byte[] aid) { 390ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid == null) { 391ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NullPointerException("aid must not be null"); 392ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (!mIsConnected) { 393ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Secure Element is not connected"); 394ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 395ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 396ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 397ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 398ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 399ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 400ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 401ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00, 402ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue new ISecureElement.openLogicalChannelCallback() { 403ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 404ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void onValues(LogicalChannelResponse response, byte halStatus) { 405ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue status[0] = halStatus; 406ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue responseArray[0] = response; 407ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return; 408ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 409ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }); 410ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.SUCCESS) { 411ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal.closeChannel(responseArray[0].channelNumber); 412ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return true; 413ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 414ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 415ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 416ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error in isAidSelectable() returning false" + e); 417ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 418ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 419ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 420ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 421ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 422ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 423ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Transmits the specified command and returns the response. 424ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 425ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * @param cmd the command APDU to be transmitted. 426ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * @return the response received. 427ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 4283878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka public byte[] transmit(byte[] cmd) throws IOException { 429ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!mIsConnected) { 430ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Secure Element is not connected"); 4313878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException("Secure Element is not connected"); 432ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 433ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 434ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] rsp = transmitInternal(cmd); 435ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int sw1 = rsp[rsp.length - 2] & 0xFF; 436ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int sw2 = rsp[rsp.length - 1] & 0xFF; 437ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 438ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (sw1 == 0x6C) { 439ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue cmd[cmd.length - 1] = rsp[rsp.length - 1]; 440ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue rsp = transmitInternal(cmd); 441ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (sw1 == 0x61) { 442ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue do { 443ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] getResponseCmd = new byte[]{ 444ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2 445ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }; 446ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] tmp = transmitInternal(getResponseCmd); 447ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] aux = rsp; 448ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue rsp = new byte[aux.length + tmp.length - 2]; 449ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(aux, 0, rsp, 0, aux.length - 2); 450ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length); 451ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue sw1 = rsp[rsp.length - 2] & 0xFF; 452ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue sw2 = rsp[rsp.length - 1] & 0xFF; 453ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } while (sw1 == 0x61); 454ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 455ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return rsp; 456ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 457ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 4583878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka private byte[] transmitInternal(byte[] cmd) throws IOException { 4593878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka ArrayList<Byte> response; 4603878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka try { 4613878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka response = mSEHal.transmit(byteArrayToArrayList(cmd)); 4623878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } catch (RemoteException e) { 4633878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException(e.getMessage()); 4643878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } 465ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (response.isEmpty()) { 4663878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException("Error in transmit()"); 467ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 468ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] rsp = arrayListToByteArray(response); 469ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mDebug) { 470ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd)); 471ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp)); 472ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 473ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return rsp; 474ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 475ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 476ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 477ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Checks if the application is authorized to receive the transaction event. 478ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 479ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean[] isNfcEventAllowed( 480ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue PackageManager packageManager, 481ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] aid, 482ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue String[] packageNames, 483ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue boolean checkRefreshTag) { 484ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 485ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Access Control Enforcer not properly set up"); 486ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue initializeAccessControl(); 487ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 488ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setPackageManager(packageManager); 489ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 490ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 491ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 492ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames, 493ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue checkRefreshTag); 494ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception e) { 495ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 496ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 497ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 498ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 499ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 500ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 501ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 502ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns true if the Secure Element is present 503ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 504ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isSecureElementPresent() { 505ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 506ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mSEHal.isCardPresent(); 507ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 508ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error in isSecureElementPresent() " + e); 509ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 510ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 511ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 512ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 513ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 514ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Initialize the Access Control and set up the channel access. 515ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 5163e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, 5173e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka boolean checkRefreshTag, int pid) throws IOException { 518ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 519ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Access Control Enforcer not properly set up"); 520ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue initializeAccessControl(); 521ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 522ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); 523ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 524ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 525ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 526ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = 527ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setUpChannelAccess(aid, packageName, 528ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue checkRefreshTag); 529ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue channelAccess.setCallingPid(pid); 530ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return channelAccess; 5313e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (IOException e) { 5323e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw e; 533ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception e) { 534ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new SecurityException("Exception in setUpChannelAccess()" + e); 535ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 536ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 537ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 538ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 539ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 540ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Initializes the Access Control for this Terminal 541ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 542ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private synchronized void initializeAccessControl() { 543ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 544ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 545ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer = new AccessControlEnforcer(this); 546ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 547ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.initialize(true); 548ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 549ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 550ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 551ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public AccessControlEnforcer getAccessControlEnforcer() { 552ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mAccessControlEnforcer; 553ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 554ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 555ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private byte[] getSelectedAid(byte[] selectResponse) { 556ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectedAid = null; 557ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if ((selectResponse != null && selectResponse.length >= 2) 558ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue && (selectResponse.length == (selectResponse[1] + 4)) 559ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue && // header(2) + SW(2) 560ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ((selectResponse[0] == (byte) 0x62) 561ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue || (selectResponse[0] == (byte) 0x6F))) { // FCP or FCI template 562ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int nextTlv = 2; 563ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue while (selectResponse.length > nextTlv) { 564ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse[nextTlv] == (byte) 0x84) { 565ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse.length >= (nextTlv + selectResponse[nextTlv + 1] + 2)) { 566ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectedAid = new byte[selectResponse[nextTlv + 1]]; 567ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy( 568ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse, nextTlv + 2, selectedAid, 0, 569ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse[nextTlv + 1]); 570ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 571ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue break; 572ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 573ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue nextTlv += 2 + selectResponse[nextTlv + 1]; 574ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 575ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 576ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 577ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return selectedAid; 578ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 579ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 580ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** Dump data for debug purpose . */ 581ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void dump(PrintWriter writer) { 582ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName); 583ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 584ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 585ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("mIsConnected:" + mIsConnected); 586ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 587ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 588ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /* Dump the list of currunlty openned channels */ 589ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("List of open channels:"); 590ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 591ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Channel channel : mChannels.values()) { 592ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("channel " + channel.getChannelNumber() + ": "); 593ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("package: " + channel.getChannelAccess().getPackageName()); 594ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("pid: " + channel.getChannelAccess().getCallingPid()); 595ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("aid selected: " + channel.hasSelectedAid()); 596ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("basic channel: " + channel.isBasicChannel()); 597ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 598ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 599ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 600ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 601ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /* Dump ACE data */ 602ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer != null) { 603ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.dump(writer); 604ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 605ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 606ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 607ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue // Implementation of the SecureElement Reader interface according to OMAPI. 608ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue final class SecureElementReader extends ISecureElementReader.Stub { 609ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 610ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final SecureElementService mService; 611ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final ArrayList<SecureElementSession> mSessions = 612ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue new ArrayList<SecureElementSession>(); 613ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 614ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue SecureElementReader(SecureElementService service) { 615ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mService = service; 616ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 617ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 618ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public byte[] getAtr() { 619ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this.getAtr(); 620ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 621ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 622ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 623ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isSecureElementPresent() throws RemoteException { 624ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this.isSecureElementPresent(); 625ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 626ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 627ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 628ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void closeSessions() { 629ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 630ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue while (mSessions.size() > 0) { 631ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 632ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.get(0).close(); 633ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception ignore) { 634ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 635ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 636ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.clear(); 637ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 638ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 639ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 640ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void removeSession(SecureElementSession session) { 641ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (session == null) { 642ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NullPointerException("session is null"); 643ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 644ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.remove(session); 645e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi synchronized (mLock) { 646e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi if (mSessions.size() == 0) { 647e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi mDefaultApplicationSelectedOnBasicChannel = true; 648e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 649e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 650ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 651ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 652ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 653ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public ISecureElementSession openSession() throws RemoteException { 654ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!isSecureElementPresent()) { 655ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new ServiceSpecificException(SEService.IO_ERROR, 656ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue "Secure Element is not present."); 657ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 658ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 659ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 660ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue SecureElementSession session = mService.new SecureElementSession(this); 661ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.add(session); 662ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return session; 663ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 664ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 665ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 666ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Terminal getTerminal() { 667ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this; 668ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 669ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 670ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue} 671