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.Intent; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageManager.NameNotFoundException; 31 import android.hardware.secure_element.V1_0.ISecureElement; 32 import android.hardware.secure_element.V1_0.ISecureElementHalCallback; 33 import android.hardware.secure_element.V1_0.LogicalChannelResponse; 34 import android.hardware.secure_element.V1_0.SecureElementStatus; 35 import android.os.Build; 36 import android.os.Handler; 37 import android.os.HwBinder; 38 import android.os.Message; 39 import android.os.RemoteException; 40 import android.os.ServiceSpecificException; 41 import android.os.UserHandle; 42 import android.se.omapi.ISecureElementListener; 43 import android.se.omapi.ISecureElementReader; 44 import android.se.omapi.ISecureElementSession; 45 import android.se.omapi.SEService; 46 import android.util.Log; 47 48 import com.android.se.SecureElementService.SecureElementSession; 49 import com.android.se.internal.ByteArrayConverter; 50 import com.android.se.security.AccessControlEnforcer; 51 import com.android.se.security.ChannelAccess; 52 53 import java.io.IOException; 54 import java.io.PrintWriter; 55 import java.util.ArrayList; 56 import java.util.Arrays; 57 import java.util.Collection; 58 import java.util.HashMap; 59 import java.util.Map; 60 import java.util.MissingResourceException; 61 import java.util.NoSuchElementException; 62 63 /** 64 * Each Terminal represents a Secure Element. 65 * Communicates to the SE via SecureElement HAL. 66 */ 67 public class Terminal { 68 69 private final String mTag; 70 private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>(); 71 private final Object mLock = new Object(); 72 private final String mName; 73 public boolean mIsConnected = false; 74 private Context mContext; 75 private boolean mDefaultApplicationSelectedOnBasicChannel = true; 76 77 private static final boolean DEBUG = Build.IS_DEBUGGABLE; 78 private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000; 79 private static final int EVENT_GET_HAL = 1; 80 81 private final int mMaxGetHalRetryCount = 5; 82 private int mGetHalRetryCount = 0; 83 84 private ISecureElement mSEHal; 85 private android.hardware.secure_element.V1_2.ISecureElement mSEHal12; 86 87 /** For each Terminal there will be one AccessController object. */ 88 private AccessControlEnforcer mAccessControlEnforcer; 89 90 private static final String SECURE_ELEMENT_PRIVILEGED_OPERATION_PERMISSION = 91 "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"; 92 93 public static final byte[] ISD_R_AID = 94 new byte[]{ 95 (byte) 0xA0, 96 (byte) 0x00, 97 (byte) 0x00, 98 (byte) 0x05, 99 (byte) 0x59, 100 (byte) 0x10, 101 (byte) 0x10, 102 (byte) 0xFF, 103 (byte) 0xFF, 104 (byte) 0xFF, 105 (byte) 0xFF, 106 (byte) 0x89, 107 (byte) 0x00, 108 (byte) 0x00, 109 (byte) 0x01, 110 (byte) 0x00, 111 }; 112 113 private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() { 114 @Override 115 public void onStateChange(boolean state) { 116 stateChange(state, ""); 117 } 118 }; 119 120 private android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub mHalCallback11 = 121 new android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub() { 122 @Override 123 public void onStateChange_1_1(boolean state, String reason) { 124 stateChange(state, reason); 125 } 126 127 public void onStateChange(boolean state) { 128 return; 129 } 130 }; 131 stateChange(boolean state, String reason)132 private void stateChange(boolean state, String reason) { 133 synchronized (mLock) { 134 Log.i(mTag, "OnStateChange:" + state + " reason:" + reason); 135 mIsConnected = state; 136 if (!state) { 137 if (mAccessControlEnforcer != null) { 138 mAccessControlEnforcer.reset(); 139 } 140 SecureElementStatsLog.write( 141 SecureElementStatsLog.SE_STATE_CHANGED, 142 SecureElementStatsLog.SE_STATE_CHANGED__STATE__DISCONNECTED, 143 reason, 144 mName); 145 } else { 146 // If any logical channel in use is in the channel list, it should be closed 147 // because the access control enfocer allowed to open it by checking the access 148 // rules retrieved before. Now we are going to retrieve the rules again and 149 // the new rules can be different from the previous ones. 150 closeChannels(); 151 try { 152 initializeAccessControl(); 153 } catch (Exception e) { 154 // ignore 155 } 156 mDefaultApplicationSelectedOnBasicChannel = true; 157 SecureElementStatsLog.write( 158 SecureElementStatsLog.SE_STATE_CHANGED, 159 SecureElementStatsLog.SE_STATE_CHANGED__STATE__CONNECTED, 160 reason, 161 mName); 162 } 163 164 sendStateChangedBroadcast(state); 165 } 166 } 167 sendStateChangedBroadcast(boolean state)168 private void sendStateChangedBroadcast(boolean state) { 169 Intent intent = new Intent(SEService.ACTION_SECURE_ELEMENT_STATE_CHANGED); 170 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 171 intent.putExtra(SEService.EXTRA_READER_NAME, mName); 172 intent.putExtra(SEService.EXTRA_READER_STATE, state); 173 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT); 174 }; 175 176 class SecureElementDeathRecipient implements HwBinder.DeathRecipient { 177 @Override serviceDied(long cookie)178 public void serviceDied(long cookie) { 179 Log.e(mTag, mName + " died"); 180 SecureElementStatsLog.write( 181 SecureElementStatsLog.SE_STATE_CHANGED, 182 SecureElementStatsLog.SE_STATE_CHANGED__STATE__HALCRASH, 183 "HALCRASH", 184 mName); 185 synchronized (mLock) { 186 mIsConnected = false; 187 if (mAccessControlEnforcer != null) { 188 mAccessControlEnforcer.reset(); 189 } 190 } 191 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_GET_HAL, 0), 192 GET_SERVICE_DELAY_MILLIS); 193 } 194 } 195 196 private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient(); 197 198 private Handler mHandler = new Handler() { 199 @Override 200 public void handleMessage(Message message) { 201 switch (message.what) { 202 case EVENT_GET_HAL: 203 try { 204 if (mName.startsWith(SecureElementService.ESE_TERMINAL)) { 205 initialize(true); 206 } else { 207 initialize(false); 208 } 209 } catch (Exception e) { 210 Log.e(mTag, mName + " could not be initialized again"); 211 if (mGetHalRetryCount < mMaxGetHalRetryCount) { 212 mGetHalRetryCount++; 213 sendMessageDelayed(obtainMessage(EVENT_GET_HAL, 0), 214 GET_SERVICE_DELAY_MILLIS); 215 } else { 216 Log.e(mTag, mName + " reach maximum retry count"); 217 } 218 } 219 break; 220 default: 221 break; 222 } 223 } 224 }; 225 Terminal(String name, Context context)226 public Terminal(String name, Context context) { 227 mContext = context; 228 mName = name; 229 mTag = "SecureElement-Terminal-" + getName(); 230 } 231 232 /** 233 * Initializes the terminal 234 * 235 * @throws NoSuchElementException if there is no HAL implementation for the specified SE name 236 * @throws RemoteException if there is a failure communicating with the remote 237 */ initialize(boolean retryOnFail)238 public void initialize(boolean retryOnFail) throws NoSuchElementException, RemoteException { 239 android.hardware.secure_element.V1_1.ISecureElement mSEHal11 = null; 240 synchronized (mLock) { 241 try { 242 mSEHal = mSEHal11 = mSEHal12 = 243 android.hardware.secure_element.V1_2.ISecureElement.getService(mName, 244 retryOnFail); 245 } catch (Exception e) { 246 Log.d(mTag, "SE Hal V1.2 is not supported"); 247 } 248 if (mSEHal12 == null) { 249 try { 250 mSEHal = mSEHal11 = 251 android.hardware.secure_element.V1_1.ISecureElement.getService(mName, 252 retryOnFail); 253 } catch (Exception e) { 254 Log.d(mTag, "SE Hal V1.1 is not supported"); 255 } 256 257 if (mSEHal11 == null) { 258 mSEHal = ISecureElement.getService(mName, retryOnFail); 259 if (mSEHal == null) { 260 throw new NoSuchElementException("No HAL is provided for " + mName); 261 } 262 } 263 } 264 if (mSEHal11 != null || mSEHal12 != null) { 265 mSEHal11.init_1_1(mHalCallback11); 266 } else { 267 mSEHal.init(mHalCallback); 268 } 269 mSEHal.linkToDeath(mDeathRecipient, 0); 270 } 271 Log.i(mTag, mName + " was initialized"); 272 SecureElementStatsLog.write( 273 SecureElementStatsLog.SE_STATE_CHANGED, 274 SecureElementStatsLog.SE_STATE_CHANGED__STATE__INITIALIZED, 275 "INIT", 276 mName); 277 } 278 byteArrayToArrayList(byte[] array)279 private ArrayList<Byte> byteArrayToArrayList(byte[] array) { 280 ArrayList<Byte> list = new ArrayList<Byte>(); 281 if (array == null) { 282 return list; 283 } 284 285 for (Byte b : array) { 286 list.add(b); 287 } 288 return list; 289 } 290 arrayListToByteArray(ArrayList<Byte> list)291 private byte[] arrayListToByteArray(ArrayList<Byte> list) { 292 Byte[] byteArray = list.toArray(new Byte[list.size()]); 293 int i = 0; 294 byte[] result = new byte[list.size()]; 295 for (Byte b : byteArray) { 296 result[i++] = b.byteValue(); 297 } 298 return result; 299 } 300 301 /** 302 * Closes the given channel 303 */ closeChannel(Channel channel)304 public void closeChannel(Channel channel) { 305 if (channel == null) { 306 return; 307 } 308 synchronized (mLock) { 309 if (mIsConnected) { 310 try { 311 byte status = mSEHal.closeChannel((byte) channel.getChannelNumber()); 312 /* For Basic Channels, errors are expected. 313 * Underlying implementations use this call as an indication when there 314 * aren't any users actively using the channel, and the chip can go 315 * into low power state. 316 */ 317 if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) { 318 Log.e(mTag, "Error closing channel " + channel.getChannelNumber()); 319 } 320 } catch (RemoteException e) { 321 Log.e(mTag, "Exception in closeChannel() " + e); 322 } 323 } 324 mChannels.remove(channel.getChannelNumber(), channel); 325 if (mChannels.get(channel.getChannelNumber()) != null) { 326 Log.e(mTag, "Removing channel failed"); 327 } 328 } 329 } 330 331 /** 332 * Cleans up all the channels in use. 333 */ closeChannels()334 public void closeChannels() { 335 synchronized (mLock) { 336 Collection<Channel> col = mChannels.values(); 337 Channel[] channelList = col.toArray(new Channel[col.size()]); 338 for (Channel channel : channelList) { 339 channel.close(); 340 } 341 } 342 } 343 344 /** 345 * Closes the terminal. 346 */ close()347 public void close() { 348 synchronized (mLock) { 349 if (mSEHal != null) { 350 try { 351 mSEHal.unlinkToDeath(mDeathRecipient); 352 } catch (RemoteException e) { 353 // ignore 354 } 355 } 356 } 357 } 358 getName()359 public String getName() { 360 return mName; 361 } 362 363 /** 364 * Returns the ATR of the Secure Element, or null if not available. 365 */ getAtr()366 public byte[] getAtr() { 367 if (!mIsConnected) { 368 return null; 369 } 370 371 try { 372 ArrayList<Byte> responseList = mSEHal.getAtr(); 373 if (responseList.isEmpty()) { 374 return null; 375 } 376 byte[] atr = arrayListToByteArray(responseList); 377 if (DEBUG) { 378 Log.i(mTag, "ATR : " + ByteArrayConverter.byteArrayToHexString(atr)); 379 } 380 return atr; 381 } catch (RemoteException e) { 382 Log.e(mTag, "Exception in getAtr()" + e); 383 return null; 384 } 385 } 386 387 /** 388 * Selects the default application on the basic channel. 389 * 390 * If there is an exception selecting the default application, select 391 * is performed with the default access control aid. 392 */ selectDefaultApplication()393 public void selectDefaultApplication() { 394 try { 395 select(null); 396 } catch (NoSuchElementException e) { 397 if (getAccessControlEnforcer() != null) { 398 try { 399 select(mAccessControlEnforcer.getDefaultAccessControlAid()); 400 } catch (Exception ignore) { 401 } 402 } 403 } catch (Exception ignore) { 404 } 405 } 406 select(byte[] aid)407 private void select(byte[] aid) throws IOException { 408 int commandSize = (aid == null ? 0 : aid.length) + 5; 409 byte[] selectCommand = new byte[commandSize]; 410 selectCommand[0] = 0x00; 411 selectCommand[1] = (byte) 0xA4; 412 selectCommand[2] = 0x04; 413 selectCommand[3] = 0x00; 414 if (aid != null && aid.length != 0) { 415 selectCommand[4] = (byte) aid.length; 416 System.arraycopy(aid, 0, selectCommand, 5, aid.length); 417 } else { 418 selectCommand[4] = 0x00; 419 } 420 byte[] selectResponse = transmit(selectCommand); 421 if (selectResponse.length < 2) { 422 selectResponse = null; 423 throw new NoSuchElementException("Response length is too small"); 424 } 425 int sw1 = selectResponse[selectResponse.length - 2] & 0xFF; 426 int sw2 = selectResponse[selectResponse.length - 1] & 0xFF; 427 if (sw1 != 0x90 || sw2 != 0x00) { 428 selectResponse = null; 429 throw new NoSuchElementException("Status word is incorrect"); 430 } 431 } 432 433 /** 434 * Opens a Basic Channel with the given AID and P2 paramters 435 */ openBasicChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, int pid)436 public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2, 437 ISecureElementListener listener, String packageName, int pid) throws IOException, 438 NoSuchElementException { 439 if (aid != null && aid.length == 0) { 440 aid = null; 441 } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 442 throw new IllegalArgumentException("AID out of range"); 443 } else if (!mIsConnected) { 444 throw new IOException("Secure Element is not connected"); 445 } 446 447 ChannelAccess channelAccess = null; 448 if (packageName != null) { 449 Log.w(mTag, "Enable access control on basic channel for " + packageName); 450 SecureElementStatsLog.write( 451 SecureElementStatsLog.SE_OMAPI_REPORTED, 452 SecureElementStatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL, 453 mName, 454 packageName); 455 try { 456 // For application without privilege permission or carrier privilege, 457 // openBasicChannel with UICC terminals should be rejected. 458 channelAccess = setUpChannelAccess(aid, packageName, pid, true); 459 } catch (MissingResourceException e) { 460 return null; 461 } 462 } 463 464 synchronized (mLock) { 465 if (mChannels.get(0) != null) { 466 Log.e(mTag, "basic channel in use"); 467 return null; 468 } 469 if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) { 470 Log.e(mTag, "default application is not selected"); 471 return null; 472 } 473 474 ArrayList<byte[]> responseList = new ArrayList<byte[]>(); 475 byte[] status = new byte[1]; 476 477 try { 478 mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2, 479 new ISecureElement.openBasicChannelCallback() { 480 @Override 481 public void onValues(ArrayList<Byte> responseObject, byte halStatus) { 482 status[0] = halStatus; 483 responseList.add(arrayListToByteArray(responseObject)); 484 return; 485 } 486 }); 487 } catch (RemoteException e) { 488 throw new IOException(e.getMessage()); 489 } 490 491 byte[] selectResponse = responseList.get(0); 492 if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 493 return null; 494 } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 495 throw new UnsupportedOperationException("OpenBasicChannel() failed"); 496 } else if (status[0] == SecureElementStatus.IOERROR) { 497 throw new IOException("OpenBasicChannel() failed"); 498 } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 499 throw new NoSuchElementException("OpenBasicChannel() failed"); 500 } 501 502 Channel basicChannel = new Channel(session, this, 0, selectResponse, aid, 503 listener); 504 basicChannel.setChannelAccess(channelAccess); 505 506 if (aid != null) { 507 mDefaultApplicationSelectedOnBasicChannel = false; 508 } 509 mChannels.put(0, basicChannel); 510 return basicChannel; 511 } 512 } 513 514 /** 515 * Opens a logical Channel without Channel Access initialization. 516 */ openLogicalChannelWithoutChannelAccess(byte[] aid)517 public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException, 518 NoSuchElementException { 519 return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0); 520 } 521 522 /** 523 * Opens a logical Channel with AID. 524 */ openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, int pid)525 public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, 526 ISecureElementListener listener, String packageName, int pid) throws IOException, 527 NoSuchElementException { 528 if (aid != null && aid.length == 0) { 529 aid = null; 530 } else if (aid != null && (aid.length < 5 || aid.length > 16)) { 531 throw new IllegalArgumentException("AID out of range"); 532 } else if (!mIsConnected) { 533 throw new IOException("Secure Element is not connected"); 534 } 535 536 ChannelAccess channelAccess = null; 537 if (packageName != null) { 538 Log.w(mTag, "Enable access control on logical channel for " + packageName); 539 SecureElementStatsLog.write( 540 SecureElementStatsLog.SE_OMAPI_REPORTED, 541 SecureElementStatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL, 542 mName, 543 packageName); 544 try { 545 channelAccess = setUpChannelAccess(aid, packageName, pid, false); 546 } catch (MissingResourceException | UnsupportedOperationException e) { 547 return null; 548 } 549 } 550 551 synchronized (mLock) { 552 LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 553 byte[] status = new byte[1]; 554 555 try { 556 mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2, 557 new ISecureElement.openLogicalChannelCallback() { 558 @Override 559 public void onValues(LogicalChannelResponse response, byte halStatus) { 560 status[0] = halStatus; 561 responseArray[0] = response; 562 return; 563 } 564 }); 565 } catch (RemoteException e) { 566 throw new IOException(e.getMessage()); 567 } 568 569 if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) { 570 return null; 571 } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) { 572 throw new UnsupportedOperationException("OpenLogicalChannel() failed"); 573 } else if (status[0] == SecureElementStatus.IOERROR) { 574 throw new IOException("OpenLogicalChannel() failed"); 575 } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) { 576 throw new NoSuchElementException("OpenLogicalChannel() failed"); 577 } 578 if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) { 579 return null; 580 } 581 int channelNumber = responseArray[0].channelNumber; 582 byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse); 583 Channel logicalChannel = new Channel(session, this, channelNumber, 584 selectResponse, aid, listener); 585 logicalChannel.setChannelAccess(channelAccess); 586 587 mChannels.put(channelNumber, logicalChannel); 588 return logicalChannel; 589 } 590 } 591 592 /** 593 * Returns true if the given AID can be selected on the Terminal 594 */ isAidSelectable(byte[] aid)595 public boolean isAidSelectable(byte[] aid) { 596 if (aid == null) { 597 throw new NullPointerException("aid must not be null"); 598 } else if (!mIsConnected) { 599 Log.e(mTag, "Secure Element is not connected"); 600 return false; 601 } 602 603 synchronized (mLock) { 604 LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1]; 605 byte[] status = new byte[1]; 606 try { 607 mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00, 608 new ISecureElement.openLogicalChannelCallback() { 609 @Override 610 public void onValues(LogicalChannelResponse response, byte halStatus) { 611 status[0] = halStatus; 612 responseArray[0] = response; 613 return; 614 } 615 }); 616 if (status[0] == SecureElementStatus.SUCCESS) { 617 mSEHal.closeChannel(responseArray[0].channelNumber); 618 return true; 619 } 620 return false; 621 } catch (RemoteException e) { 622 Log.e(mTag, "Error in isAidSelectable() returning false" + e); 623 return false; 624 } 625 } 626 } 627 628 /** 629 * Transmits the specified command and returns the response. 630 * 631 * @param cmd the command APDU to be transmitted. 632 * @return the response received. 633 */ transmit(byte[] cmd)634 public byte[] transmit(byte[] cmd) throws IOException { 635 if (!mIsConnected) { 636 Log.e(mTag, "Secure Element is not connected"); 637 throw new IOException("Secure Element is not connected"); 638 } 639 640 byte[] rsp = transmitInternal(cmd); 641 int sw1 = rsp[rsp.length - 2] & 0xFF; 642 int sw2 = rsp[rsp.length - 1] & 0xFF; 643 644 if (sw1 == 0x6C) { 645 cmd[cmd.length - 1] = rsp[rsp.length - 1]; 646 rsp = transmit(cmd); 647 } else if (sw1 == 0x61) { 648 do { 649 byte[] getResponseCmd = new byte[]{ 650 cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2 651 }; 652 byte[] tmp = transmitInternal(getResponseCmd); 653 byte[] aux = rsp; 654 rsp = new byte[aux.length + tmp.length - 2]; 655 System.arraycopy(aux, 0, rsp, 0, aux.length - 2); 656 System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length); 657 sw1 = rsp[rsp.length - 2] & 0xFF; 658 sw2 = rsp[rsp.length - 1] & 0xFF; 659 } while (sw1 == 0x61); 660 } 661 return rsp; 662 } 663 transmitInternal(byte[] cmd)664 private byte[] transmitInternal(byte[] cmd) throws IOException { 665 ArrayList<Byte> response; 666 try { 667 response = mSEHal.transmit(byteArrayToArrayList(cmd)); 668 } catch (RemoteException e) { 669 throw new IOException(e.getMessage()); 670 } 671 if (response.isEmpty()) { 672 throw new IOException("Error in transmit()"); 673 } 674 byte[] rsp = arrayListToByteArray(response); 675 if (DEBUG) { 676 Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd)); 677 Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp)); 678 } 679 return rsp; 680 } 681 682 /** 683 * Checks if the application is authorized to receive the transaction event. 684 */ isNfcEventAllowed(PackageManager packageManager, byte[] aid, String[] packageNames)685 public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid, 686 String[] packageNames) { 687 if (!mIsConnected) { 688 // Return if not connected 689 return null; 690 } 691 // Return if the access control enforcer failed in previous attempt or no rule was found. 692 if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) { 693 Log.i(mTag, "isNfcEventAllowed: No access rules for checking."); 694 return null; 695 } 696 mAccessControlEnforcer.setPackageManager(packageManager); 697 698 synchronized (mLock) { 699 try { 700 return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames); 701 } catch (Exception e) { 702 Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage()); 703 return null; 704 } 705 } 706 } 707 708 /** 709 * Returns true if the Secure Element is present 710 */ isSecureElementPresent()711 public boolean isSecureElementPresent() { 712 try { 713 return mSEHal.isCardPresent(); 714 } catch (RemoteException e) { 715 Log.e(mTag, "Error in isSecureElementPresent() " + e); 716 return false; 717 } 718 } 719 720 /** 721 * Reset the Secure Element. Return true if success, false otherwise. 722 */ reset()723 public boolean reset() { 724 if (mSEHal12 == null) { 725 return false; 726 } 727 mContext.enforceCallingOrSelfPermission( 728 android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION, 729 "Need SECURE_ELEMENT_PRIVILEGED_OPERATION permission"); 730 731 try { 732 byte status = mSEHal12.reset(); 733 // Successfully trigger reset. HAL service should send onStateChange 734 // after secure element reset and initialization process complete 735 if (status == SecureElementStatus.SUCCESS) { 736 return true; 737 } 738 Log.e(mTag, "Error reseting terminal " + mName); 739 } catch (RemoteException e) { 740 Log.e(mTag, "Exception in reset()" + e); 741 } 742 return false; 743 } 744 745 /** 746 * Initialize the Access Control and set up the channel access. 747 */ setUpChannelAccess(byte[] aid, String packageName, int pid, boolean isBasicChannel)748 private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid, 749 boolean isBasicChannel) throws IOException, MissingResourceException { 750 boolean checkRefreshTag = true; 751 if (isPrivilegedApplication(packageName)) { 752 return ChannelAccess.getPrivilegeAccess(packageName, pid); 753 } 754 // Attempt to initialize the access control enforcer if it failed 755 // due to a kind of temporary failure or no rule was found in the previous attempt. 756 // For privilege access, do not attempt to initialize the access control enforcer 757 // if no rule was found in the previous attempt. 758 if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) { 759 initializeAccessControl(); 760 // Just finished to initialize the access control enforcer. 761 // It is too much to check the refresh tag in this case. 762 checkRefreshTag = false; 763 } 764 mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); 765 766 // Check carrier privilege when AID is not ISD-R 767 if (getName().startsWith(SecureElementService.UICC_TERMINAL) 768 && !Arrays.equals(aid, ISD_R_AID)) { 769 try { 770 PackageManager pm = mContext.getPackageManager(); 771 if (pm != null) { 772 PackageInfo pkgInfo = 773 pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 774 // Do not check the refresh tag for carrier privilege 775 if (mAccessControlEnforcer.checkCarrierPrivilege(pkgInfo, false)) { 776 Log.i(mTag, "setUp PrivilegeAccess for CarrierPrivilegeApplication. "); 777 return ChannelAccess.getCarrierPrivilegeAccess(packageName, pid); 778 } 779 } 780 } catch (NameNotFoundException ne) { 781 Log.e(mTag, "checkCarrierPrivilege(): packageInfo is not found. "); 782 } catch (Exception e) { 783 Log.e(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage()); 784 } 785 if (isBasicChannel) { 786 throw new MissingResourceException("openBasicChannel is not allowed.", "", ""); 787 } else if (aid == null) { 788 // openLogicalChannel with null aid is only allowed for privilege applications 789 throw new UnsupportedOperationException( 790 "null aid is not accepted in UICC terminal."); 791 } 792 } 793 794 synchronized (mLock) { 795 try { 796 ChannelAccess channelAccess = 797 mAccessControlEnforcer.setUpChannelAccess(aid, packageName, 798 checkRefreshTag); 799 channelAccess.setCallingPid(pid); 800 return channelAccess; 801 } catch (IOException | MissingResourceException e) { 802 throw e; 803 } catch (Exception e) { 804 throw new SecurityException("Exception in setUpChannelAccess()" + e); 805 } 806 } 807 } 808 809 /** 810 * Initializes the Access Control for this Terminal 811 */ initializeAccessControl()812 private synchronized void initializeAccessControl() throws IOException, 813 MissingResourceException { 814 synchronized (mLock) { 815 if (mAccessControlEnforcer == null) { 816 mAccessControlEnforcer = new AccessControlEnforcer(this); 817 } 818 try { 819 mAccessControlEnforcer.initialize(); 820 } catch (IOException | MissingResourceException e) { 821 // Retrieving access rules failed because of an IO error happened between 822 // the terminal and the secure element or the lack of a logical channel available. 823 // It might be a temporary failure, so the terminal shall attempt to cache 824 // the access rules again later. 825 mAccessControlEnforcer = null; 826 throw e; 827 } 828 } 829 } 830 831 /** 832 * Checks if Secure Element Privilege permission exists for the given package 833 */ isPrivilegedApplication(String packageName)834 private boolean isPrivilegedApplication(String packageName) { 835 PackageManager pm = mContext.getPackageManager(); 836 if (pm != null) { 837 return (pm.checkPermission(SECURE_ELEMENT_PRIVILEGED_OPERATION_PERMISSION, 838 packageName) == PackageManager.PERMISSION_GRANTED); 839 } 840 return false; 841 } 842 getAccessControlEnforcer()843 public AccessControlEnforcer getAccessControlEnforcer() { 844 return mAccessControlEnforcer; 845 } 846 getContext()847 public Context getContext() { 848 return mContext; 849 } 850 851 /** 852 * Checks if Carrier Privilege exists for the given package 853 */ checkCarrierPrivilegeRules(PackageInfo pInfo)854 public boolean checkCarrierPrivilegeRules(PackageInfo pInfo) { 855 boolean checkRefreshTag = true; 856 if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) { 857 try { 858 initializeAccessControl(); 859 } catch (IOException e) { 860 return false; 861 } 862 checkRefreshTag = false; 863 } 864 mAccessControlEnforcer.setPackageManager(mContext.getPackageManager()); 865 866 synchronized (mLock) { 867 try { 868 return mAccessControlEnforcer.checkCarrierPrivilege(pInfo, checkRefreshTag); 869 } catch (Exception e) { 870 Log.i(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage()); 871 return false; 872 } 873 } 874 } 875 876 /** Dump data for debug purpose . */ dump(PrintWriter writer)877 public void dump(PrintWriter writer) { 878 writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName); 879 writer.println(); 880 881 writer.println("mIsConnected:" + mIsConnected); 882 writer.println(); 883 884 /* Dump the list of currunlty openned channels */ 885 writer.println("List of open channels:"); 886 887 for (Channel channel : mChannels.values()) { 888 writer.println("channel " + channel.getChannelNumber() + ": "); 889 writer.println("package: " + channel.getChannelAccess().getPackageName()); 890 writer.println("pid: " + channel.getChannelAccess().getCallingPid()); 891 writer.println("aid selected: " + channel.hasSelectedAid()); 892 writer.println("basic channel: " + channel.isBasicChannel()); 893 writer.println(); 894 } 895 writer.println(); 896 897 /* Dump ACE data */ 898 if (mAccessControlEnforcer != null) { 899 mAccessControlEnforcer.dump(writer); 900 } 901 } 902 903 // Implementation of the SecureElement Reader interface according to OMAPI. 904 final class SecureElementReader extends ISecureElementReader.Stub { 905 906 private final SecureElementService mService; 907 private final ArrayList<SecureElementSession> mSessions = 908 new ArrayList<SecureElementSession>(); 909 SecureElementReader(SecureElementService service)910 SecureElementReader(SecureElementService service) { 911 mService = service; 912 } 913 getAtr()914 public byte[] getAtr() { 915 return Terminal.this.getAtr(); 916 } 917 918 @Override isSecureElementPresent()919 public boolean isSecureElementPresent() throws RemoteException { 920 return Terminal.this.isSecureElementPresent(); 921 } 922 923 @Override closeSessions()924 public void closeSessions() { 925 synchronized (mLock) { 926 while (mSessions.size() > 0) { 927 try { 928 mSessions.get(0).close(); 929 } catch (Exception ignore) { 930 } 931 } 932 mSessions.clear(); 933 } 934 } 935 removeSession(SecureElementSession session)936 public void removeSession(SecureElementSession session) { 937 if (session == null) { 938 throw new NullPointerException("session is null"); 939 } 940 941 synchronized (mLock) { 942 mSessions.remove(session); 943 if (mSessions.size() == 0) { 944 mDefaultApplicationSelectedOnBasicChannel = true; 945 } 946 } 947 } 948 949 @Override openSession()950 public ISecureElementSession openSession() throws RemoteException { 951 if (!isSecureElementPresent()) { 952 throw new ServiceSpecificException(SEService.IO_ERROR, 953 "Secure Element is not present."); 954 } 955 956 synchronized (mLock) { 957 SecureElementSession session = mService.new SecureElementSession(this); 958 mSessions.add(session); 959 return session; 960 } 961 } 962 getTerminal()963 Terminal getTerminal() { 964 return Terminal.this; 965 } 966 967 @Override reset()968 public boolean reset() { 969 return Terminal.this.reset(); 970 } 971 } 972 } 973