1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /* 17 * Copyright (c) 2015-2017, The Linux Foundation. 18 */ 19 20 /* 21 * Contributed by: Giesecke & Devrient GmbH. 22 */ 23 24 package com.android.se; 25 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.hardware.secure_element.V1_0.ISecureElement; 29 import android.hardware.secure_element.V1_0.ISecureElementHalCallback; 30 import android.hardware.secure_element.V1_0.LogicalChannelResponse; 31 import android.hardware.secure_element.V1_0.SecureElementStatus; 32 import android.os.Build; 33 import android.os.Handler; 34 import android.os.HwBinder; 35 import android.os.Message; 36 import android.os.RemoteException; 37 import android.os.ServiceSpecificException; 38 import android.se.omapi.ISecureElementListener; 39 import android.se.omapi.ISecureElementReader; 40 import android.se.omapi.ISecureElementSession; 41 import android.se.omapi.SEService; 42 import android.util.Log; 43 import android.util.StatsLog; 44 45 import com.android.se.SecureElementService.SecureElementSession; 46 import com.android.se.internal.ByteArrayConverter; 47 import com.android.se.security.AccessControlEnforcer; 48 import com.android.se.security.ChannelAccess; 49 50 import java.io.IOException; 51 import java.io.PrintWriter; 52 import java.util.ArrayList; 53 import java.util.Collection; 54 import java.util.HashMap; 55 import java.util.Map; 56 import java.util.MissingResourceException; 57 import java.util.NoSuchElementException; 58 59 /** 60 * Each Terminal represents a Secure Element. 61 * Communicates to the SE via SecureElement HAL. 62 */ 63 public class Terminal { 64 65 private final String mTag; 66 private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>(); 67 private final Object mLock = new Object(); 68 private final String mName; 69 public boolean mIsConnected = false; 70 private Context mContext; 71 private boolean mDefaultApplicationSelectedOnBasicChannel = true; 72 73 private static final boolean DEBUG = Build.IS_DEBUGGABLE; 74 private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000; 75 private static final int EVENT_GET_HAL = 1; 76 77 private ISecureElement mSEHal; 78 79 /** For each Terminal there will be one AccessController object. */ 80 private AccessControlEnforcer mAccessControlEnforcer; 81 82 private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() { 83 @Override 84 public void onStateChange(boolean state) { 85 stateChange(state, ""); 86 } 87 }; 88 89 private android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub mHalCallback11 = 90 new android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub() { 91 @Override 92 public void onStateChange_1_1(boolean state, String reason) { 93 stateChange(state, reason); 94 } 95 96 public void onStateChange(boolean state) { 97 return; 98 } 99 }; 100 stateChange(boolean state, String reason)101 private void stateChange(boolean state, String reason) { 102 synchronized (mLock) { 103 Log.i(mTag, "OnStateChange:" + state + " reason:" + reason); 104 mIsConnected = state; 105 if (!state) { 106 if (mAccessControlEnforcer != null) { 107 mAccessControlEnforcer.reset(); 108 } 109 StatsLog.write( 110 StatsLog.SE_STATE_CHANGED, 111 StatsLog.SE_STATE_CHANGED__STATE__DISCONNECTED, 112 reason, 113 mName); 114 } else { 115 // If any logical channel in use is in the channel list, it should be closed 116 // because the access control enfocer allowed to open it by checking the access 117 // rules retrieved before. Now we are going to retrieve the rules again and 118 // the new rules can be different from the previous ones. 119 closeChannels(); 120 try { 121 initializeAccessControl(); 122 } catch (Exception e) { 123 // ignore 124 } 125 mDefaultApplicationSelectedOnBasicChannel = true; 126 StatsLog.write( 127 StatsLog.SE_STATE_CHANGED, 128 StatsLog.SE_STATE_CHANGED__STATE__CONNECTED, 129 reason, 130 mName); 131 } 132 } 133 } 134 135 class SecureElementDeathRecipient implements HwBinder.DeathRecipient { 136 @Override serviceDied(long cookie)137 public void serviceDied(long cookie) { 138 Log.e(mTag, mName + " died"); 139 StatsLog.write( 140 StatsLog.SE_STATE_CHANGED, 141 StatsLog.SE_STATE_CHANGED__STATE__HALCRASH, 142 "HALCRASH", 143 mName); 144 synchronized (mLock) { 145 mIsConnected = false; 146 if (mAccessControlEnforcer != null) { 147 mAccessControlEnforcer.reset(); 148 } 149 } 150 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_GET_HAL, 0), 151 GET_SERVICE_DELAY_MILLIS); 152 } 153 } 154 155 private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient(); 156 157 private Handler mHandler = new Handler() { 158 @Override 159 public void handleMessage(Message message) { 160 switch (message.what) { 161 case EVENT_GET_HAL: 162 try { 163 initialize(); 164 } catch (Exception e) { 165 Log.e(mTag, mName + " could not be initialized again"); 166 sendMessageDelayed(obtainMessage(EVENT_GET_HAL, 0), 167 GET_SERVICE_DELAY_MILLIS); 168 } 169 break; 170 default: 171 break; 172 } 173 } 174 }; 175 Terminal(String name, Context context)176 public Terminal(String name, Context context) { 177 mContext = context; 178 mName = name; 179 mTag = "SecureElement-Terminal-" + getName(); 180 } 181 182 /** 183 * Initializes the terminal 184 * 185 * @throws NoSuchElementException if there is no HAL implementation for the specified SE name 186 * @throws RemoteException if there is a failure communicating with the remote 187 */ initialize()188 public void initialize() throws NoSuchElementException, RemoteException { 189 synchronized (mLock) { 190 android.hardware.secure_element.V1_1.ISecureElement seHal11 = null; 191 try { 192 seHal11 = 193 android.hardware.secure_element.V1_1.ISecureElement.getService(mName, true); 194 } catch (Exception e) { 195 Log.d(mTag, "SE Hal V1.1 is not supported"); 196 } 197 198 if (seHal11 == null) { 199 mSEHal = ISecureElement.getService(mName, true); 200 if (mSEHal == null) { 201 throw new NoSuchElementException("No HAL is provided for " + mName); 202 } 203 } 204 if (seHal11 != null) { 205 mSEHal = seHal11; 206 seHal11.init_1_1(mHalCallback11); 207 } else { 208 mSEHal.init(mHalCallback); 209 } 210 mSEHal.linkToDeath(mDeathRecipient, 0); 211 } 212 Log.i(mTag, mName + " was initialized"); 213 StatsLog.write( 214 StatsLog.SE_STATE_CHANGED, 215 StatsLog.SE_STATE_CHANGED__STATE__INITIALIZED, 216 "INIT", 217 mName); 218 } 219 byteArrayToArrayList(byte[] array)220 private ArrayList<Byte> byteArrayToArrayList(byte[] array) { 221 ArrayList<Byte> list = new ArrayList<Byte>(); 222 if (array == null) { 223 return list; 224 } 225 226 for (Byte b : array) { 227 list.add(b); 228 } 229 return list; 230 } 231 arrayListToByteArray(ArrayList<Byte> list)232 private byte[] arrayListToByteArray(ArrayList<Byte> list) { 233 Byte[] byteArray = list.toArray(new Byte[list.size()]); 234 int i = 0; 235 byte[] result = new byte[list.size()]; 236 for (Byte b : byteArray) { 237 result[i++] = b.byteValue(); 238 } 239 return result; 240 } 241 242 /** 243 * Closes the given channel 244 */ closeChannel(Channel channel)245 public void closeChannel(Channel channel) { 246 if (channel == null) { 247 return; 248 } 249 if (mIsConnected) { 250 try { 251 byte status = mSEHal.closeChannel((byte) channel.getChannelNumber()); 252 /* For Basic Channels, errors are expected. 253 * Underlying implementations use this call as an indication when there 254 * aren't any users actively using the channel, and the chip can go 255 * into low power state. 256 */ 257 if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) { 258 Log.e(mTag, "Error closing channel " + channel.getChannelNumber()); 259 } 260 } catch (RemoteException e) { 261 Log.e(mTag, "Exception in closeChannel() " + e); 262 } 263 } 264 synchronized (mLock) { 265 mChannels.remove(channel.getChannelNumber(), channel); 266 if (mChannels.get(channel.getChannelNumber()) != null) { 267 Log.e(mTag, "Removing channel failed"); 268 } 269 } 270 } 271 272 /** 273 * Cleans up all the channels in use. 274 */ closeChannels()275 public synchronized void closeChannels() { 276 Collection<Channel> col = mChannels.values(); 277 Channel[] channelList = col.toArray(new Channel[col.size()]); 278 for (Channel channel : channelList) { 279 channel.close(); 280 } 281 } 282 283 /** 284 * Closes the terminal. 285 */ close()286 public void close() { 287 synchronized (mLock) { 288 if (mSEHal != null) { 289 try { 290 mSEHal.unlinkToDeath(mDeathRecipient); 291 } catch (RemoteException e) { 292 // ignore 293 } 294 } 295 } 296 } 297 getName()298 public String getName() { 299 return mName; 300 } 301 302 /** 303 * Returns the ATR of the Secure Element, or null if not available. 304 */ getAtr()305 public byte[] getAtr() { 306 if (!mIsConnected) { 307 return null; 308 } 309 310 try { 311 ArrayList<Byte> responseList = mSEHal.getAtr(); 312 if (responseList.isEmpty()) { 313 return null; 314 } 315 byte[] atr = arrayListToByteArray(responseList); 316 if (DEBUG) { 317 Log.i(mTag, "ATR : " + ByteArrayConverter.byteArrayToHexString(atr)); 318 } 319 return atr; 320 } catch (RemoteException e) { 321 Log.e(mTag, "Exception in getAtr()" + e); 322 return null; 323 } 324 } 325 326 /** 327 * Selects the default application on the basic channel. 328 * 329 * If there is an exception selecting the default application, select 330 * is performed with the default access control aid. 331 */ selectDefaultApplication()332 public void selectDefaultApplication() { 333 try { 334 select(null); 335 } catch (NoSuchElementException e) { 336 if (getAccessControlEnforcer() != null) { 337 try { 338 select(mAccessControlEnforcer.getDefaultAccessControlAid()); 339 } catch (Exception ignore) { 340 } 341 } 342 } catch (Exception ignore) { 343 } 344 } 345 select(byte[] aid)346 private void select(byte[] aid) throws IOException { 347 int commandSize = (aid == null ? 0 : aid.length) + 5; 348 byte[] selectCommand = new byte[commandSize]; 349 selectCommand[0] = 0x00; 350 selectCommand[1] = (byte) 0xA4; 351 selectCommand[2] = 0x04; 352 selectCommand[3] = 0x00; 353 if (aid != null && aid.length != 0) { 354 selectCommand[4] = (byte) aid.length; 355 System.arraycopy(aid, 0, selectCommand, 5, aid.length); 356 } else { 357 selectCommand[4] = 0x00; 358 } 359 byte[] selectResponse = transmit(selectCommand); 360 if (selectResponse.length < 2) { 361 selectResponse = null; 362 throw new NoSuchElementException("Response length is too small"); 363 } 364 int sw1 = selectResponse[selectResponse.length - 2] & 0xFF; 365 int sw2 = selectResponse[selectResponse.length - 1] & 0xFF; 366 if (sw1 != 0x90 || sw2 != 0x00) { 367 selectResponse = null; 368 throw new NoSuchElementException("Status word is incorrect"); 369 } 370 } 371 372 /** 373 * Opens a Basic Channel with the given AID and P2 paramters 374 */ openBasicChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, int pid)375 public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2, 376 ISecureElementListener listener, String packageName, int pid) throws IOException, 377 NoSuchElementException { 378 if (aid != null && aid.length == 0) { 379 aid = null; 380 } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 381 throw new IllegalArgumentException("AID out of range"); 382 } else if (!mIsConnected) { 383 throw new IOException("Secure Element is not connected"); 384 } 385 386 Log.w(mTag, "Enable access control on basic channel for " + packageName); 387 StatsLog.write( 388 StatsLog.SE_OMAPI_REPORTED, 389 StatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL, 390 mName, 391 packageName); 392 ChannelAccess channelAccess; 393 try { 394 channelAccess = setUpChannelAccess(aid, packageName, pid); 395 } catch (MissingResourceException e) { 396 return null; 397 } 398 399 synchronized (mLock) { 400 if (mChannels.get(0) != null) { 401 Log.e(mTag, "basic channel in use"); 402 return null; 403 } 404 if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) { 405 Log.e(mTag, "default application is not selected"); 406 return null; 407 } 408 409 ArrayList<byte[]> responseList = new ArrayList<byte[]>(); 410 byte[] status = new byte[1]; 411 412 try { 413 mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2, 414 new ISecureElement.openBasicChannelCallback() { 415 @Override 416 public void onValues(ArrayList<Byte> responseObject, byte halStatus) { 417 status[0] = halStatus; 418 responseList.add(arrayListToByteArray(responseObject)); 419 return; 420 } 421 }); 422 } catch (RemoteException e) { 423 throw new IOException(e.getMessage()); 424 } 425 426 byte[] selectResponse = responseList.get(0); 427 if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 428 return null; 429 } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 430 throw new UnsupportedOperationException("OpenBasicChannel() failed"); 431 } else if (status[0] == SecureElementStatus.IOERROR) { 432 throw new IOException("OpenBasicChannel() failed"); 433 } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 434 throw new NoSuchElementException("OpenBasicChannel() failed"); 435 } 436 437 Channel basicChannel = new Channel(session, this, 0, selectResponse, aid, 438 listener); 439 basicChannel.setChannelAccess(channelAccess); 440 441 if (aid != null) { 442 mDefaultApplicationSelectedOnBasicChannel = false; 443 } 444 mChannels.put(0, basicChannel); 445 return basicChannel; 446 } 447 } 448 449 /** 450 * Opens a logical Channel without Channel Access initialization. 451 */ openLogicalChannelWithoutChannelAccess(byte[] aid)452 public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException, 453 NoSuchElementException { 454 return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0); 455 } 456 457 /** 458 * Opens a logical Channel with AID. 459 */ openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, int pid)460 public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, 461 ISecureElementListener listener, String packageName, int pid) throws IOException, 462 NoSuchElementException { 463 if (aid != null && aid.length == 0) { 464 aid = null; 465 } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 466 throw new IllegalArgumentException("AID out of range"); 467 } else if (!mIsConnected) { 468 throw new IOException("Secure Element is not connected"); 469 } 470 471 ChannelAccess channelAccess = null; 472 if (packageName != null) { 473 Log.w(mTag, "Enable access control on logical channel for " + packageName); 474 StatsLog.write( 475 StatsLog.SE_OMAPI_REPORTED, 476 StatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL, 477 mName, 478 packageName); 479 try { 480 channelAccess = setUpChannelAccess(aid, packageName, pid); 481 } catch (MissingResourceException e) { 482 return null; 483 } 484 } 485 486 synchronized (mLock) { 487 LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 488 byte[] status = new byte[1]; 489 490 try { 491 mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2, 492 new ISecureElement.openLogicalChannelCallback() { 493 @Override 494 public void onValues(LogicalChannelResponse response, byte halStatus) { 495 status[0] = halStatus; 496 responseArray[0] = response; 497 return; 498 } 499 }); 500 } catch (RemoteException e) { 501 throw new IOException(e.getMessage()); 502 } 503 504 if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 505 return null; 506 } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 507 throw new UnsupportedOperationException("OpenLogicalChannel() failed"); 508 } else if (status[0] == SecureElementStatus.IOERROR) { 509 throw new IOException("OpenLogicalChannel() failed"); 510 } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 511 throw new NoSuchElementException("OpenLogicalChannel() failed"); 512 } 513 if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) { 514 return null; 515 } 516 int channelNumber = responseArray[0].channelNumber; 517 byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse); 518 Channel logicalChannel = new Channel(session, this, channelNumber, 519 selectResponse, aid, listener); 520 logicalChannel.setChannelAccess(channelAccess); 521 522 mChannels.put(channelNumber, logicalChannel); 523 return logicalChannel; 524 } 525 } 526 527 /** 528 * Returns true if the given AID can be selected on the Terminal 529 */ isAidSelectable(byte[] aid)530 public boolean isAidSelectable(byte[] aid) { 531 if (aid == null) { 532 throw new NullPointerException("aid must not be null"); 533 } else if (!mIsConnected) { 534 Log.e(mTag, "Secure Element is not connected"); 535 return false; 536 } 537 538 synchronized (mLock) { 539 LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 540 byte[] status = new byte[1]; 541 try { 542 mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00, 543 new ISecureElement.openLogicalChannelCallback() { 544 @Override 545 public void onValues(LogicalChannelResponse response, byte halStatus) { 546 status[0] = halStatus; 547 responseArray[0] = response; 548 return; 549 } 550 }); 551 if (status[0] == SecureElementStatus.SUCCESS) { 552 mSEHal.closeChannel(responseArray[0].channelNumber); 553 return true; 554 } 555 return false; 556 } catch (RemoteException e) { 557 Log.e(mTag, "Error in isAidSelectable() returning false" + e); 558 return false; 559 } 560 } 561 } 562 563 /** 564 * Transmits the specified command and returns the response. 565 * 566 * @param cmd the command APDU to be transmitted. 567 * @return the response received. 568 */ transmit(byte[] cmd)569 public byte[] transmit(byte[] cmd) throws IOException { 570 if (!mIsConnected) { 571 Log.e(mTag, "Secure Element is not connected"); 572 throw new IOException("Secure Element is not connected"); 573 } 574 575 byte[] rsp = transmitInternal(cmd); 576 int sw1 = rsp[rsp.length - 2] & 0xFF; 577 int sw2 = rsp[rsp.length - 1] & 0xFF; 578 579 if (sw1 == 0x6C) { 580 cmd[cmd.length - 1] = rsp[rsp.length - 1]; 581 rsp = transmitInternal(cmd); 582 } else if (sw1 == 0x61) { 583 do { 584 byte[] getResponseCmd = new byte[]{ 585 cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2 586 }; 587 byte[] tmp = transmitInternal(getResponseCmd); 588 byte[] aux = rsp; 589 rsp = new byte[aux.length + tmp.length - 2]; 590 System.arraycopy(aux, 0, rsp, 0, aux.length - 2); 591 System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length); 592 sw1 = rsp[rsp.length - 2] & 0xFF; 593 sw2 = rsp[rsp.length - 1] & 0xFF; 594 } while (sw1 == 0x61); 595 } 596 return rsp; 597 } 598 transmitInternal(byte[] cmd)599 private byte[] transmitInternal(byte[] cmd) throws IOException { 600 ArrayList<Byte> response; 601 try { 602 response = mSEHal.transmit(byteArrayToArrayList(cmd)); 603 } catch (RemoteException e) { 604 throw new IOException(e.getMessage()); 605 } 606 if (response.isEmpty()) { 607 throw new IOException("Error in transmit()"); 608 } 609 byte[] rsp = arrayListToByteArray(response); 610 if (DEBUG) { 611 Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd)); 612 Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp)); 613 } 614 return rsp; 615 } 616 617 /** 618 * Checks if the application is authorized to receive the transaction event. 619 */ isNfcEventAllowed(PackageManager packageManager, byte[] aid, String[] packageNames)620 public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid, 621 String[] packageNames) { 622 // Attempt to initialize the access control enforcer if it failed in the previous attempt 623 // due to a kind of temporary failure or no rule was found. 624 if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) { 625 try { 626 initializeAccessControl(); 627 // Just finished to initialize the access control enforcer. 628 // It is too much to check the refresh tag in this case. 629 } catch (Exception e) { 630 Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 631 return null; 632 } 633 } 634 mAccessControlEnforcer.setPackageManager(packageManager); 635 636 synchronized (mLock) { 637 try { 638 return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames); 639 } catch (Exception e) { 640 Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 641 return null; 642 } 643 } 644 } 645 646 /** 647 * Returns true if the Secure Element is present 648 */ isSecureElementPresent()649 public boolean isSecureElementPresent() { 650 try { 651 return mSEHal.isCardPresent(); 652 } catch (RemoteException e) { 653 Log.e(mTag, "Error in isSecureElementPresent() " + e); 654 return false; 655 } 656 } 657 658 /** 659 * Initialize the Access Control and set up the channel access. 660 */ setUpChannelAccess(byte[] aid, String packageName, int pid)661 private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid) 662 throws IOException, MissingResourceException { 663 boolean checkRefreshTag = true; 664 // Attempt to initialize the access control enforcer if it failed 665 // due to a kind of temporary failure or no rule was found in the previous attempt. 666 if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) { 667 initializeAccessControl(); 668 // Just finished to initialize the access control enforcer. 669 // It is too much to check the refresh tag in this case. 670 checkRefreshTag = false; 671 } 672 mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); 673 674 synchronized (mLock) { 675 try { 676 ChannelAccess channelAccess = 677 mAccessControlEnforcer.setUpChannelAccess(aid, packageName, 678 checkRefreshTag); 679 channelAccess.setCallingPid(pid); 680 return channelAccess; 681 } catch (IOException | MissingResourceException e) { 682 throw e; 683 } catch (Exception e) { 684 throw new SecurityException("Exception in setUpChannelAccess()" + e); 685 } 686 } 687 } 688 689 /** 690 * Initializes the Access Control for this Terminal 691 */ initializeAccessControl()692 private synchronized void initializeAccessControl() throws IOException, 693 MissingResourceException { 694 synchronized (mLock) { 695 if (mAccessControlEnforcer == null) { 696 mAccessControlEnforcer = new AccessControlEnforcer(this); 697 } 698 try { 699 mAccessControlEnforcer.initialize(); 700 } catch (IOException | MissingResourceException e) { 701 // Retrieving access rules failed because of an IO error happened between 702 // the terminal and the secure element or the lack of a logical channel available. 703 // It might be a temporary failure, so the terminal shall attempt to cache 704 // the access rules again later. 705 mAccessControlEnforcer = null; 706 throw e; 707 } 708 } 709 } 710 getAccessControlEnforcer()711 public AccessControlEnforcer getAccessControlEnforcer() { 712 return mAccessControlEnforcer; 713 } 714 715 /** Dump data for debug purpose . */ dump(PrintWriter writer)716 public void dump(PrintWriter writer) { 717 writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName); 718 writer.println(); 719 720 writer.println("mIsConnected:" + mIsConnected); 721 writer.println(); 722 723 /* Dump the list of currunlty openned channels */ 724 writer.println("List of open channels:"); 725 726 for (Channel channel : mChannels.values()) { 727 writer.println("channel " + channel.getChannelNumber() + ": "); 728 writer.println("package: " + channel.getChannelAccess().getPackageName()); 729 writer.println("pid: " + channel.getChannelAccess().getCallingPid()); 730 writer.println("aid selected: " + channel.hasSelectedAid()); 731 writer.println("basic channel: " + channel.isBasicChannel()); 732 writer.println(); 733 } 734 writer.println(); 735 736 /* Dump ACE data */ 737 if (mAccessControlEnforcer != null) { 738 mAccessControlEnforcer.dump(writer); 739 } 740 } 741 742 // Implementation of the SecureElement Reader interface according to OMAPI. 743 final class SecureElementReader extends ISecureElementReader.Stub { 744 745 private final SecureElementService mService; 746 private final ArrayList<SecureElementSession> mSessions = 747 new ArrayList<SecureElementSession>(); 748 SecureElementReader(SecureElementService service)749 SecureElementReader(SecureElementService service) { 750 mService = service; 751 } 752 getAtr()753 public byte[] getAtr() { 754 return Terminal.this.getAtr(); 755 } 756 757 @Override isSecureElementPresent()758 public boolean isSecureElementPresent() throws RemoteException { 759 return Terminal.this.isSecureElementPresent(); 760 } 761 762 @Override closeSessions()763 public void closeSessions() { 764 synchronized (mLock) { 765 while (mSessions.size() > 0) { 766 try { 767 mSessions.get(0).close(); 768 } catch (Exception ignore) { 769 } 770 } 771 mSessions.clear(); 772 } 773 } 774 removeSession(SecureElementSession session)775 public void removeSession(SecureElementSession session) { 776 if (session == null) { 777 throw new NullPointerException("session is null"); 778 } 779 mSessions.remove(session); 780 synchronized (mLock) { 781 if (mSessions.size() == 0) { 782 mDefaultApplicationSelectedOnBasicChannel = true; 783 } 784 } 785 } 786 787 @Override openSession()788 public ISecureElementSession openSession() throws RemoteException { 789 if (!isSecureElementPresent()) { 790 throw new ServiceSpecificException(SEService.IO_ERROR, 791 "Secure Element is not present."); 792 } 793 794 synchronized (mLock) { 795 SecureElementSession session = mService.new SecureElementSession(this); 796 mSessions.add(session); 797 return session; 798 } 799 } 800 getTerminal()801 Terminal getTerminal() { 802 return Terminal.this; 803 } 804 } 805 } 806