1/* 2 * Copyright (C) 2014 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 17package com.android.internal.telephony.uicc; 18 19import android.annotation.Nullable; 20import android.content.Intent; 21import android.content.pm.PackageInfo; 22import android.content.pm.PackageManager; 23import android.content.pm.ResolveInfo; 24import android.content.pm.Signature; 25import android.os.AsyncResult; 26import android.os.Binder; 27import android.os.Handler; 28import android.os.Message; 29import android.telephony.Rlog; 30import android.telephony.TelephonyManager; 31 32import com.android.internal.telephony.CommandException; 33import com.android.internal.telephony.CommandsInterface; 34import com.android.internal.telephony.uicc.IccUtils; 35 36import java.io.ByteArrayInputStream; 37import java.io.FileDescriptor; 38import java.io.PrintWriter; 39import java.lang.IllegalArgumentException; 40import java.lang.IndexOutOfBoundsException; 41import java.security.MessageDigest; 42import java.security.NoSuchAlgorithmException; 43import java.security.cert.Certificate; 44import java.security.cert.CertificateException; 45import java.security.cert.CertificateFactory; 46import java.security.cert.X509Certificate; 47import java.util.ArrayList; 48import java.util.Arrays; 49import java.util.List; 50import java.util.Locale; 51import java.util.concurrent.atomic.AtomicInteger; 52 53/** 54 * Class that reads and stores the carrier privileged rules from the UICC. 55 * 56 * The rules are read when the class is created, hence it should only be created 57 * after the UICC can be read. And it should be deleted when a UICC is changed. 58 * 59 * The spec for the rules: 60 * GP Secure Element Access Control: 61 * http://www.globalplatform.org/specifications/review/GPD_SE_Access_Control_v1.0.20.pdf 62 * Extension spec: 63 * https://code.google.com/p/seek-for-android/ 64 * 65 * 66 * TODO: Notifications. 67 * 68 * {@hide} 69 */ 70public class UiccCarrierPrivilegeRules extends Handler { 71 private static final String LOG_TAG = "UiccCarrierPrivilegeRules"; 72 private static final boolean DBG = false; 73 74 private static final String AID = "A00000015141434C00"; 75 private static final int CLA = 0x80; 76 private static final int COMMAND = 0xCA; 77 private static final int P1 = 0xFF; 78 private static final int P2 = 0x40; 79 private static final int P2_EXTENDED_DATA = 0x60; 80 private static final int P3 = 0x00; 81 private static final String DATA = ""; 82 83 /* 84 * Rules format: 85 * ALL_REF_AR_DO = TAG_ALL_REF_AR_DO + len + [REF_AR_DO]*n 86 * REF_AR_DO = TAG_REF_AR_DO + len + REF-DO + AR-DO 87 * 88 * REF_DO = TAG_REF_DO + len + DEVICE_APP_ID_REF_DO + (optional) PKG_REF_DO 89 * AR_DO = TAG_AR_DO + len + PERM_AR_DO 90 * 91 * DEVICE_APP_ID_REF_DO = TAG_DEVICE_APP_ID_REF_DO + len + sha256 hexstring of cert 92 * PKG_REF_DO = TAG_PKG_REF_DO + len + package name 93 * PERM_AR_DO = TAG_PERM_AR_DO + len + detailed permission (8 bytes) 94 * 95 * Data objects hierarchy by TAG: 96 * FF40 97 * E2 98 * E1 99 * C1 100 * CA 101 * E3 102 * DB 103 */ 104 // Values from the data standard. 105 private static final String TAG_ALL_REF_AR_DO = "FF40"; 106 private static final String TAG_REF_AR_DO = "E2"; 107 private static final String TAG_REF_DO = "E1"; 108 private static final String TAG_DEVICE_APP_ID_REF_DO = "C1"; 109 private static final String TAG_PKG_REF_DO = "CA"; 110 private static final String TAG_AR_DO = "E3"; 111 private static final String TAG_PERM_AR_DO = "DB"; 112 113 private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1; 114 private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2; 115 private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 3; 116 117 // State of the object. 118 private static final int STATE_LOADING = 0; 119 private static final int STATE_LOADED = 1; 120 private static final int STATE_ERROR = 2; 121 122 // Max number of retries for open logical channel, interval is 10s. 123 private static final int MAX_RETRY = 1; 124 private static final int RETRY_INTERVAL_MS = 10000; 125 126 // Describes a single rule. 127 private static class AccessRule { 128 public byte[] certificateHash; 129 public String packageName; 130 public long accessType; // This bit is not currently used, but reserved for future use. 131 132 AccessRule(byte[] certificateHash, String packageName, long accessType) { 133 this.certificateHash = certificateHash; 134 this.packageName = packageName; 135 this.accessType = accessType; 136 } 137 138 boolean matches(byte[] certHash, String packageName) { 139 return certHash != null && Arrays.equals(this.certificateHash, certHash) && 140 (this.packageName == null || this.packageName.equals(packageName)); 141 } 142 143 @Override 144 public String toString() { 145 return "cert: " + IccUtils.bytesToHexString(certificateHash) + " pkg: " + 146 packageName + " access: " + accessType; 147 } 148 } 149 150 // Used for parsing the data from the UICC. 151 private static class TLV { 152 private static final int SINGLE_BYTE_MAX_LENGTH = 0x80; 153 private String tag; 154 // Length encoding is in GPC_Specification_2.2.1: 11.1.5 APDU Message and Data Length. 155 // Length field could be either 1 byte if length < 128, or multiple bytes with first byte 156 // specifying how many bytes are used for length, followed by length bytes. 157 // Bytes for the length field, in ASCII HEX string form. 158 private String lengthBytes; 159 // Decoded length as integer. 160 private Integer length; 161 private String value; 162 163 public TLV(String tag) { 164 this.tag = tag; 165 } 166 167 public String parseLength(String data) { 168 int offset = tag.length(); 169 int firstByte = Integer.parseInt(data.substring(offset, offset + 2), 16); 170 if (firstByte < SINGLE_BYTE_MAX_LENGTH) { 171 length = firstByte * 2; 172 lengthBytes = data.substring(offset, offset + 2); 173 } else { 174 int numBytes = firstByte - SINGLE_BYTE_MAX_LENGTH; 175 length = Integer.parseInt(data.substring(offset + 2, offset + 2 + numBytes * 2), 16) * 2; 176 lengthBytes = data.substring(offset, offset + 2 + numBytes * 2); 177 } 178 log("TLV parseLength length=" + length + "lenghtBytes: " + lengthBytes); 179 return lengthBytes; 180 } 181 182 public String parse(String data, boolean shouldConsumeAll) { 183 log("Parse TLV: " + tag); 184 if (!data.startsWith(tag)) { 185 throw new IllegalArgumentException("Tags don't match."); 186 } 187 int index = tag.length(); 188 if (index + 2 > data.length()) { 189 throw new IllegalArgumentException("No length."); 190 } 191 192 parseLength(data); 193 index += lengthBytes.length(); 194 195 log("index="+index+" length="+length+"data.length="+data.length()); 196 int remainingLength = data.length() - (index + length); 197 if (remainingLength < 0) { 198 throw new IllegalArgumentException("Not enough data."); 199 } 200 if (shouldConsumeAll && (remainingLength != 0)) { 201 throw new IllegalArgumentException("Did not consume all."); 202 } 203 value = data.substring(index, index + length); 204 205 log("Got TLV: " + tag + "," + length + "," + value); 206 207 return data.substring(index + length); 208 } 209 } 210 211 private UiccCard mUiccCard; // Parent 212 private AtomicInteger mState; 213 private List<AccessRule> mAccessRules; 214 private String mRules; 215 private Message mLoadedCallback; 216 private String mStatusMessage; // Only used for debugging. 217 private int mChannelId; // Channel Id for communicating with UICC. 218 private int mRetryCount; // Number of retries for open logical channel. 219 private final Runnable mRetryRunnable = new Runnable() { 220 @Override 221 public void run() { 222 openChannel(); 223 } 224 }; 225 226 private void openChannel() { 227 // Send open logical channel request. 228 mUiccCard.iccOpenLogicalChannel(AID, 229 obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, null)); 230 } 231 232 public UiccCarrierPrivilegeRules(UiccCard uiccCard, Message loadedCallback) { 233 log("Creating UiccCarrierPrivilegeRules"); 234 mUiccCard = uiccCard; 235 mState = new AtomicInteger(STATE_LOADING); 236 mStatusMessage = "Not loaded."; 237 mLoadedCallback = loadedCallback; 238 mRules = ""; 239 240 openChannel(); 241 } 242 243 /** 244 * Returns true if the carrier privilege rules have finished loading. 245 */ 246 public boolean areCarrierPriviligeRulesLoaded() { 247 return mState.get() != STATE_LOADING; 248 } 249 250 /** 251 * Returns the status of the carrier privileges for the input certificate and package name. 252 * 253 * @param signature The signature of the certificate. 254 * @param packageName name of the package. 255 * @return Access status. 256 */ 257 public int getCarrierPrivilegeStatus(Signature signature, String packageName) { 258 log("hasCarrierPrivileges: " + signature + " : " + packageName); 259 int state = mState.get(); 260 if (state == STATE_LOADING) { 261 log("Rules not loaded."); 262 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 263 } else if (state == STATE_ERROR) { 264 log("Error loading rules."); 265 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 266 } 267 268 // SHA-1 is for backward compatible support only, strongly discouraged for new use. 269 byte[] certHash = getCertHash(signature, "SHA-1"); 270 byte[] certHash256 = getCertHash(signature, "SHA-256"); 271 for (AccessRule ar : mAccessRules) { 272 if (ar.matches(certHash, packageName) || ar.matches(certHash256, packageName)) { 273 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 274 } 275 } 276 277 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 278 } 279 280 /** 281 * Returns the status of the carrier privileges for the input package name. 282 * 283 * @param packageManager PackageManager for getting signatures. 284 * @param packageName name of the package. 285 * @return Access status. 286 */ 287 public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) { 288 try { 289 // Include DISABLED_UNTIL_USED components. This facilitates cases where a carrier app 290 // is disabled by default, and some other component wants to enable it when it has 291 // gained carrier privileges (as an indication that a matching SIM has been inserted). 292 PackageInfo pInfo = packageManager.getPackageInfo(packageName, 293 PackageManager.GET_SIGNATURES | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); 294 Signature[] signatures = pInfo.signatures; 295 for (Signature sig : signatures) { 296 int accessStatus = getCarrierPrivilegeStatus(sig, pInfo.packageName); 297 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 298 return accessStatus; 299 } 300 } 301 } catch (PackageManager.NameNotFoundException ex) { 302 Rlog.e(LOG_TAG, "NameNotFoundException", ex); 303 } 304 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 305 } 306 307 /** 308 * Returns the status of the carrier privileges for the caller of the current transaction. 309 * 310 * @param packageManager PackageManager for getting signatures and package names. 311 * @return Access status. 312 */ 313 public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) { 314 String[] packages = packageManager.getPackagesForUid(Binder.getCallingUid()); 315 316 for (String pkg : packages) { 317 int accessStatus = getCarrierPrivilegeStatus(packageManager, pkg); 318 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 319 return accessStatus; 320 } 321 } 322 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 323 } 324 325 /** 326 * Returns the package name of the carrier app that should handle the input intent. 327 * 328 * @param packageManager PackageManager for getting receivers. 329 * @param intent Intent that will be sent. 330 * @return list of carrier app package names that can handle the intent. 331 * Returns null if there is an error and an empty list if there 332 * are no matching packages. 333 */ 334 public List<String> getCarrierPackageNamesForIntent( 335 PackageManager packageManager, Intent intent) { 336 List<String> packages = new ArrayList<String>(); 337 List<ResolveInfo> receivers = new ArrayList<ResolveInfo>(); 338 receivers.addAll(packageManager.queryBroadcastReceivers(intent, 0)); 339 receivers.addAll(packageManager.queryIntentContentProviders(intent, 0)); 340 receivers.addAll(packageManager.queryIntentActivities(intent, 0)); 341 receivers.addAll(packageManager.queryIntentServices(intent, 0)); 342 343 for (ResolveInfo resolveInfo : receivers) { 344 String packageName = getPackageName(resolveInfo); 345 if (packageName == null) { 346 continue; 347 } 348 349 int status = getCarrierPrivilegeStatus(packageManager, packageName); 350 if (status == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 351 packages.add(packageName); 352 } else if (status != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 353 // Any status apart from HAS_ACCESS and NO_ACCESS is considered an error. 354 return null; 355 } 356 } 357 358 return packages; 359 } 360 361 @Nullable 362 private String getPackageName(ResolveInfo resolveInfo) { 363 if (resolveInfo.activityInfo != null) { 364 return resolveInfo.activityInfo.packageName; 365 } else if (resolveInfo.serviceInfo != null) { 366 return resolveInfo.serviceInfo.packageName; 367 } else if (resolveInfo.providerInfo != null) { 368 return resolveInfo.providerInfo.packageName; 369 } 370 return null; 371 } 372 373 @Override 374 public void handleMessage(Message msg) { 375 AsyncResult ar; 376 377 switch (msg.what) { 378 379 case EVENT_OPEN_LOGICAL_CHANNEL_DONE: 380 log("EVENT_OPEN_LOGICAL_CHANNEL_DONE"); 381 ar = (AsyncResult) msg.obj; 382 if (ar.exception == null && ar.result != null) { 383 mChannelId = ((int[]) ar.result)[0]; 384 mUiccCard.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3, DATA, 385 obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(mChannelId))); 386 } else { 387 // MISSING_RESOURCE could be due to logical channels temporarily unavailable, 388 // so we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS. 389 if (ar.exception instanceof CommandException && mRetryCount < MAX_RETRY && 390 ((CommandException) (ar.exception)).getCommandError() == 391 CommandException.Error.MISSING_RESOURCE) { 392 mRetryCount++; 393 removeCallbacks(mRetryRunnable); 394 postDelayed(mRetryRunnable, RETRY_INTERVAL_MS); 395 } else { 396 updateState(STATE_ERROR, "Error opening channel: " + ar.exception); 397 } 398 } 399 break; 400 401 case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE: 402 log("EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE"); 403 ar = (AsyncResult) msg.obj; 404 if (ar.exception == null && ar.result != null) { 405 IccIoResult response = (IccIoResult) ar.result; 406 if (response.sw1 == 0x90 && response.sw2 == 0x00 && 407 response.payload != null && response.payload.length > 0) { 408 try { 409 mRules += IccUtils.bytesToHexString(response.payload).toUpperCase(Locale.US); 410 if (isDataComplete()) { 411 mAccessRules = parseRules(mRules); 412 updateState(STATE_LOADED, "Success!"); 413 } else { 414 mUiccCard.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2_EXTENDED_DATA, P3, DATA, 415 obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(mChannelId))); 416 break; 417 } 418 } catch (IllegalArgumentException ex) { 419 updateState(STATE_ERROR, "Error parsing rules: " + ex); 420 } catch (IndexOutOfBoundsException ex) { 421 updateState(STATE_ERROR, "Error parsing rules: " + ex); 422 } 423 } else { 424 String errorMsg = "Invalid response: payload=" + response.payload + 425 " sw1=" + response.sw1 + " sw2=" + response.sw2; 426 updateState(STATE_ERROR, errorMsg); 427 } 428 } else { 429 updateState(STATE_ERROR, "Error reading value from SIM."); 430 } 431 432 mUiccCard.iccCloseLogicalChannel(mChannelId, obtainMessage( 433 EVENT_CLOSE_LOGICAL_CHANNEL_DONE)); 434 mChannelId = -1; 435 break; 436 437 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 438 log("EVENT_CLOSE_LOGICAL_CHANNEL_DONE"); 439 break; 440 441 default: 442 Rlog.e(LOG_TAG, "Unknown event " + msg.what); 443 } 444 } 445 446 /* 447 * Check if all rule bytes have been read from UICC. 448 * For long payload, we need to fetch it repeatly before start parsing it. 449 */ 450 private boolean isDataComplete() { 451 log("isDataComplete mRules:" + mRules); 452 if (mRules.startsWith(TAG_ALL_REF_AR_DO)) { 453 TLV allRules = new TLV(TAG_ALL_REF_AR_DO); 454 String lengthBytes = allRules.parseLength(mRules); 455 log("isDataComplete lengthBytes: " + lengthBytes); 456 if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() + 457 allRules.length) { 458 log("isDataComplete yes"); 459 return true; 460 } else { 461 log("isDataComplete no"); 462 return false; 463 } 464 } else { 465 throw new IllegalArgumentException("Tags don't match."); 466 } 467 } 468 469 /* 470 * Parses the rules from the input string. 471 */ 472 private static List<AccessRule> parseRules(String rules) { 473 log("Got rules: " + rules); 474 475 TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40 476 allRefArDo.parse(rules, true); 477 478 String arDos = allRefArDo.value; 479 List<AccessRule> accessRules = new ArrayList<AccessRule>(); 480 while (!arDos.isEmpty()) { 481 TLV refArDo = new TLV(TAG_REF_AR_DO); //E2 482 arDos = refArDo.parse(arDos, false); 483 AccessRule accessRule = parseRefArdo(refArDo.value); 484 if (accessRule != null) { 485 accessRules.add(accessRule); 486 } else { 487 Rlog.e(LOG_TAG, "Skip unrecognized rule." + refArDo.value); 488 } 489 } 490 return accessRules; 491 } 492 493 /* 494 * Parses a single rule. 495 */ 496 private static AccessRule parseRefArdo(String rule) { 497 log("Got rule: " + rule); 498 499 String certificateHash = null; 500 String packageName = null; 501 String tmp = null; 502 long accessType = 0; 503 504 while (!rule.isEmpty()) { 505 if (rule.startsWith(TAG_REF_DO)) { 506 TLV refDo = new TLV(TAG_REF_DO); //E1 507 rule = refDo.parse(rule, false); 508 509 // Skip unrelated rules. 510 if (!refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) { 511 return null; 512 } 513 514 TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1 515 tmp = deviceDo.parse(refDo.value, false); 516 certificateHash = deviceDo.value; 517 518 if (!tmp.isEmpty()) { 519 if (!tmp.startsWith(TAG_PKG_REF_DO)) { 520 return null; 521 } 522 TLV pkgDo = new TLV(TAG_PKG_REF_DO); //CA 523 pkgDo.parse(tmp, true); 524 packageName = new String(IccUtils.hexStringToBytes(pkgDo.value)); 525 } else { 526 packageName = null; 527 } 528 } else if (rule.startsWith(TAG_AR_DO)) { 529 TLV arDo = new TLV(TAG_AR_DO); //E3 530 rule = arDo.parse(rule, false); 531 532 // Skip unrelated rules. 533 if (!arDo.value.startsWith(TAG_PERM_AR_DO)) { 534 return null; 535 } 536 537 TLV permDo = new TLV(TAG_PERM_AR_DO); //DB 538 permDo.parse(arDo.value, true); 539 } else { 540 // Spec requires it must be either TAG_REF_DO or TAG_AR_DO. 541 throw new RuntimeException("Invalid Rule type"); 542 } 543 } 544 545 AccessRule accessRule = new AccessRule(IccUtils.hexStringToBytes(certificateHash), 546 packageName, accessType); 547 return accessRule; 548 } 549 550 /* 551 * Converts a Signature into a Certificate hash usable for comparison. 552 */ 553 private static byte[] getCertHash(Signature signature, String algo) { 554 try { 555 MessageDigest md = MessageDigest.getInstance(algo); 556 return md.digest(signature.toByteArray()); 557 } catch (NoSuchAlgorithmException ex) { 558 Rlog.e(LOG_TAG, "NoSuchAlgorithmException: " + ex); 559 } 560 return null; 561 } 562 563 /* 564 * Updates the state and notifies the UiccCard that the rules have finished loading. 565 */ 566 private void updateState(int newState, String statusMessage) { 567 mState.set(newState); 568 if (mLoadedCallback != null) { 569 mLoadedCallback.sendToTarget(); 570 } 571 572 mStatusMessage = statusMessage; 573 } 574 575 private static void log(String msg) { 576 if (DBG) Rlog.d(LOG_TAG, msg); 577 } 578 579 /** 580 * Dumps info to Dumpsys - useful for debugging. 581 */ 582 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 583 pw.println("UiccCarrierPrivilegeRules: " + this); 584 pw.println(" mState=" + getStateString(mState.get())); 585 pw.println(" mStatusMessage='" + mStatusMessage + "'"); 586 if (mAccessRules != null) { 587 pw.println(" mAccessRules: "); 588 for (AccessRule ar : mAccessRules) { 589 pw.println(" rule='" + ar + "'"); 590 } 591 } else { 592 pw.println(" mAccessRules: null"); 593 } 594 pw.flush(); 595 } 596 597 /* 598 * Converts state into human readable format. 599 */ 600 private String getStateString(int state) { 601 switch (state) { 602 case STATE_LOADING: 603 return "STATE_LOADING"; 604 case STATE_LOADED: 605 return "STATE_LOADED"; 606 case STATE_ERROR: 607 return "STATE_ERROR"; 608 default: 609 return "UNKNOWN"; 610 } 611 } 612} 613