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(uid); 312 return uuid; 313 } 314 315 final class SecureElementSession extends ISecureElementSession.Stub { 316 317 private final SecureElementReader mReader; 318 /** List of open channels in use of by this client. */ 319 private final List<Channel> mChannels = new ArrayList<>(); 320 private final Object mLock = new Object(); 321 private boolean mIsClosed; 322 private byte[] mAtr; 323 SecureElementSession(SecureElementReader reader)324 SecureElementSession(SecureElementReader reader) { 325 if (reader == null) { 326 throw new NullPointerException("SecureElementReader cannot be null"); 327 } 328 mReader = reader; 329 mAtr = mReader.getAtr(); 330 mIsClosed = false; 331 } 332 getReader()333 public ISecureElementReader getReader() throws RemoteException { 334 return mReader; 335 } 336 337 @Override getAtr()338 public byte[] getAtr() throws RemoteException { 339 return mAtr; 340 } 341 342 @Override close()343 public void close() throws RemoteException { 344 closeChannels(); 345 mReader.removeSession(this); 346 synchronized (mLock) { 347 mIsClosed = true; 348 } 349 } 350 removeChannel(Channel channel)351 void removeChannel(Channel channel) { 352 synchronized (mLock) { 353 if (mChannels != null) { 354 mChannels.remove(channel); 355 } 356 } 357 } 358 359 @Override closeChannels()360 public void closeChannels() throws RemoteException { 361 synchronized (mLock) { 362 while (mChannels.size() > 0) { 363 try { 364 mChannels.get(0).close(); 365 } catch (Exception ignore) { 366 Log.e(mTag, "SecureElementSession Channel - close Exception " 367 + ignore.getMessage()); 368 } 369 } 370 } 371 } 372 373 @Override isClosed()374 public boolean isClosed() throws RemoteException { 375 synchronized (mLock) { 376 return mIsClosed; 377 } 378 } 379 380 @Override openBasicChannel(byte[] aid, byte p2, ISecureElementListener listener)381 public ISecureElementChannel openBasicChannel(byte[] aid, byte p2, 382 ISecureElementListener listener) throws RemoteException { 383 if (DEBUG) { 384 Log.i(mTag, "openBasicChannel() AID = " 385 + ByteArrayConverter.byteArrayToHexString(aid) + ", P2 = " + p2); 386 } 387 if (isClosed()) { 388 throw new IllegalStateException("Session is closed"); 389 } else if (listener == null) { 390 throw new NullPointerException("listener must not be null"); 391 } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08) 392 && (p2 != (byte) 0x0C)) { 393 throw new UnsupportedOperationException("p2 not supported: " 394 + String.format("%02x ", p2 & 0xFF)); 395 } 396 397 String packageName = null; 398 byte[] uuid = null; 399 try { 400 packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 401 } catch (AccessControlException e) { 402 // Since packageName not found for calling process, try to find UUID mapping 403 // provided by vendors for the calling process UID 404 // (vendor provide UUID mapping for native services to access secure element) 405 Log.d(mTag, "openBasicChannel() trying to find mapping uuid"); 406 // Allow UUID based access only on embedded secure elements eSE. 407 if (mReader.getTerminal().getName().startsWith(SecureElementService.ESE_TERMINAL)) { 408 uuid = getUUIDFromCallingUid(Binder.getCallingUid()); 409 } 410 if (uuid == null) { 411 Log.e(mTag, "openBasicChannel() uuid mapping for calling uid is not found"); 412 throw e; 413 } 414 } 415 Channel channel = null; 416 417 try { 418 channel = mReader.getTerminal().openBasicChannel(this, aid, p2, listener, 419 packageName, uuid, Binder.getCallingPid()); 420 } catch (IOException e) { 421 throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage()); 422 } catch (NoSuchElementException e) { 423 throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage()); 424 } 425 426 if (channel == null) { 427 Log.i(mTag, "OpenBasicChannel() - returning null"); 428 return null; 429 } 430 Log.i(mTag, "Open basic channel success. Channel: " 431 + channel.getChannelNumber()); 432 433 synchronized (mLock) { 434 mChannels.add(channel); 435 } 436 return channel.new SecureElementChannel(); 437 } 438 439 @Override openLogicalChannel(byte[] aid, byte p2, ISecureElementListener listener)440 public ISecureElementChannel openLogicalChannel(byte[] aid, byte p2, 441 ISecureElementListener listener) throws RemoteException { 442 if (DEBUG) { 443 Log.i(mTag, "openLogicalChannel() AID = " 444 + ByteArrayConverter.byteArrayToHexString(aid) + ", P2 = " + p2); 445 } 446 if (isClosed()) { 447 throw new IllegalStateException("Session is closed"); 448 } else if (listener == null) { 449 throw new NullPointerException("listener must not be null"); 450 } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08) 451 && (p2 != (byte) 0x0C)) { 452 throw new UnsupportedOperationException("p2 not supported: " 453 + String.format("%02x ", p2 & 0xFF)); 454 } 455 456 String packageName = null; 457 byte[] uuid = null; 458 try { 459 packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 460 } catch (AccessControlException e) { 461 // Since packageName not found for calling process, try to find UUID mapping 462 // provided by vendors for the calling process UID 463 // (vendor provide UUID mapping for native services to access secure element) 464 Log.d(mTag, "openLogicalChannel() trying to find mapping uuid"); 465 // Allow UUID based access only on embedded secure elements eSE. 466 if (mReader.getTerminal().getName().startsWith(SecureElementService.ESE_TERMINAL)) { 467 uuid = getUUIDFromCallingUid(Binder.getCallingUid()); 468 } 469 if (uuid == null) { 470 Log.e(mTag, "openLogicalChannel() uuid mapping for calling uid is not found"); 471 throw e; 472 } 473 } 474 Channel channel = null; 475 476 try { 477 channel = mReader.getTerminal().openLogicalChannel(this, aid, p2, listener, 478 packageName, uuid, Binder.getCallingPid()); 479 } catch (IOException e) { 480 throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage()); 481 } catch (NoSuchElementException e) { 482 throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage()); 483 } 484 485 if (channel == null) { 486 Log.i(mTag, "openLogicalChannel() - returning null"); 487 return null; 488 } 489 Log.i(mTag, "openLogicalChannel() Success. Channel: " 490 + channel.getChannelNumber()); 491 492 synchronized (mLock) { 493 mChannels.add(channel); 494 } 495 return channel.new SecureElementChannel(); 496 } 497 498 @Override getInterfaceHash()499 public String getInterfaceHash() { 500 return ISecureElementSession.HASH; 501 } 502 503 @Override getInterfaceVersion()504 public int getInterfaceVersion() { 505 return ISecureElementSession.VERSION; 506 } 507 } 508 509 private final BroadcastReceiver mMultiSimConfigChangedReceiver = new BroadcastReceiver() { 510 @Override 511 public void onReceive(Context context, Intent intent) { 512 String action = intent.getAction(); 513 if (action.equals(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED)) { 514 int activeSimCount = 515 intent.getIntExtra(TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 1); 516 Log.i(mTag, "received action MultiSimConfigChanged. Refresh UICC terminals"); 517 Log.i(mTag, "Current ActiveSimCount:" + activeSimCount 518 + ". Previous ActiveSimCount:" + mActiveSimCount); 519 520 // Check for any change to UICC SE HAL implementations 521 refreshUiccTerminals(activeSimCount); 522 } 523 } 524 }; 525 } 526