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; 33cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Nakaimport android.os.Handler; 34cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Nakaimport android.os.HwBinder; 35cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Nakaimport android.os.Message; 36ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.RemoteException; 37ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.os.ServiceSpecificException; 38ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementListener; 39ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementReader; 40ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.ISecureElementSession; 41ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.se.omapi.SEService; 42ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport android.util.Log; 43ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 44ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.SecureElementService.SecureElementSession; 45ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.internal.ByteArrayConverter; 46ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.AccessControlEnforcer; 47ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport com.android.se.security.ChannelAccess; 48ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 493e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Nakaimport java.io.IOException; 50ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.io.PrintWriter; 51ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.ArrayList; 52ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Collection; 53ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.HashMap; 54ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.Map; 55b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Nakaimport java.util.MissingResourceException; 56ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghueimport java.util.NoSuchElementException; 57ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 58ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue/** 59ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Each Terminal represents a Secure Element. 60ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Communicates to the SE via SecureElement HAL. 61ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 62ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghuepublic class Terminal { 63ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 64ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final String mTag; 65ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>(); 66ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final Object mLock = new Object(); 67ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final String mName; 68ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean mIsConnected = false; 69ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private Context mContext; 70ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private boolean mDefaultApplicationSelectedOnBasicChannel = true; 71ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 7257ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Naka private static final boolean DEBUG = Build.IS_DEBUGGABLE; 73cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000; 74cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka private static final int EVENT_GET_HAL = 1; 75ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 76ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ISecureElement mSEHal; 77ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 78ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** For each Terminal there will be one AccessController object. */ 79ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private AccessControlEnforcer mAccessControlEnforcer; 80ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 81ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() { 82ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 83ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void onStateChange(boolean state) { 84ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 85ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "OnStateChange:" + state); 86ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mIsConnected = state; 87ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!state) { 88ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer != null) { 89ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.reset(); 90ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 91ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 920f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto // If any logical channel in use is in the channel list, it should be closed 930f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto // because the access control enfocer allowed to open it by checking the access 940f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto // rules retrieved before. Now we are going to retrieve the rules again and 950f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto // the new rules can be different from the previous ones. 960f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto closeChannels(); 97a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka try { 98a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka initializeAccessControl(); 99a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (Exception e) { 100a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // ignore 101a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } 102cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mDefaultApplicationSelectedOnBasicChannel = true; 103ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 104ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 105ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 106ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }; 107ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 108cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka class SecureElementDeathRecipient implements HwBinder.DeathRecipient { 109cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka @Override 110cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka public void serviceDied(long cookie) { 111cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka Log.e(mTag, mName + " died"); 112cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka synchronized (mLock) { 113cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mIsConnected = false; 114cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka if (mAccessControlEnforcer != null) { 115cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mAccessControlEnforcer.reset(); 116cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 117cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 118cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_GET_HAL, 0), 119cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka GET_SERVICE_DELAY_MILLIS); 120cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 121cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 122cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka 123cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient(); 124cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka 125cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka private Handler mHandler = new Handler() { 126cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka @Override 127cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka public void handleMessage(Message message) { 128cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka switch (message.what) { 129cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka case EVENT_GET_HAL: 130cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka try { 131cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka initialize(); 132cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } catch (Exception e) { 133cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka Log.e(mTag, mName + " could not be initialized again"); 134cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka sendMessageDelayed(obtainMessage(EVENT_GET_HAL, 0), 135cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka GET_SERVICE_DELAY_MILLIS); 136cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 137cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka break; 138cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka default: 139cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka break; 140cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 141ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 142cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka }; 143cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka 144cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka public Terminal(String name, Context context) { 145ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mContext = context; 146ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mName = name; 147ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mTag = "SecureElement-Terminal-" + getName(); 148cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 149cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka 150cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka /** 151cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka * Initializes the terminal 152cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka * 153cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka * @throws NoSuchElementException if there is no HAL implementation for the specified SE name 154cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka * @throws RemoteException if there is a failure communicating with the remote 155cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka */ 156cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka public void initialize() throws NoSuchElementException, RemoteException { 157cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka synchronized (mLock) { 158cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mSEHal = ISecureElement.getService(mName); 159cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka if (mSEHal == null) { 160cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka throw new NoSuchElementException("No HAL is provided for " + mName); 161cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 162cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mSEHal.init(mHalCallback); 163cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mSEHal.linkToDeath(mDeathRecipient, 0); 164ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 165cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka Log.i(mTag, mName + " was initialized"); 166ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 167ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 168ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private ArrayList<Byte> byteArrayToArrayList(byte[] array) { 169ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<Byte> list = new ArrayList<Byte>(); 170ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (array == null) { 171ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return list; 172ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 173ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 174ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Byte b : array) { 175ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue list.add(b); 176ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 177ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return list; 178ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 179ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 180ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private byte[] arrayListToByteArray(ArrayList<Byte> list) { 181ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Byte[] byteArray = list.toArray(new Byte[list.size()]); 182ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int i = 0; 183ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] result = new byte[list.size()]; 184ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Byte b : byteArray) { 185ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue result[i++] = b.byteValue(); 186ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 187ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return result; 188ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 189ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 190ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 191ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Closes the given channel 192ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 193ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void closeChannel(Channel channel) { 194ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (channel == null) { 195ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return; 196ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 197fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi if (mIsConnected) { 198ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 199ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte status = mSEHal.closeChannel((byte) channel.getChannelNumber()); 200fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi /* For Basic Channels, errors are expected. 201fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi * Underlying implementations use this call as an indication when there 202fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi * aren't any users actively using the channel, and the chip can go 203fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi * into low power state. 204fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi */ 205fffcc4e3ff78f746101858c1e055ae681ea343a7Ruchi Kandoi if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) { 206ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error closing channel " + channel.getChannelNumber()); 207ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 208ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 209ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Exception in closeChannel() " + e); 210ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 211ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 212ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 213ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.remove(channel.getChannelNumber(), channel); 214ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mChannels.get(channel.getChannelNumber()) != null) { 215ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Removing channel failed"); 216ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 217ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 218ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 219ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 220ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 2210f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto * Cleans up all the channels in use. 222ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 223ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public synchronized void closeChannels() { 224ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Collection<Channel> col = mChannels.values(); 225ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel[] channelList = col.toArray(new Channel[col.size()]); 226ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Channel channel : channelList) { 2270f8b45235b612ac4d7a9cd7af7233039e4358b81Yukinori Sakamoto channel.close(); 228ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 229ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 230ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 231cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka /** 232cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka * Closes the terminal. 233cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka */ 234cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka public void close() { 235cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka synchronized (mLock) { 236cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka if (mSEHal != null) { 237cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka try { 238cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka mSEHal.unlinkToDeath(mDeathRecipient); 239cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } catch (RemoteException e) { 240cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka // ignore 241cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 242cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 243cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 244cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka } 245cf7d2f1d5d06675593e770e267d318357b598fdcYoshiaki Naka 246ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public String getName() { 247ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mName; 248ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 249ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 250ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 251ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns the ATR of the Secure Element, or null if not available. 252ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 253ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public byte[] getAtr() { 254ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!mIsConnected) { 255ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 256ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 257ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 258ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 259ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<Byte> responseList = mSEHal.getAtr(); 260ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (responseList.isEmpty()) { 261ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 262ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 263ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return arrayListToByteArray(responseList); 264ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 265ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Exception in getAtr()" + e); 266ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 267ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 268ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 269ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 270ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 271ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Selects the default application on the basic channel. 272ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 273ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * If there is an exception selecting the default application, select 274ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * is performed with the default access control aid. 275ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 276ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void selectDefaultApplication() { 277ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 278ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue select(null); 279ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (NoSuchElementException e) { 280ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (getAccessControlEnforcer() != null) { 281ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 282ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue select(mAccessControlEnforcer.getDefaultAccessControlAid()); 283ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception ignore) { 284ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 285ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 2863878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } catch (Exception ignore) { 287ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 288ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 289ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 2903878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka private void select(byte[] aid) throws IOException { 291ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int commandSize = (aid == null ? 0 : aid.length) + 5; 292ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectCommand = new byte[commandSize]; 293ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[0] = 0x00; 294ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[1] = (byte) 0xA4; 295ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[2] = 0x04; 296ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[3] = 0x00; 297ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length != 0) { 298ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[4] = (byte) aid.length; 299ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(aid, 0, selectCommand, 5, aid.length); 300ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else { 301ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectCommand[4] = 0x00; 302ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 303ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = transmit(selectCommand); 304ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (selectResponse.length < 2) { 305ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse = null; 306ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NoSuchElementException("Response length is too small"); 307ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 308e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi int sw1 = selectResponse[selectResponse.length - 2] & 0xFF; 309e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi int sw2 = selectResponse[selectResponse.length - 1] & 0xFF; 310ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (sw1 != 0x90 || sw2 != 0x00) { 311ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue selectResponse = null; 312ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NoSuchElementException("Status word is incorrect"); 313ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 314ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 315ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 316ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 317ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a Basic Channel with the given AID and P2 paramters 318ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 319ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2, 3205091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka ISecureElementListener listener, String packageName, int pid) throws IOException, 3215091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka NoSuchElementException { 322ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length == 0) { 323ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue aid = null; 324ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 325ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("AID out of range"); 3263e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } else if (!mIsConnected) { 3273e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("Secure Element is not connected"); 328ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 329ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 330ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.w(mTag, "Enable access control on basic channel for " + packageName); 331b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka ChannelAccess channelAccess; 332b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka try { 333a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka channelAccess = setUpChannelAccess(aid, packageName, pid); 334b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } catch (MissingResourceException e) { 335b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka return null; 336b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } 337ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 338ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 339ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mChannels.get(0) != null) { 340ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "basic channel in use"); 341ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 342ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 343ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) { 344ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "default application is not selected"); 345ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 346ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 347ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 348ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ArrayList<byte[]> responseList = new ArrayList<byte[]>(); 349ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 3503e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 3513e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka try { 3523e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2, 3533e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka new ISecureElement.openBasicChannelCallback() { 3543e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka @Override 3553e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public void onValues(ArrayList<Byte> responseObject, byte halStatus) { 3563e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka status[0] = halStatus; 3573e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka responseList.add(arrayListToByteArray(responseObject)); 3583e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka return; 3593e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 3603e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka }); 3613e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (RemoteException e) { 3623e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException(e.getMessage()); 3633e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 3643e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 365ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = responseList.get(0); 366ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 367ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 368ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 369ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new UnsupportedOperationException("OpenBasicChannel() failed"); 370ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.IOERROR) { 3713e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("OpenBasicChannel() failed"); 372e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 3735091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka throw new NoSuchElementException("OpenBasicChannel() failed"); 374ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 375e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi 376ee4e841e19af13ab78b7b7f385c3245019ff3806Ruchi Kandoi Channel basicChannel = new Channel(session, this, 0, selectResponse, aid, 377ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue listener); 378ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue basicChannel.setChannelAccess(channelAccess); 379ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 380ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null) { 381ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mDefaultApplicationSelectedOnBasicChannel = false; 382ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 383ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.put(0, basicChannel); 384ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return basicChannel; 385ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 386ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 387ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 388ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 389ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a logical Channel without Channel Access initialization. 390ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 3915091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException, 3925091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka NoSuchElementException { 393ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0); 394ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 395ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 396ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 397ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Opens a logical Channel with AID. 398ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 3993e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, 4005091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka ISecureElementListener listener, String packageName, int pid) throws IOException, 4015091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka NoSuchElementException { 402ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid != null && aid.length == 0) { 403ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue aid = null; 404ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 405ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new IllegalArgumentException("AID out of range"); 406ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (!mIsConnected) { 4073e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("Secure Element is not connected"); 408ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 409ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 410ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = null; 411ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (packageName != null) { 412ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.w(mTag, "Enable access control on logical channel for " + packageName); 413b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka try { 414a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka channelAccess = setUpChannelAccess(aid, packageName, pid); 415b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } catch (MissingResourceException e) { 416b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka return null; 417b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka } 418ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 419ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 420ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 421ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 422ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 4233e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 4243e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka try { 4253e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2, 4263e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka new ISecureElement.openLogicalChannelCallback() { 4273e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka @Override 4283e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka public void onValues(LogicalChannelResponse response, byte halStatus) { 4293e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka status[0] = halStatus; 4303e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka responseArray[0] = response; 4313e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka return; 4323e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 4333e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka }); 4343e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } catch (RemoteException e) { 4353e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException(e.getMessage()); 4363e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka } 4373e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka 438ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 439ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 440ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 441ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new UnsupportedOperationException("OpenLogicalChannel() failed"); 442ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.IOERROR) { 4433e785e28c90aefc1a5c09f089684fdd48633fa32Yoshiaki Naka throw new IOException("OpenLogicalChannel() failed"); 444ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 4455091d61f6760b87dc00d48040fad9da6509a522bYoshiaki Naka throw new NoSuchElementException("OpenLogicalChannel() failed"); 446ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 447ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) { 448ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 449ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 450ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int channelNumber = responseArray[0].channelNumber; 451ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse); 452ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Channel logicalChannel = new Channel(session, this, channelNumber, 453ee4e841e19af13ab78b7b7f385c3245019ff3806Ruchi Kandoi selectResponse, aid, listener); 454ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue logicalChannel.setChannelAccess(channelAccess); 455ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 456ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mChannels.put(channelNumber, logicalChannel); 457ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return logicalChannel; 458ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 459ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 460ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 461ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 462ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns true if the given AID can be selected on the Terminal 463ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 464ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isAidSelectable(byte[] aid) { 465ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (aid == null) { 466ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NullPointerException("aid must not be null"); 467ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (!mIsConnected) { 468ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Secure Element is not connected"); 469ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 470ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 471ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 472ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 473ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 474ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] status = new byte[1]; 475ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 476ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00, 477ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue new ISecureElement.openLogicalChannelCallback() { 478ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 479ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void onValues(LogicalChannelResponse response, byte halStatus) { 480ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue status[0] = halStatus; 481ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue responseArray[0] = response; 482ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return; 483ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 484ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }); 485ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (status[0] == SecureElementStatus.SUCCESS) { 486ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSEHal.closeChannel(responseArray[0].channelNumber); 487ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return true; 488ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 489ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 490ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 491ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error in isAidSelectable() returning false" + e); 492ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 493ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 494ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 495ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 496ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 497ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 498ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Transmits the specified command and returns the response. 499ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * 500ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * @param cmd the command APDU to be transmitted. 501ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * @return the response received. 502ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 5033878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka public byte[] transmit(byte[] cmd) throws IOException { 504ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!mIsConnected) { 505ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Secure Element is not connected"); 5063878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException("Secure Element is not connected"); 507ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 508ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 509ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] rsp = transmitInternal(cmd); 510ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int sw1 = rsp[rsp.length - 2] & 0xFF; 511ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue int sw2 = rsp[rsp.length - 1] & 0xFF; 512ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 513ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (sw1 == 0x6C) { 514ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue cmd[cmd.length - 1] = rsp[rsp.length - 1]; 515ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue rsp = transmitInternal(cmd); 516ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } else if (sw1 == 0x61) { 517ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue do { 518ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] getResponseCmd = new byte[]{ 519ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2 520ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue }; 521ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] tmp = transmitInternal(getResponseCmd); 522ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] aux = rsp; 523ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue rsp = new byte[aux.length + tmp.length - 2]; 524ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(aux, 0, rsp, 0, aux.length - 2); 525ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length); 526ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue sw1 = rsp[rsp.length - 2] & 0xFF; 527ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue sw2 = rsp[rsp.length - 1] & 0xFF; 528ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } while (sw1 == 0x61); 529ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 530ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return rsp; 531ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 532ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 5333878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka private byte[] transmitInternal(byte[] cmd) throws IOException { 5343878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka ArrayList<Byte> response; 5353878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka try { 5363878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka response = mSEHal.transmit(byteArrayToArrayList(cmd)); 5373878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } catch (RemoteException e) { 5383878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException(e.getMessage()); 5393878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka } 540ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (response.isEmpty()) { 5413878ce67ae4810258882c749f4dcbf508e6ad9edYoshiaki Naka throw new IOException("Error in transmit()"); 542ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 543ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue byte[] rsp = arrayListToByteArray(response); 54457ae12642a4b355e34025f16b4bcb1c379c629e3Yoshiaki Naka if (DEBUG) { 545ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd)); 546ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp)); 547ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 548ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return rsp; 549ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 550ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 551ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 552ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Checks if the application is authorized to receive the transaction event. 553ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 554a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid, 555a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka String[] packageNames) { 556a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka boolean checkRefreshTag = true; 557ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 558a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka try { 559a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka initializeAccessControl(); 560a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // Just finished to initialize the access control enforcer. 561a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // It is too much to check the refresh tag in this case. 562a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka checkRefreshTag = false; 563a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (Exception e) { 564a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 565a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka return null; 566a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } 567ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 568ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setPackageManager(packageManager); 569ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 570ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 571ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 572ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames, 573ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue checkRefreshTag); 574ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception e) { 575ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 576ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return null; 577ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 578ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 579ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 580ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 581ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 582ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Returns true if the Secure Element is present 583ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 584ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isSecureElementPresent() { 585ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 586ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mSEHal.isCardPresent(); 587ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (RemoteException e) { 588ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Log.e(mTag, "Error in isSecureElementPresent() " + e); 589ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return false; 590ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 591ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 592ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 593ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 594ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Initialize the Access Control and set up the channel access. 595ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 596a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid) 597a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka throws IOException, MissingResourceException { 598a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka boolean checkRefreshTag = true; 599ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 600ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue initializeAccessControl(); 601a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // Just finished to initialize the access control enforcer. 602a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // It is too much to check the refresh tag in this case. 603a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka checkRefreshTag = false; 604ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 605ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); 606ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 607ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 608ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 609ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue ChannelAccess channelAccess = 610ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.setUpChannelAccess(aid, packageName, 611ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue checkRefreshTag); 612ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue channelAccess.setCallingPid(pid); 613ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return channelAccess; 614a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (IOException | MissingResourceException e) { 615b36dd054b47593b8a6b7d199aaf3336fe6ec70e8Yoshiaki Naka throw e; 616ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception e) { 617ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new SecurityException("Exception in setUpChannelAccess()" + e); 618ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 619ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 620ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 621ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 622ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** 623ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue * Initializes the Access Control for this Terminal 624ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue */ 625a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka private synchronized void initializeAccessControl() throws IOException, 626a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka MissingResourceException { 627ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 628ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer == null) { 629ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer = new AccessControlEnforcer(this); 630ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 631a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka try { 632a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka mAccessControlEnforcer.initialize(); 633a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } catch (IOException | MissingResourceException e) { 634a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // Retrieving access rules failed because of an IO error happened between 635a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // the terminal and the secure element or the lack of a logical channel available. 636a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // It might be a temporary failure, so the terminal shall attempt to cache 637a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka // the access rules again later. 638a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka mAccessControlEnforcer = null; 639a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka throw e; 640a726b469d3c61c4dab20aefa75408d363431bf6aYoshiaki Naka } 641ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 642ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 643ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 644ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public AccessControlEnforcer getAccessControlEnforcer() { 645ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return mAccessControlEnforcer; 646ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 647ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 648ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /** Dump data for debug purpose . */ 649ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void dump(PrintWriter writer) { 650ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName); 651ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 652ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 653ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("mIsConnected:" + mIsConnected); 654ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 655ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 656ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /* Dump the list of currunlty openned channels */ 657ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("List of open channels:"); 658ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 659ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue for (Channel channel : mChannels.values()) { 660ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("channel " + channel.getChannelNumber() + ": "); 661ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("package: " + channel.getChannelAccess().getPackageName()); 662ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("pid: " + channel.getChannelAccess().getCallingPid()); 663ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("aid selected: " + channel.hasSelectedAid()); 664ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println("basic channel: " + channel.isBasicChannel()); 665ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 666ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 667ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue writer.println(); 668ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 669ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue /* Dump ACE data */ 670ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (mAccessControlEnforcer != null) { 671ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mAccessControlEnforcer.dump(writer); 672ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 673ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 674ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 675ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue // Implementation of the SecureElement Reader interface according to OMAPI. 676ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue final class SecureElementReader extends ISecureElementReader.Stub { 677ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 678ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final SecureElementService mService; 679ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue private final ArrayList<SecureElementSession> mSessions = 680ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue new ArrayList<SecureElementSession>(); 681ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 682ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue SecureElementReader(SecureElementService service) { 683ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mService = service; 684ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 685ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 686ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public byte[] getAtr() { 687ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this.getAtr(); 688ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 689ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 690ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 691ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public boolean isSecureElementPresent() throws RemoteException { 692ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this.isSecureElementPresent(); 693ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 694ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 695ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 696ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void closeSessions() { 697ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 698ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue while (mSessions.size() > 0) { 699ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue try { 700ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.get(0).close(); 701ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } catch (Exception ignore) { 702ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 703ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 704ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.clear(); 705ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 706ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 707ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 708ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public void removeSession(SecureElementSession session) { 709ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (session == null) { 710ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new NullPointerException("session is null"); 711ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 712ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.remove(session); 713e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi synchronized (mLock) { 714e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi if (mSessions.size() == 0) { 715e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi mDefaultApplicationSelectedOnBasicChannel = true; 716e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 717e6556339e7843be665238dd9b53a22a37d4eddb7Ruchi Kandoi } 718ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 719ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 720ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue @Override 721ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue public ISecureElementSession openSession() throws RemoteException { 722ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue if (!isSecureElementPresent()) { 723ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue throw new ServiceSpecificException(SEService.IO_ERROR, 724ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue "Secure Element is not present."); 725ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 726ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 727ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue synchronized (mLock) { 728ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue SecureElementSession session = mService.new SecureElementSession(this); 729ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue mSessions.add(session); 730ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return session; 731ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 732ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 733ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue 734ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue Terminal getTerminal() { 735ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue return Terminal.this; 736ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 737ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue } 738ab336de91e0468a1352d1a9f5d92f219140e0bd1Jeremy O'Donoghue} 739