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 /* 21 * Copyright 2012 Giesecke & Devrient GmbH. 22 * 23 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 24 * use this file except in compliance with the License. You may obtain a copy of 25 * the License at 26 * 27 * http://www.apache.org/licenses/LICENSE-2.0 28 * 29 * Unless required by applicable law or agreed to in writing, software 30 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 31 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 32 * License for the specific language governing permissions and limitations under 33 * the License. 34 */ 35 36 package com.android.se.security; 37 38 import android.content.pm.PackageInfo; 39 import android.content.pm.PackageManager; 40 import android.content.pm.PackageManager.NameNotFoundException; 41 import android.content.pm.Signature; 42 import android.os.Build; 43 import android.os.SystemProperties; 44 import android.util.Log; 45 46 import com.android.se.Channel; 47 import com.android.se.SecureElementService; 48 import com.android.se.Terminal; 49 import com.android.se.internal.ByteArrayConverter; 50 import com.android.se.security.ChannelAccess.ACCESS; 51 import com.android.se.security.ara.AraController; 52 import com.android.se.security.arf.ArfController; 53 54 import java.io.IOException; 55 import java.io.PrintWriter; 56 import java.security.AccessControlException; 57 import java.security.MessageDigest; 58 import java.security.NoSuchAlgorithmException; 59 import java.util.ArrayList; 60 import java.util.List; 61 import java.util.MissingResourceException; 62 import java.util.NoSuchElementException; 63 64 /** Reads and Maintains the ARF and ARA access control for a particular Secure Element */ 65 public class AccessControlEnforcer { 66 67 private final String mTag = "SecureElement-AccessControlEnforcer"; 68 private static final boolean DEBUG = Build.IS_DEBUGGABLE; 69 private PackageManager mPackageManager = null; 70 private boolean mNoRuleFound = false; 71 private AraController mAraController = null; 72 private boolean mUseAra = true; 73 private ArfController mArfController = null; 74 private boolean mUseArf = false; 75 private AccessRuleCache mAccessRuleCache = null; 76 private boolean mRulesRead = false; 77 private Terminal mTerminal = null; 78 private ChannelAccess mInitialChannelAccess = new ChannelAccess(); 79 private boolean mFullAccess = false; 80 AccessControlEnforcer(Terminal terminal)81 public AccessControlEnforcer(Terminal terminal) { 82 83 mTerminal = terminal; 84 mAccessRuleCache = new AccessRuleCache(); 85 } 86 getDefaultAccessControlAid()87 public static byte[] getDefaultAccessControlAid() { 88 return AraController.getAraMAid(); 89 } 90 getPackageManager()91 public PackageManager getPackageManager() { 92 return mPackageManager; 93 } 94 setPackageManager(PackageManager packageManager)95 public void setPackageManager(PackageManager packageManager) { 96 mPackageManager = packageManager; 97 } 98 getTerminal()99 public Terminal getTerminal() { 100 return mTerminal; 101 } 102 getAccessRuleCache()103 public AccessRuleCache getAccessRuleCache() { 104 return mAccessRuleCache; 105 } 106 107 /** Resets the Access Control for the Secure Element */ reset()108 public synchronized void reset() { 109 // Destroy any previous Controler 110 // in order to reset the ACE 111 Log.i(mTag, "Reset the ACE for terminal:" + mTerminal.getName()); 112 mAccessRuleCache.reset(); 113 mAraController = null; 114 mArfController = null; 115 } 116 117 /** Initializes the Access Control for the Secure Element */ initialize()118 public synchronized void initialize() throws IOException, MissingResourceException { 119 boolean status = true; 120 String denyMsg = ""; 121 // allow access to set up access control for a channel 122 mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED); 123 mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.ALLOWED); 124 mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, ""); 125 126 readSecurityProfile(); 127 mNoRuleFound = false; 128 129 // 1 - Let's try to use ARA 130 if (mUseAra && mAraController == null) { 131 mAraController = new AraController(mAccessRuleCache, mTerminal); 132 } 133 134 if (mUseAra && mAraController != null) { 135 try { 136 mAraController.initialize(); 137 Log.i(mTag, "ARA applet is used for:" + mTerminal.getName()); 138 // disable other access methods 139 mUseArf = false; 140 mFullAccess = false; 141 } catch (IOException | MissingResourceException e) { 142 throw e; 143 } catch (Exception e) { 144 // ARA cannot be used since we got an exception during initialization 145 mUseAra = false; 146 denyMsg = e.getLocalizedMessage(); 147 if (e instanceof NoSuchElementException) { 148 Log.i(mTag, "No ARA applet found in: " + mTerminal.getName()); 149 if (!mUseArf) { 150 // ARA does not exist on the secure element right now, 151 // but it might be installed later. 152 mNoRuleFound = true; 153 status = mFullAccess; 154 } 155 } else if (mTerminal.getName().startsWith(SecureElementService.UICC_TERMINAL)) { 156 // A possible explanation could simply be due to the fact that the UICC is old 157 // and does not support logical channel (and is not compliant with GP spec). 158 // We should simply act as if no ARA was available in this case. 159 if (!mUseArf) { 160 // Only ARA was the candidate to retrieve access rules, 161 // but it is not 100% sure if the expected ARA really does not exist. 162 // Full access should not be granted in this case. 163 mFullAccess = false; 164 status = false; 165 } 166 } else { 167 // ARA is available but doesn't work properly. 168 // We are going to disable everything per security req. 169 mUseArf = false; 170 mFullAccess = false; 171 status = false; 172 Log.i(mTag, "Problem accessing ARA, Access DENIED " 173 + e.getLocalizedMessage()); 174 } 175 } 176 } 177 178 // 2 - Let's try to use ARF since ARA cannot be used 179 if (mUseArf && mArfController == null) { 180 mArfController = new ArfController(mAccessRuleCache, mTerminal); 181 } 182 183 if (mUseArf && mArfController != null) { 184 try { 185 mArfController.initialize(); 186 // disable other access methods 187 Log.i(mTag, "ARF rules are used for:" + mTerminal.getName()); 188 mFullAccess = false; 189 } catch (IOException | MissingResourceException e) { 190 throw e; 191 } catch (Exception e) { 192 // ARF cannot be used since we got an exception 193 mUseArf = false; 194 denyMsg = e.getLocalizedMessage(); 195 Log.e(mTag, e.getMessage()); 196 if (e instanceof NoSuchElementException) { 197 Log.i(mTag, "No ARF found in: " + mTerminal.getName()); 198 // ARF does not exist on the secure element right now, 199 // but it might be added later. 200 mNoRuleFound = true; 201 status = mFullAccess; 202 } else { 203 // It is not 100% sure if the expected ARF really does not exist. 204 // No ARF might be due to a kind of temporary problem, 205 // so full access should not be granted in this case. 206 mFullAccess = false; 207 status = false; 208 } 209 } 210 } 211 212 /* 4 - Let's block everything since neither ARA, ARF or fullaccess can be used */ 213 if (!mUseArf && !mUseAra && !mFullAccess) { 214 mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED); 215 mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED); 216 mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.DENIED, denyMsg); 217 Log.i(mTag, "Deny any access to:" + mTerminal.getName()); 218 } 219 220 mRulesRead = status; 221 } 222 223 /** 224 * Returns the result of the previous attempt to select ARA and/or ARF. 225 * 226 * @return true if no rule was found in the previous attempt. 227 */ isNoRuleFound()228 public boolean isNoRuleFound() { 229 return mNoRuleFound; 230 } 231 232 /** Check if the Channel has permission for the given APDU */ checkCommand(Channel channel, byte[] command)233 public synchronized void checkCommand(Channel channel, byte[] command) { 234 ChannelAccess ca = channel.getChannelAccess(); 235 if (ca == null) { 236 throw new AccessControlException(mTag + "Channel access not set"); 237 } 238 String reason = ca.getReason(); 239 if (reason.length() == 0) { 240 reason = "Unspecified"; 241 } 242 if (DEBUG) { 243 Log.i(mTag, "checkCommand() : Access = " + ca.getAccess() + " APDU Access = " 244 + ca.getApduAccess() + " Reason = " + reason); 245 } 246 if (ca.getAccess() != ACCESS.ALLOWED) { 247 throw new AccessControlException(mTag + reason); 248 } 249 if (ca.isUseApduFilter()) { 250 ApduFilter[] accessConditions = ca.getApduFilter(); 251 if (accessConditions == null || accessConditions.length == 0) { 252 throw new AccessControlException(mTag + "Access Rule not available:" 253 + reason); 254 } 255 for (ApduFilter ac : accessConditions) { 256 if (CommandApdu.compareHeaders(command, ac.getMask(), ac.getApdu())) { 257 return; 258 } 259 } 260 throw new AccessControlException(mTag + "Access Rule does not match: " 261 + reason); 262 } 263 if (ca.getApduAccess() == ChannelAccess.ACCESS.ALLOWED) { 264 return; 265 } else { 266 throw new AccessControlException(mTag + "APDU access NOT allowed"); 267 } 268 } 269 270 /** Sets up the Channel Access for the given Package */ setUpChannelAccess(byte[] aid, String packageName, boolean checkRefreshTag)271 public ChannelAccess setUpChannelAccess(byte[] aid, String packageName, boolean checkRefreshTag) 272 throws IOException, MissingResourceException { 273 ChannelAccess channelAccess = null; 274 // check result of channel access during initialization procedure 275 if (mInitialChannelAccess.getAccess() == ChannelAccess.ACCESS.DENIED) { 276 throw new AccessControlException( 277 mTag + "access denied: " + mInitialChannelAccess.getReason()); 278 } 279 // this is the new GP Access Control Enforcer implementation 280 if (mUseAra || mUseArf) { 281 channelAccess = internal_setUpChannelAccess(aid, packageName, 282 checkRefreshTag); 283 } 284 if (channelAccess == null || (channelAccess.getApduAccess() != ChannelAccess.ACCESS.ALLOWED 285 && !channelAccess.isUseApduFilter())) { 286 if (mFullAccess) { 287 // if full access is set then we reuse the initial channel access, 288 // since we got so far it allows everything with a descriptive reason. 289 channelAccess = mInitialChannelAccess; 290 } else { 291 throw new AccessControlException(mTag + "no APDU access allowed!"); 292 } 293 } 294 channelAccess.setPackageName(packageName); 295 return channelAccess.clone(); 296 } 297 internal_setUpChannelAccess(byte[] aid, String packageName, boolean checkRefreshTag)298 private synchronized ChannelAccess internal_setUpChannelAccess(byte[] aid, 299 String packageName, boolean checkRefreshTag) throws IOException, 300 MissingResourceException { 301 if (packageName == null || packageName.isEmpty()) { 302 throw new AccessControlException("package names must be specified"); 303 } 304 try { 305 // estimate SHA-1 and SHA-256 hash values of the device application's certificate. 306 List<byte[]> appCertHashes = getAppCertHashes(packageName); 307 // APP certificates must be available => otherwise Exception 308 if (appCertHashes == null || appCertHashes.size() == 0) { 309 throw new AccessControlException( 310 "Application certificates are invalid or do not exist."); 311 } 312 if (checkRefreshTag) { 313 updateAccessRuleIfNeed(); 314 } 315 return getAccessRule(aid, appCertHashes); 316 } catch (IOException | MissingResourceException e) { 317 throw e; 318 } catch (Throwable exp) { 319 throw new AccessControlException(exp.getMessage()); 320 } 321 } 322 323 /** Fetches the Access Rules for the given application and AID pair */ getAccessRule( byte[] aid, List<byte []> appCertHashes)324 public ChannelAccess getAccessRule( 325 byte[] aid, List<byte []> appCertHashes) 326 throws AccessControlException { 327 if (DEBUG) { 328 for (byte[] appCertHash : appCertHashes) { 329 Log.i(mTag, "getAccessRule() appCert = " 330 + ByteArrayConverter.byteArrayToHexString(appCertHash)); 331 } 332 } 333 ChannelAccess channelAccess = null; 334 // if read all is true get rule from cache. 335 if (mRulesRead) { 336 // get rules from internal storage 337 channelAccess = mAccessRuleCache.findAccessRule(aid, appCertHashes); 338 } 339 // if no rule was found return an empty access rule 340 // with all access denied. 341 if (channelAccess == null) { 342 channelAccess = new ChannelAccess(); 343 channelAccess.setAccess(ChannelAccess.ACCESS.DENIED, "no access rule found!"); 344 channelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED); 345 channelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED); 346 } 347 return channelAccess; 348 } 349 350 /** 351 * Returns hashes of certificate chain for one package. 352 */ getAppCertHashes(String packageName)353 private List<byte[]> getAppCertHashes(String packageName) 354 throws NoSuchAlgorithmException, AccessControlException { 355 if (packageName == null || packageName.length() == 0) { 356 throw new AccessControlException("Package Name not defined"); 357 } 358 PackageInfo foundPkgInfo; 359 try { 360 foundPkgInfo = mPackageManager.getPackageInfo(packageName, 361 PackageManager.GET_SIGNATURES); 362 } catch (NameNotFoundException ne) { 363 throw new AccessControlException("Package does not exist"); 364 } 365 if (foundPkgInfo == null) { 366 throw new AccessControlException("Package does not exist"); 367 } 368 MessageDigest md = MessageDigest.getInstance("SHA"); 369 MessageDigest md256 = MessageDigest.getInstance("SHA-256"); 370 if (md == null || md256 == null) { 371 throw new AccessControlException("Hash can not be computed"); 372 } 373 List<byte[]> appCertHashes = new ArrayList<byte[]>(); 374 for (Signature signature : foundPkgInfo.signatures) { 375 appCertHashes.add(md.digest(signature.toByteArray())); 376 appCertHashes.add(md256.digest(signature.toByteArray())); 377 } 378 return appCertHashes; 379 } 380 381 /** Returns true if the given application is allowed to recieve NFC Events */ isNfcEventAllowed(byte[] aid, String[] packageNames)382 public synchronized boolean[] isNfcEventAllowed(byte[] aid, 383 String[] packageNames) { 384 if (mUseAra || mUseArf) { 385 return internal_isNfcEventAllowed(aid, packageNames); 386 } else { 387 // if ARA and ARF is not available and 388 // - terminal DOES NOT belong to a UICC -> mFullAccess is true 389 // - terminal belongs to a UICC -> mFullAccess is false 390 boolean[] ret = new boolean[packageNames.length]; 391 for (int i = 0; i < ret.length; i++) { 392 ret[i] = mFullAccess; 393 } 394 return ret; 395 } 396 } 397 internal_isNfcEventAllowed(byte[] aid, String[] packageNames)398 private synchronized boolean[] internal_isNfcEventAllowed(byte[] aid, 399 String[] packageNames) { 400 int i = 0; 401 boolean[] nfcEventFlags = new boolean[packageNames.length]; 402 for (String packageName : packageNames) { 403 // estimate hash value of the device application's certificate. 404 try { 405 List<byte[]> appCertHashes = getAppCertHashes(packageName); 406 // APP certificates must be available => otherwise Exception 407 if (appCertHashes == null || appCertHashes.size() == 0) { 408 nfcEventFlags[i] = false; 409 } else { 410 ChannelAccess channelAccess = getAccessRule(aid, appCertHashes); 411 nfcEventFlags[i] = 412 (channelAccess.getNFCEventAccess() == ChannelAccess.ACCESS.ALLOWED); 413 } 414 } catch (Exception e) { 415 Log.w(mTag, " Access Rules for NFC: " + e.getLocalizedMessage()); 416 nfcEventFlags[i] = false; 417 } 418 i++; 419 } 420 return nfcEventFlags; 421 } 422 updateAccessRuleIfNeed()423 private void updateAccessRuleIfNeed() throws IOException { 424 if (mUseAra && mAraController != null) { 425 try { 426 mAraController.initialize(); 427 mUseArf = false; 428 mFullAccess = false; 429 } catch (IOException | MissingResourceException e) { 430 // There was a communication error between the terminal and the secure element 431 // or failure in retrieving rules due to the lack of a new logical channel. 432 // These errors must be distinguished from other ones. 433 throw e; 434 } catch (Exception e) { 435 throw new AccessControlException("No ARA applet found in " + mTerminal.getName()); 436 } 437 } else if (mUseArf && mArfController != null) { 438 try { 439 mArfController.initialize(); 440 } catch (IOException | MissingResourceException e) { 441 // There was a communication error between the terminal and the secure element 442 // or failure in retrieving rules due to the lack of a new logical channel. 443 // These errors must be distinguished from other ones. 444 throw e; 445 } catch (Exception e) { 446 throw new AccessControlException("No ARF found in " + mTerminal.getName()); 447 } 448 } 449 } 450 451 /** Debug information to be used by dumpsys */ dump(PrintWriter writer)452 public void dump(PrintWriter writer) { 453 writer.println(mTag + ":"); 454 455 writer.println("mUseArf: " + mUseArf); 456 writer.println("mUseAra: " + mUseAra); 457 writer.println("mInitialChannelAccess:"); 458 writer.println(mInitialChannelAccess.toString()); 459 writer.println(); 460 461 /* Dump the access rule cache */ 462 if (mAccessRuleCache != null) mAccessRuleCache.dump(writer); 463 } 464 readSecurityProfile()465 private void readSecurityProfile() { 466 if (!Build.IS_DEBUGGABLE) { 467 mUseArf = true; 468 mUseAra = true; 469 mFullAccess = false; // Per default we don't grant full access. 470 } else { 471 String level = SystemProperties.get("service.seek", "useara usearf"); 472 level = SystemProperties.get("persist.service.seek", level); 473 474 if (level.contains("usearf")) { 475 mUseArf = true; 476 } else { 477 mUseArf = false; 478 } 479 if (level.contains("useara")) { 480 mUseAra = true; 481 } else { 482 mUseAra = false; 483 } 484 if (level.contains("fullaccess")) { 485 mFullAccess = true; 486 } else { 487 mFullAccess = false; 488 } 489 } 490 if (!mTerminal.getName().startsWith(SecureElementService.UICC_TERMINAL)) { 491 // It shall be allowed to grant full access if no rule can be retrieved 492 // from the secure element except for UICC. 493 mFullAccess = true; 494 // ARF is supported only on UICC. 495 mUseArf = false; 496 } 497 Log.i( 498 mTag, 499 "Allowed ACE mode: ara=" + mUseAra + " arf=" + mUseArf + " fullaccess=" 500 + mFullAccess); 501 } 502 } 503