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