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