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) 2014-2017, The Linux Foundation. 18 */ 19 /* 20 * Contributed by: Giesecke & Devrient GmbH. 21 */ 22 23 package com.android.se; 24 25 import android.app.Service; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.PackageManager; 31 import android.os.Binder; 32 import android.os.Build; 33 import android.os.IBinder; 34 import android.os.RemoteException; 35 import android.os.ServiceManager; 36 import android.os.ServiceSpecificException; 37 import android.os.UserHandle; 38 import android.se.omapi.ISecureElementChannel; 39 import android.se.omapi.ISecureElementListener; 40 import android.se.omapi.ISecureElementReader; 41 import android.se.omapi.ISecureElementService; 42 import android.se.omapi.ISecureElementSession; 43 import android.se.omapi.SEService; 44 import android.telephony.TelephonyManager; 45 import android.util.Log; 46 47 import com.android.se.Terminal.SecureElementReader; 48 import com.android.se.internal.ByteArrayConverter; 49 import com.android.se.security.HalRefDoParser; 50 51 import java.io.FileDescriptor; 52 import java.io.IOException; 53 import java.io.PrintWriter; 54 import java.security.AccessControlException; 55 import java.util.ArrayList; 56 import java.util.LinkedHashMap; 57 import java.util.List; 58 import java.util.NoSuchElementException; 59 import java.util.Vector; 60 61 /** 62 * Underlying implementation for OMAPI SEService 63 */ 64 public final class SecureElementService extends Service { 65 66 public static final String UICC_TERMINAL = "SIM"; 67 public static final String ESE_TERMINAL = "eSE"; 68 public static final String VSTABLE_SECURE_ELEMENT_SERVICE = 69 "android.se.omapi.ISecureElementService/default"; 70 private final String mTag = "SecureElementService"; 71 private static final boolean DEBUG = Build.isDebuggable(); 72 // LinkedHashMap will maintain the order of insertion 73 private LinkedHashMap<String, Terminal> mTerminals = new LinkedHashMap<String, Terminal>(); 74 private int mActiveSimCount = 0; 75 private class SecureElementServiceBinder extends ISecureElementService.Stub { 76 77 @Override getReaders()78 public String[] getReaders() throws RemoteException { 79 try { 80 // This determines calling process is application/framework 81 String packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 82 Log.d(mTag, "getReaders() for " + packageName); 83 return mTerminals.keySet().toArray(new String[mTerminals.size()]); 84 } catch (AccessControlException e) { 85 // since packagename not found, UUID might be used to access 86 // allow only to use eSE readers with UUID based requests 87 Vector<String> eSEReaders = new Vector<String>(); 88 for (String reader : mTerminals.keySet()) { 89 if (reader.startsWith(SecureElementService.ESE_TERMINAL)) { 90 Log.i(mTag, "Adding Reader: " + reader); 91 eSEReaders.add(reader); 92 } 93 } 94 95 return eSEReaders.toArray(new String[eSEReaders.size()]); 96 } 97 } 98 99 @Override getReader(String reader)100 public ISecureElementReader getReader(String reader) throws RemoteException { 101 Log.d(mTag, "getReader() " + reader); 102 Terminal terminal = null; 103 try { 104 // This determines calling process is application/framework 105 String packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 106 Log.d(mTag, "getReader() for " + packageName); 107 terminal = getTerminal(reader); 108 } catch (AccessControlException e) { 109 // since packagename not found, UUID might be used to access 110 // allow only to use eSE readers with UUID based requests 111 if (reader.startsWith(SecureElementService.ESE_TERMINAL)) { 112 terminal = getTerminal(reader); 113 } else { 114 Log.d(mTag, "only eSE readers can access SE using UUID"); 115 } 116 } 117 if (terminal != null) { 118 return terminal.new SecureElementReader(SecureElementService.this); 119 } else { 120 throw new IllegalArgumentException("Reader: " + reader + " not supported"); 121 } 122 } 123 124 @Override isNfcEventAllowed(String reader, byte[] aid, String[] packageNames, int userId)125 public synchronized boolean[] isNfcEventAllowed(String reader, byte[] aid, 126 String[] packageNames, int userId) throws RemoteException { 127 if (aid == null || aid.length == 0) { 128 aid = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}; 129 } 130 if (aid.length < 5 || aid.length > 16) { 131 throw new IllegalArgumentException("AID out of range"); 132 } 133 if (packageNames == null || packageNames.length == 0) { 134 throw new IllegalArgumentException("package names not specified"); 135 } 136 Terminal terminal = getTerminal(reader); 137 Context context; 138 try { 139 context = createContextAsUser(UserHandle.of(userId), /*flags=*/0); 140 } catch (IllegalStateException e) { 141 context = null; 142 Log.d(mTag, "fail to call createContextAsUser for userId:" + userId); 143 } 144 return context == null ? null : terminal.isNfcEventAllowed( 145 context.getPackageManager(), aid, packageNames); 146 147 } 148 149 @Override dump(FileDescriptor fd, PrintWriter writer, String[] args)150 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 151 for (Terminal terminal : mTerminals.values()) { 152 terminal.dump(writer); 153 } 154 } 155 156 @Override getInterfaceHash()157 public String getInterfaceHash() { 158 return ISecureElementService.HASH; 159 } 160 161 @Override getInterfaceVersion()162 public int getInterfaceVersion() { 163 return ISecureElementService.VERSION; 164 } 165 } 166 167 private final ISecureElementService.Stub mSecureElementServiceBinder = 168 new SecureElementServiceBinder(); 169 170 private final ISecureElementService.Stub mSecureElementServiceBinderVntf = 171 new SecureElementServiceBinder(); 172 SecureElementService()173 public SecureElementService() { 174 super(); 175 } 176 initialize()177 private void initialize() { 178 // listen for events 179 IntentFilter intentFilter = new IntentFilter(); 180 intentFilter.addAction(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED); 181 this.registerReceiver(mMultiSimConfigChangedReceiver, intentFilter); 182 } 183 184 /** Returns the terminal from the Reader name. */ getTerminal(String reader)185 private Terminal getTerminal(String reader) { 186 if (reader == null) { 187 throw new NullPointerException("reader must not be null"); 188 } 189 if (reader.equals("SIM")) { 190 reader = "SIM1"; 191 } 192 Terminal terminal = mTerminals.get(reader); 193 if (terminal == null) { 194 throw new IllegalArgumentException("Reader: " + reader + " doesn't exist"); 195 } 196 return terminal; 197 } 198 199 @Override onBind(Intent intent)200 public IBinder onBind(Intent intent) { 201 Log.i(mTag, Thread.currentThread().getName() + " onBind"); 202 if (ISecureElementService.class.getName().equals(intent.getAction())) { 203 return mSecureElementServiceBinder; 204 } 205 return null; 206 } 207 208 @Override onCreate()209 public void onCreate() { 210 super.onCreate(); 211 Log.i(mTag, Thread.currentThread().getName() + " onCreate"); 212 initialize(); 213 createTerminals(); 214 215 // Add vendor stable service only if it is configured 216 if (getResources().getBoolean(R.bool.secure_element_vintf_enabled)) { 217 ServiceManager.addService(VSTABLE_SECURE_ELEMENT_SERVICE, 218 mSecureElementServiceBinderVntf); 219 } 220 221 // Since ISecureElementService is marked with VINTF stability 222 // to use this same interface within the system partition, will use 223 // forceDowngradeToSystemStability and register it. 224 mSecureElementServiceBinder.forceDowngradeToSystemStability(); 225 ServiceManager.addService(Context.SECURE_ELEMENT_SERVICE, mSecureElementServiceBinder); 226 } 227 228 /** 229 * In case the onDestroy is called, we free the memory and 230 * close all the channels. 231 */ onDestroy()232 public void onDestroy() { 233 super.onDestroy(); 234 Log.i(mTag, "onDestroy"); 235 for (Terminal terminal : mTerminals.values()) { 236 terminal.closeChannels(); 237 terminal.close(); 238 } 239 if (mMultiSimConfigChangedReceiver != null) { 240 this.unregisterReceiver(mMultiSimConfigChangedReceiver); 241 } 242 } 243 addTerminals(String terminalName)244 private void addTerminals(String terminalName) { 245 int index = 1; 246 String name = null; 247 if (terminalName.startsWith(SecureElementService.UICC_TERMINAL)) { 248 index = mActiveSimCount + 1; 249 } 250 try { 251 do { 252 name = terminalName + Integer.toString(index); 253 Terminal terminal = new Terminal(name, this); 254 255 Log.i(mTag, "Check if terminal " + name + " is available."); 256 // Only retry on fail for the first terminal of each type. 257 terminal.initialize(index == 1); 258 mTerminals.put(name, terminal); 259 if (terminalName.equals(UICC_TERMINAL)) { 260 mActiveSimCount = index; 261 } 262 } while (++index > 0); 263 } catch (NoSuchElementException e) { 264 Log.i(mTag, "No HAL implementation for " + name); 265 } catch (RemoteException | RuntimeException e) { 266 Log.e(mTag, "Error in getService() for " + name); 267 } 268 } 269 createTerminals()270 private void createTerminals() { 271 // Check for all SE HAL implementations 272 addTerminals(ESE_TERMINAL); 273 addTerminals(UICC_TERMINAL); 274 } 275 refreshUiccTerminals(int activeSimCount)276 private void refreshUiccTerminals(int activeSimCount) { 277 String name = null; 278 synchronized (this) { 279 if (activeSimCount < mActiveSimCount) { 280 // Remove non-supported UICC terminals 281 for (int i = activeSimCount + 1; i <= mActiveSimCount; i++) { 282 name = UICC_TERMINAL + Integer.toString(i); 283 Terminal terminal = mTerminals.get(name); 284 if (terminal != null) { 285 terminal.closeChannels(); 286 terminal.close(); 287 } 288 mTerminals.remove(name); 289 Log.i(mTag, name + " is removed from available Terminals"); 290 } 291 mActiveSimCount = activeSimCount; 292 } else if (activeSimCount > mActiveSimCount) { 293 // Try to initialize new UICC terminals 294 addTerminals(UICC_TERMINAL); 295 } 296 } 297 } 298 getPackageNameFromCallingUid(int uid)299 private String getPackageNameFromCallingUid(int uid) { 300 PackageManager packageManager = getPackageManager(); 301 if (packageManager != null) { 302 String[] packageName = packageManager.getPackagesForUid(uid); 303 if (packageName != null && packageName.length > 0) { 304 return packageName[0]; 305 } 306 } 307 throw new AccessControlException("PackageName can not be determined"); 308 } 309 getUUIDFromCallingUid(int uid)310 private byte[] getUUIDFromCallingUid(int uid) { 311 byte[] uuid = HalRefDoParser.getInstance().findUUID(Binder.getCallingUid()); 312 313 if (uuid != null) { 314 return uuid; 315 } 316 317 return null; 318 } 319 320 final class SecureElementSession extends ISecureElementSession.Stub { 321 322 private final SecureElementReader mReader; 323 /** List of open channels in use of by this client. */ 324 private final List<Channel> mChannels = new ArrayList<>(); 325 private final Object mLock = new Object(); 326 private boolean mIsClosed; 327 private byte[] mAtr; 328 SecureElementSession(SecureElementReader reader)329 SecureElementSession(SecureElementReader reader) { 330 if (reader == null) { 331 throw new NullPointerException("SecureElementReader cannot be null"); 332 } 333 mReader = reader; 334 mAtr = mReader.getAtr(); 335 mIsClosed = false; 336 } 337 getReader()338 public ISecureElementReader getReader() throws RemoteException { 339 return mReader; 340 } 341 342 @Override getAtr()343 public byte[] getAtr() throws RemoteException { 344 return mAtr; 345 } 346 347 @Override close()348 public void close() throws RemoteException { 349 closeChannels(); 350 mReader.removeSession(this); 351 synchronized (mLock) { 352 mIsClosed = true; 353 } 354 } 355 removeChannel(Channel channel)356 void removeChannel(Channel channel) { 357 synchronized (mLock) { 358 if (mChannels != null) { 359 mChannels.remove(channel); 360 } 361 } 362 } 363 364 @Override closeChannels()365 public void closeChannels() throws RemoteException { 366 synchronized (mLock) { 367 while (mChannels.size() > 0) { 368 try { 369 mChannels.get(0).close(); 370 } catch (Exception ignore) { 371 Log.e(mTag, "SecureElementSession Channel - close Exception " 372 + ignore.getMessage()); 373 } 374 } 375 } 376 } 377 378 @Override isClosed()379 public boolean isClosed() throws RemoteException { 380 synchronized (mLock) { 381 return mIsClosed; 382 } 383 } 384 385 @Override openBasicChannel(byte[] aid, byte p2, ISecureElementListener listener)386 public ISecureElementChannel openBasicChannel(byte[] aid, byte p2, 387 ISecureElementListener listener) throws RemoteException { 388 if (DEBUG) { 389 Log.i(mTag, "openBasicChannel() AID = " 390 + ByteArrayConverter.byteArrayToHexString(aid) + ", P2 = " + p2); 391 } 392 if (isClosed()) { 393 throw new IllegalStateException("Session is closed"); 394 } else if (listener == null) { 395 throw new NullPointerException("listener must not be null"); 396 } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08) 397 && (p2 != (byte) 0x0C)) { 398 throw new UnsupportedOperationException("p2 not supported: " 399 + String.format("%02x ", p2 & 0xFF)); 400 } 401 402 String packageName = null; 403 byte[] uuid = null; 404 try { 405 packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 406 } catch (AccessControlException e) { 407 // Since packageName not found for calling process, try to find UUID mapping 408 // provided by vendors for the calling process UID 409 // (vendor provide UUID mapping for native services to access secure element) 410 Log.d(mTag, "openBasicChannel() trying to find mapping uuid"); 411 // Allow UUID based access only on embedded secure elements eSE. 412 if (mReader.getTerminal().getName().startsWith(SecureElementService.ESE_TERMINAL)) { 413 uuid = getUUIDFromCallingUid(Binder.getCallingUid()); 414 } 415 if (uuid == null) { 416 Log.e(mTag, "openBasicChannel() uuid mapping for calling uid is not found"); 417 throw e; 418 } 419 } 420 Channel channel = null; 421 422 try { 423 channel = mReader.getTerminal().openBasicChannel(this, aid, p2, listener, 424 packageName, uuid, Binder.getCallingPid()); 425 } catch (IOException e) { 426 throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage()); 427 } catch (NoSuchElementException e) { 428 throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage()); 429 } 430 431 if (channel == null) { 432 Log.i(mTag, "OpenBasicChannel() - returning null"); 433 return null; 434 } 435 Log.i(mTag, "Open basic channel success. Channel: " 436 + channel.getChannelNumber()); 437 438 synchronized (mLock) { 439 mChannels.add(channel); 440 } 441 return channel.new SecureElementChannel(); 442 } 443 444 @Override openLogicalChannel(byte[] aid, byte p2, ISecureElementListener listener)445 public ISecureElementChannel openLogicalChannel(byte[] aid, byte p2, 446 ISecureElementListener listener) throws RemoteException { 447 if (DEBUG) { 448 Log.i(mTag, "openLogicalChannel() AID = " 449 + ByteArrayConverter.byteArrayToHexString(aid) + ", P2 = " + p2); 450 } 451 if (isClosed()) { 452 throw new IllegalStateException("Session is closed"); 453 } else if (listener == null) { 454 throw new NullPointerException("listener must not be null"); 455 } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08) 456 && (p2 != (byte) 0x0C)) { 457 throw new UnsupportedOperationException("p2 not supported: " 458 + String.format("%02x ", p2 & 0xFF)); 459 } 460 461 String packageName = null; 462 byte[] uuid = null; 463 try { 464 packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 465 } catch (AccessControlException e) { 466 // Since packageName not found for calling process, try to find UUID mapping 467 // provided by vendors for the calling process UID 468 // (vendor provide UUID mapping for native services to access secure element) 469 Log.d(mTag, "openLogicalChannel() trying to find mapping uuid"); 470 // Allow UUID based access only on embedded secure elements eSE. 471 if (mReader.getTerminal().getName().startsWith(SecureElementService.ESE_TERMINAL)) { 472 uuid = getUUIDFromCallingUid(Binder.getCallingUid()); 473 } 474 if (uuid == null) { 475 Log.e(mTag, "openLogicalChannel() uuid mapping for calling uid is not found"); 476 throw e; 477 } 478 } 479 Channel channel = null; 480 481 try { 482 channel = mReader.getTerminal().openLogicalChannel(this, aid, p2, listener, 483 packageName, uuid, Binder.getCallingPid()); 484 } catch (IOException e) { 485 throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage()); 486 } catch (NoSuchElementException e) { 487 throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage()); 488 } 489 490 if (channel == null) { 491 Log.i(mTag, "openLogicalChannel() - returning null"); 492 return null; 493 } 494 Log.i(mTag, "openLogicalChannel() Success. Channel: " 495 + channel.getChannelNumber()); 496 497 synchronized (mLock) { 498 mChannels.add(channel); 499 } 500 return channel.new SecureElementChannel(); 501 } 502 503 @Override getInterfaceHash()504 public String getInterfaceHash() { 505 return ISecureElementSession.HASH; 506 } 507 508 @Override getInterfaceVersion()509 public int getInterfaceVersion() { 510 return ISecureElementSession.VERSION; 511 } 512 } 513 514 private final BroadcastReceiver mMultiSimConfigChangedReceiver = new BroadcastReceiver() { 515 @Override 516 public void onReceive(Context context, Intent intent) { 517 String action = intent.getAction(); 518 if (action.equals(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED)) { 519 int activeSimCount = 520 intent.getIntExtra(TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 1); 521 Log.i(mTag, "received action MultiSimConfigChanged. Refresh UICC terminals"); 522 Log.i(mTag, "Current ActiveSimCount:" + activeSimCount 523 + ". Previous ActiveSimCount:" + mActiveSimCount); 524 525 // Check for any change to UICC SE HAL implementations 526 refreshUiccTerminals(activeSimCount); 527 } 528 } 529 }; 530 } 531