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.IS_DEBUGGABLE; 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 Log.i(mTag, Thread.currentThread().getName() + " onCreate"); 211 initialize(); 212 createTerminals(); 213 214 // Add vendor stable service only if it is configured 215 if (getResources().getBoolean(R.bool.secure_element_vintf_enabled)) { 216 ServiceManager.addService(VSTABLE_SECURE_ELEMENT_SERVICE, 217 mSecureElementServiceBinderVntf); 218 } 219 220 // Since ISecureElementService is marked with VINTF stability 221 // to use this same interface within the system partition, will use 222 // forceDowngradeToSystemStability and register it. 223 mSecureElementServiceBinder.forceDowngradeToSystemStability(); 224 ServiceManager.addService(Context.SECURE_ELEMENT_SERVICE, mSecureElementServiceBinder); 225 } 226 227 /** 228 * In case the onDestroy is called, we free the memory and 229 * close all the channels. 230 */ onDestroy()231 public void onDestroy() { 232 Log.i(mTag, "onDestroy"); 233 for (Terminal terminal : mTerminals.values()) { 234 terminal.closeChannels(); 235 terminal.close(); 236 } 237 if (mMultiSimConfigChangedReceiver != null) { 238 this.unregisterReceiver(mMultiSimConfigChangedReceiver); 239 } 240 } 241 addTerminals(String terminalName)242 private void addTerminals(String terminalName) { 243 int index = 1; 244 String name = null; 245 if (terminalName.startsWith(SecureElementService.UICC_TERMINAL)) { 246 index = mActiveSimCount + 1; 247 } 248 try { 249 do { 250 name = terminalName + Integer.toString(index); 251 Terminal terminal = new Terminal(name, this); 252 253 Log.i(mTag, "Check if terminal " + name + " is available."); 254 // Only retry on fail for the first terminal of each type. 255 terminal.initialize(index == 1); 256 mTerminals.put(name, terminal); 257 if (terminalName.equals(UICC_TERMINAL)) { 258 mActiveSimCount = index; 259 } 260 } while (++index > 0); 261 } catch (NoSuchElementException e) { 262 Log.i(mTag, "No HAL implementation for " + name); 263 } catch (RemoteException | RuntimeException e) { 264 Log.e(mTag, "Error in getService() for " + name); 265 } 266 } 267 createTerminals()268 private void createTerminals() { 269 // Check for all SE HAL implementations 270 addTerminals(ESE_TERMINAL); 271 addTerminals(UICC_TERMINAL); 272 } 273 refreshUiccTerminals(int activeSimCount)274 private void refreshUiccTerminals(int activeSimCount) { 275 String name = null; 276 synchronized (this) { 277 if (activeSimCount < mActiveSimCount) { 278 // Remove non-supported UICC terminals 279 for (int i = activeSimCount + 1; i <= mActiveSimCount; i++) { 280 name = UICC_TERMINAL + Integer.toString(i); 281 Terminal terminal = mTerminals.get(name); 282 if (terminal != null) { 283 terminal.closeChannels(); 284 terminal.close(); 285 } 286 mTerminals.remove(name); 287 Log.i(mTag, name + " is removed from available Terminals"); 288 } 289 mActiveSimCount = activeSimCount; 290 } else if (activeSimCount > mActiveSimCount) { 291 // Try to initialize new UICC terminals 292 addTerminals(UICC_TERMINAL); 293 } 294 } 295 } 296 getPackageNameFromCallingUid(int uid)297 private String getPackageNameFromCallingUid(int uid) { 298 PackageManager packageManager = getPackageManager(); 299 if (packageManager != null) { 300 String[] packageName = packageManager.getPackagesForUid(uid); 301 if (packageName != null && packageName.length > 0) { 302 return packageName[0]; 303 } 304 } 305 throw new AccessControlException("PackageName can not be determined"); 306 } 307 getUUIDFromCallingUid(int uid)308 private byte[] getUUIDFromCallingUid(int uid) { 309 byte[] uuid = HalRefDoParser.getInstance().findUUID(Binder.getCallingUid()); 310 311 if (uuid != null) { 312 return uuid; 313 } 314 315 return null; 316 } 317 318 final class SecureElementSession extends ISecureElementSession.Stub { 319 320 private final SecureElementReader mReader; 321 /** List of open channels in use of by this client. */ 322 private final List<Channel> mChannels = new ArrayList<>(); 323 private final Object mLock = new Object(); 324 private boolean mIsClosed; 325 private byte[] mAtr; 326 SecureElementSession(SecureElementReader reader)327 SecureElementSession(SecureElementReader reader) { 328 if (reader == null) { 329 throw new NullPointerException("SecureElementReader cannot be null"); 330 } 331 mReader = reader; 332 mAtr = mReader.getAtr(); 333 mIsClosed = false; 334 } 335 getReader()336 public ISecureElementReader getReader() throws RemoteException { 337 return mReader; 338 } 339 340 @Override getAtr()341 public byte[] getAtr() throws RemoteException { 342 return mAtr; 343 } 344 345 @Override close()346 public void close() throws RemoteException { 347 closeChannels(); 348 mReader.removeSession(this); 349 synchronized (mLock) { 350 mIsClosed = true; 351 } 352 } 353 removeChannel(Channel channel)354 void removeChannel(Channel channel) { 355 synchronized (mLock) { 356 if (mChannels != null) { 357 mChannels.remove(channel); 358 } 359 } 360 } 361 362 @Override closeChannels()363 public void closeChannels() throws RemoteException { 364 synchronized (mLock) { 365 while (mChannels.size() > 0) { 366 try { 367 mChannels.get(0).close(); 368 } catch (Exception ignore) { 369 Log.e(mTag, "SecureElementSession Channel - close Exception " 370 + ignore.getMessage()); 371 } 372 } 373 } 374 } 375 376 @Override isClosed()377 public boolean isClosed() throws RemoteException { 378 synchronized (mLock) { 379 return mIsClosed; 380 } 381 } 382 383 @Override openBasicChannel(byte[] aid, byte p2, ISecureElementListener listener)384 public ISecureElementChannel openBasicChannel(byte[] aid, byte p2, 385 ISecureElementListener listener) throws RemoteException { 386 if (DEBUG) { 387 Log.i(mTag, "openBasicChannel() AID = " 388 + ByteArrayConverter.byteArrayToHexString(aid) + ", P2 = " + p2); 389 } 390 if (isClosed()) { 391 throw new IllegalStateException("Session is closed"); 392 } else if (listener == null) { 393 throw new NullPointerException("listener must not be null"); 394 } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08) 395 && (p2 != (byte) 0x0C)) { 396 throw new UnsupportedOperationException("p2 not supported: " 397 + String.format("%02x ", p2 & 0xFF)); 398 } 399 400 String packageName = null; 401 byte[] uuid = null; 402 try { 403 packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 404 } catch (AccessControlException e) { 405 // Since packageName not found for calling process, try to find UUID mapping 406 // provided by vendors for the calling process UID 407 // (vendor provide UUID mapping for native services to access secure element) 408 Log.d(mTag, "openBasicChannel() trying to find mapping uuid"); 409 // Allow UUID based access only on embedded secure elements eSE. 410 if (mReader.getTerminal().getName().startsWith(SecureElementService.ESE_TERMINAL)) { 411 uuid = getUUIDFromCallingUid(Binder.getCallingUid()); 412 } 413 if (uuid == null) { 414 Log.e(mTag, "openBasicChannel() uuid mapping for calling uid is not found"); 415 throw e; 416 } 417 } 418 Channel channel = null; 419 420 try { 421 channel = mReader.getTerminal().openBasicChannel(this, aid, p2, listener, 422 packageName, uuid, Binder.getCallingPid()); 423 } catch (IOException e) { 424 throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage()); 425 } catch (NoSuchElementException e) { 426 throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage()); 427 } 428 429 if (channel == null) { 430 Log.i(mTag, "OpenBasicChannel() - returning null"); 431 return null; 432 } 433 Log.i(mTag, "Open basic channel success. Channel: " 434 + channel.getChannelNumber()); 435 436 synchronized (mLock) { 437 mChannels.add(channel); 438 } 439 return channel.new SecureElementChannel(); 440 } 441 442 @Override openLogicalChannel(byte[] aid, byte p2, ISecureElementListener listener)443 public ISecureElementChannel openLogicalChannel(byte[] aid, byte p2, 444 ISecureElementListener listener) throws RemoteException { 445 if (DEBUG) { 446 Log.i(mTag, "openLogicalChannel() AID = " 447 + ByteArrayConverter.byteArrayToHexString(aid) + ", P2 = " + p2); 448 } 449 if (isClosed()) { 450 throw new IllegalStateException("Session is closed"); 451 } else if (listener == null) { 452 throw new NullPointerException("listener must not be null"); 453 } else if ((p2 != 0x00) && (p2 != 0x04) && (p2 != 0x08) 454 && (p2 != (byte) 0x0C)) { 455 throw new UnsupportedOperationException("p2 not supported: " 456 + String.format("%02x ", p2 & 0xFF)); 457 } 458 459 String packageName = null; 460 byte[] uuid = null; 461 try { 462 packageName = getPackageNameFromCallingUid(Binder.getCallingUid()); 463 } catch (AccessControlException e) { 464 // Since packageName not found for calling process, try to find UUID mapping 465 // provided by vendors for the calling process UID 466 // (vendor provide UUID mapping for native services to access secure element) 467 Log.d(mTag, "openLogicalChannel() trying to find mapping uuid"); 468 // Allow UUID based access only on embedded secure elements eSE. 469 if (mReader.getTerminal().getName().startsWith(SecureElementService.ESE_TERMINAL)) { 470 uuid = getUUIDFromCallingUid(Binder.getCallingUid()); 471 } 472 if (uuid == null) { 473 Log.e(mTag, "openLogicalChannel() uuid mapping for calling uid is not found"); 474 throw e; 475 } 476 } 477 Channel channel = null; 478 479 try { 480 channel = mReader.getTerminal().openLogicalChannel(this, aid, p2, listener, 481 packageName, uuid, Binder.getCallingPid()); 482 } catch (IOException e) { 483 throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage()); 484 } catch (NoSuchElementException e) { 485 throw new ServiceSpecificException(SEService.NO_SUCH_ELEMENT_ERROR, e.getMessage()); 486 } 487 488 if (channel == null) { 489 Log.i(mTag, "openLogicalChannel() - returning null"); 490 return null; 491 } 492 Log.i(mTag, "openLogicalChannel() Success. Channel: " 493 + channel.getChannelNumber()); 494 495 synchronized (mLock) { 496 mChannels.add(channel); 497 } 498 return channel.new SecureElementChannel(); 499 } 500 501 @Override getInterfaceHash()502 public String getInterfaceHash() { 503 return ISecureElementSession.HASH; 504 } 505 506 @Override getInterfaceVersion()507 public int getInterfaceVersion() { 508 return ISecureElementSession.VERSION; 509 } 510 } 511 512 private final BroadcastReceiver mMultiSimConfigChangedReceiver = new BroadcastReceiver() { 513 @Override 514 public void onReceive(Context context, Intent intent) { 515 String action = intent.getAction(); 516 if (action.equals(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED)) { 517 int activeSimCount = 518 intent.getIntExtra(TelephonyManager.EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, 1); 519 Log.i(mTag, "received action MultiSimConfigChanged. Refresh UICC terminals"); 520 Log.i(mTag, "Current ActiveSimCount:" + activeSimCount 521 + ". Previous ActiveSimCount:" + mActiveSimCount); 522 523 // Check for any change to UICC SE HAL implementations 524 refreshUiccTerminals(activeSimCount); 525 } 526 } 527 }; 528 } 529