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.compat.annotation.UnsupportedAppUsage; 21 import android.content.Intent; 22 import android.content.pm.PackageInfo; 23 import android.content.pm.PackageManager; 24 import android.content.pm.ResolveInfo; 25 import android.content.pm.Signature; 26 import android.os.AsyncResult; 27 import android.os.Binder; 28 import android.os.Handler; 29 import android.os.Message; 30 import android.telephony.TelephonyManager; 31 import android.telephony.UiccAccessRule; 32 import android.text.TextUtils; 33 import android.util.LocalLog; 34 35 import com.android.internal.telephony.CommandException; 36 import com.android.telephony.Rlog; 37 38 import java.io.FileDescriptor; 39 import java.io.PrintWriter; 40 import java.util.ArrayList; 41 import java.util.Collections; 42 import java.util.List; 43 import java.util.Locale; 44 import java.util.concurrent.atomic.AtomicInteger; 45 46 /** 47 * Class that reads and stores the carrier privileged rules from the UICC. 48 * 49 * The rules are read when the class is created, hence it should only be created 50 * after the UICC can be read. And it should be deleted when a UICC is changed. 51 * 52 * Document: https://source.android.com/devices/tech/config/uicc.html 53 * 54 * {@hide} 55 */ 56 public class UiccCarrierPrivilegeRules extends Handler { 57 private static final String LOG_TAG = "UiccCarrierPrivilegeRules"; 58 private static final boolean DBG = false; 59 60 private static final String ARAM_AID = "A00000015141434C00"; 61 private static final String ARAD_AID = "A00000015144414300"; 62 private static final int ARAM = 1; 63 private static final int ARAD = 0; 64 private static final int CLA = 0x80; 65 private static final int COMMAND = 0xCA; 66 private static final int P1 = 0xFF; 67 private static final int P2 = 0x40; 68 private static final int P2_EXTENDED_DATA = 0x60; 69 private static final int P3 = 0x00; 70 private static final String DATA = ""; 71 72 /* 73 * Rules format: 74 * ALL_REF_AR_DO = TAG_ALL_REF_AR_DO + len + [REF_AR_DO]*n 75 * REF_AR_DO = TAG_REF_AR_DO + len + REF-DO + AR-DO 76 * 77 * REF_DO = TAG_REF_DO + len + DEVICE_APP_ID_REF_DO + (optional) PKG_REF_DO 78 * AR_DO = TAG_AR_DO + len + PERM_AR_DO 79 * 80 * DEVICE_APP_ID_REF_DO = TAG_DEVICE_APP_ID_REF_DO + len + sha256 hexstring of cert 81 * PKG_REF_DO = TAG_PKG_REF_DO + len + package name 82 * PERM_AR_DO = TAG_PERM_AR_DO + len + detailed permission (8 bytes) 83 * 84 * Data objects hierarchy by TAG: 85 * FF40 86 * E2 87 * E1 88 * C1 89 * CA 90 * E3 91 * DB 92 */ 93 // Values from the data standard. 94 private static final String TAG_ALL_REF_AR_DO = "FF40"; 95 private static final String TAG_REF_AR_DO = "E2"; 96 private static final String TAG_REF_DO = "E1"; 97 private static final String TAG_DEVICE_APP_ID_REF_DO = "C1"; 98 private static final String TAG_PKG_REF_DO = "CA"; 99 private static final String TAG_AR_DO = "E3"; 100 private static final String TAG_PERM_AR_DO = "DB"; 101 private static final String TAG_AID_REF_DO = "4F"; 102 private static final String CARRIER_PRIVILEGE_AID = "FFFFFFFFFFFF"; 103 104 private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1; 105 private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2; 106 private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 3; 107 private static final int EVENT_PKCS15_READ_DONE = 4; 108 109 // State of the object. 110 private static final int STATE_LOADING = 0; 111 private static final int STATE_LOADED = 1; 112 private static final int STATE_ERROR = 2; 113 114 // Max number of retries for open logical channel, interval is 5s. 115 private static final int MAX_RETRY = 2; 116 private static final int RETRY_INTERVAL_MS = 5000; 117 private static final int STATUS_CODE_CONDITION_NOT_SATISFIED = 0x6985; 118 private static final int STATUS_CODE_APPLET_SELECT_FAILED = 0x6999; 119 120 // Used for parsing the data from the UICC. 121 public static class TLV { 122 private static final int SINGLE_BYTE_MAX_LENGTH = 0x80; 123 private String tag; 124 // Length encoding is in GPC_Specification_2.2.1: 11.1.5 APDU Message and Data Length. 125 // Length field could be either 1 byte if length < 128, or multiple bytes with first byte 126 // specifying how many bytes are used for length, followed by length bytes. 127 // Bytes for the length field, in ASCII HEX string form. 128 private String lengthBytes; 129 // Decoded length as integer. 130 @UnsupportedAppUsage 131 private Integer length; 132 @UnsupportedAppUsage 133 private String value; 134 TLV(String tag)135 public TLV(String tag) { 136 this.tag = tag; 137 } 138 getValue()139 public String getValue() { 140 if (value == null) return ""; 141 return value; 142 } 143 parseLength(String data)144 public String parseLength(String data) { 145 int offset = tag.length(); 146 int firstByte = Integer.parseInt(data.substring(offset, offset + 2), 16); 147 if (firstByte < SINGLE_BYTE_MAX_LENGTH) { 148 length = firstByte * 2; 149 lengthBytes = data.substring(offset, offset + 2); 150 } else { 151 int numBytes = firstByte - SINGLE_BYTE_MAX_LENGTH; 152 length = Integer.parseInt(data.substring(offset + 2, offset + 2 + numBytes * 2), 16) * 2; 153 lengthBytes = data.substring(offset, offset + 2 + numBytes * 2); 154 } 155 log("TLV parseLength length=" + length + "lenghtBytes: " + lengthBytes); 156 return lengthBytes; 157 } 158 parse(String data, boolean shouldConsumeAll)159 public String parse(String data, boolean shouldConsumeAll) { 160 log("Parse TLV: " + tag); 161 if (!data.startsWith(tag)) { 162 throw new IllegalArgumentException("Tags don't match."); 163 } 164 int index = tag.length(); 165 if (index + 2 > data.length()) { 166 throw new IllegalArgumentException("No length."); 167 } 168 169 parseLength(data); 170 index += lengthBytes.length(); 171 172 log("index="+index+" length="+length+"data.length="+data.length()); 173 int remainingLength = data.length() - (index + length); 174 if (remainingLength < 0) { 175 throw new IllegalArgumentException("Not enough data."); 176 } 177 if (shouldConsumeAll && (remainingLength != 0)) { 178 throw new IllegalArgumentException("Did not consume all."); 179 } 180 value = data.substring(index, index + length); 181 182 log("Got TLV: " + tag + "," + length + "," + value); 183 184 return data.substring(index + length); 185 } 186 } 187 188 private UiccProfile mUiccProfile; // Parent 189 private UiccPkcs15 mUiccPkcs15; // ARF fallback 190 @UnsupportedAppUsage 191 private AtomicInteger mState; 192 private List<UiccAccessRule> mAccessRules; 193 private String mRules; 194 @UnsupportedAppUsage 195 private Message mLoadedCallback; 196 // LocalLog buffer to hold important status messages for debugging. 197 private LocalLog mStatusMessage = new LocalLog(100); 198 private int mChannelId; // Channel Id for communicating with UICC. 199 private int mRetryCount; // Number of retries for open logical channel. 200 private boolean mCheckedRules = false; // Flag that used to mark whether get rules from ARA-D. 201 private int mAIDInUse; // Message component to identify which AID is currently in-use. 202 private final Runnable mRetryRunnable = new Runnable() { 203 @Override 204 public void run() { 205 openChannel(mAIDInUse); 206 } 207 }; 208 openChannel(int aidId)209 private void openChannel(int aidId) { 210 // Send open logical channel request. 211 String aid = (aidId == ARAD) ? ARAD_AID : ARAM_AID; 212 int p2 = 0x00; 213 mUiccProfile.iccOpenLogicalChannel(aid, p2, /* supported p2 value */ 214 obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, 0, aidId, null)); 215 } 216 UiccCarrierPrivilegeRules(UiccProfile uiccProfile, Message loadedCallback)217 public UiccCarrierPrivilegeRules(UiccProfile uiccProfile, Message loadedCallback) { 218 log("Creating UiccCarrierPrivilegeRules"); 219 mUiccProfile = uiccProfile; 220 mState = new AtomicInteger(STATE_LOADING); 221 mStatusMessage.log("Not loaded."); 222 mLoadedCallback = loadedCallback; 223 mRules = ""; 224 mAccessRules = new ArrayList<>(); 225 226 // Open logical channel with ARA_D. 227 mAIDInUse = ARAD; 228 openChannel(mAIDInUse); 229 } 230 231 /** 232 * Returns true if the carrier privilege rules have finished loading. 233 */ areCarrierPriviligeRulesLoaded()234 public boolean areCarrierPriviligeRulesLoaded() { 235 return mState.get() != STATE_LOADING; 236 } 237 238 /** 239 * Returns true if the carrier privilege rules have finished loading and some rules were 240 * specified. 241 */ hasCarrierPrivilegeRules()242 public boolean hasCarrierPrivilegeRules() { 243 return mState.get() != STATE_LOADING && mAccessRules != null && mAccessRules.size() > 0; 244 } 245 246 /** 247 * Returns package names for privilege rules. 248 * Return empty list if no rules defined or package name is empty string. 249 */ getPackageNames()250 public List<String> getPackageNames() { 251 List<String> pkgNames = new ArrayList<String>(); 252 if (mAccessRules != null) { 253 for (UiccAccessRule ar : mAccessRules) { 254 if (!TextUtils.isEmpty(ar.getPackageName())) { 255 pkgNames.add(ar.getPackageName()); 256 } 257 } 258 } 259 return pkgNames; 260 } 261 262 /** 263 * Returns list of access rules. 264 */ getAccessRules()265 public List<UiccAccessRule> getAccessRules() { 266 if (mAccessRules == null) { 267 return Collections.emptyList(); 268 } 269 return Collections.unmodifiableList(mAccessRules); 270 } 271 272 /** 273 * Returns the status of the carrier privileges for the input certificate and package name. 274 * 275 * @param signature The signature of the certificate. 276 * @param packageName name of the package. 277 * @return Access status. 278 */ getCarrierPrivilegeStatus(Signature signature, String packageName)279 public int getCarrierPrivilegeStatus(Signature signature, String packageName) { 280 int state = mState.get(); 281 if (state == STATE_LOADING) { 282 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 283 } else if (state == STATE_ERROR) { 284 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 285 } 286 287 for (UiccAccessRule ar : mAccessRules) { 288 int accessStatus = ar.getCarrierPrivilegeStatus(signature, packageName); 289 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 290 return accessStatus; 291 } 292 } 293 294 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 295 } 296 297 /** 298 * Returns the status of the carrier privileges for the input package name. 299 * 300 * @param packageManager PackageManager for getting signatures. 301 * @param packageName name of the package. 302 * @return Access status. 303 */ getCarrierPrivilegeStatus(PackageManager packageManager, String packageName)304 public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) { 305 try { 306 // Short-circuit if there are no rules to check against, so we don't need to fetch 307 // the package info with signatures. 308 if (!hasCarrierPrivilegeRules()) { 309 int state = mState.get(); 310 if (state == STATE_LOADING) { 311 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 312 } else if (state == STATE_ERROR) { 313 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 314 } 315 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 316 } 317 // Include DISABLED_UNTIL_USED components. This facilitates cases where a carrier app 318 // is disabled by default, and some other component wants to enable it when it has 319 // gained carrier privileges (as an indication that a matching SIM has been inserted). 320 PackageInfo pInfo = packageManager.getPackageInfo(packageName, 321 PackageManager.GET_SIGNING_CERTIFICATES 322 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 323 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS); 324 return getCarrierPrivilegeStatus(pInfo); 325 } catch (PackageManager.NameNotFoundException ex) { 326 log("Package " + packageName + " not found for carrier privilege status check"); 327 } 328 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 329 } 330 331 /** 332 * Returns the status of the carrier privileges for the input package info. 333 * 334 * @param packageInfo PackageInfo for the package, containing the package signatures. 335 * @return Access status. 336 */ getCarrierPrivilegeStatus(PackageInfo packageInfo)337 public int getCarrierPrivilegeStatus(PackageInfo packageInfo) { 338 int state = mState.get(); 339 if (state == STATE_LOADING) { 340 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 341 } else if (state == STATE_ERROR) { 342 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 343 } 344 345 for (UiccAccessRule ar : mAccessRules) { 346 int accessStatus = ar.getCarrierPrivilegeStatus(packageInfo); 347 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 348 return accessStatus; 349 } 350 } 351 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 352 } 353 354 /** 355 * Returns the status of the carrier privileges for the caller of the current transaction. 356 * 357 * @param packageManager PackageManager for getting signatures and package names. 358 * @return Access status. 359 */ getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager)360 public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) { 361 return getCarrierPrivilegeStatusForUid(packageManager, Binder.getCallingUid()); 362 } 363 364 /** 365 * Returns the status of the carrier privileges for the caller of the current transaction. 366 * 367 * @param packageManager PackageManager for getting signatures and package names. 368 * @return Access status. 369 */ getCarrierPrivilegeStatusForUid( PackageManager packageManager, int uid)370 public int getCarrierPrivilegeStatusForUid( 371 PackageManager packageManager, int uid) { 372 String[] packages = packageManager.getPackagesForUid(uid); 373 374 for (String pkg : packages) { 375 int accessStatus = getCarrierPrivilegeStatus(packageManager, pkg); 376 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 377 return accessStatus; 378 } 379 } 380 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 381 } 382 383 /** 384 * Returns the package name of the carrier app that should handle the input intent. 385 * 386 * @param packageManager PackageManager for getting receivers. 387 * @param intent Intent that will be sent. 388 * @return list of carrier app package names that can handle the intent. 389 * Returns null if there is an error and an empty list if there 390 * are no matching packages. 391 */ getCarrierPackageNamesForIntent( PackageManager packageManager, Intent intent)392 public List<String> getCarrierPackageNamesForIntent( 393 PackageManager packageManager, Intent intent) { 394 List<String> packages = new ArrayList<String>(); 395 List<ResolveInfo> receivers = new ArrayList<ResolveInfo>(); 396 receivers.addAll(packageManager.queryBroadcastReceivers(intent, 0)); 397 receivers.addAll(packageManager.queryIntentContentProviders(intent, 0)); 398 receivers.addAll(packageManager.queryIntentActivities(intent, 0)); 399 receivers.addAll(packageManager.queryIntentServices(intent, 0)); 400 401 for (ResolveInfo resolveInfo : receivers) { 402 String packageName = getPackageName(resolveInfo); 403 if (packageName == null) { 404 continue; 405 } 406 407 int status = getCarrierPrivilegeStatus(packageManager, packageName); 408 if (status == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 409 packages.add(packageName); 410 } else if (status != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 411 // Any status apart from HAS_ACCESS and NO_ACCESS is considered an error. 412 return null; 413 } 414 } 415 416 return packages; 417 } 418 419 @Nullable getPackageName(ResolveInfo resolveInfo)420 private String getPackageName(ResolveInfo resolveInfo) { 421 if (resolveInfo.activityInfo != null) { 422 return resolveInfo.activityInfo.packageName; 423 } else if (resolveInfo.serviceInfo != null) { 424 return resolveInfo.serviceInfo.packageName; 425 } else if (resolveInfo.providerInfo != null) { 426 return resolveInfo.providerInfo.packageName; 427 } 428 return null; 429 } 430 431 /** 432 * The following three situations could be due to logical channels temporarily unavailable, so 433 * we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS: 1. MISSING_RESOURCE, 434 * 2. NO_SUCH_ELEMENT and the status code is 6985, 3. INTERNAL_ERR and the status code is 6999. 435 */ shouldRetry(AsyncResult ar, int retryCount)436 public static boolean shouldRetry(AsyncResult ar, int retryCount) { 437 if (ar.exception instanceof CommandException && retryCount < MAX_RETRY) { 438 CommandException.Error error = ((CommandException) (ar.exception)).getCommandError(); 439 int[] results = (int[]) ar.result; 440 int statusCode = 0; 441 if (ar.result != null && results.length == 3) { 442 byte[] bytes = new byte[]{(byte) results[1], (byte) results[2]}; 443 statusCode = Integer.parseInt(IccUtils.bytesToHexString(bytes), 16); 444 log("status code: " + String.valueOf(statusCode)); 445 } 446 return (error == CommandException.Error.MISSING_RESOURCE) 447 || (error == CommandException.Error.NO_SUCH_ELEMENT 448 && statusCode == STATUS_CODE_CONDITION_NOT_SATISFIED) 449 || (error == CommandException.Error.INTERNAL_ERR 450 && statusCode == STATUS_CODE_APPLET_SELECT_FAILED); 451 } 452 return false; 453 } 454 455 @Override handleMessage(Message msg)456 public void handleMessage(Message msg) { 457 AsyncResult ar; 458 mAIDInUse = msg.arg2; // 0 means ARA-D and 1 means ARA-M. 459 460 switch (msg.what) { 461 462 case EVENT_OPEN_LOGICAL_CHANNEL_DONE: 463 log("EVENT_OPEN_LOGICAL_CHANNEL_DONE"); 464 ar = (AsyncResult) msg.obj; 465 if (ar.exception == null && ar.result != null) { 466 mChannelId = ((int[]) ar.result)[0]; 467 mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3, 468 DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, mChannelId, 469 mAIDInUse)); 470 } else { 471 if (shouldRetry(ar, mRetryCount)) { 472 log("should retry"); 473 mRetryCount++; 474 removeCallbacks(mRetryRunnable); 475 postDelayed(mRetryRunnable, RETRY_INTERVAL_MS); 476 } else { 477 if (mAIDInUse == ARAD) { 478 // Open logical channel with ARA_M. 479 mRules = ""; 480 openChannel(ARAM); 481 } 482 if (mAIDInUse == ARAM) { 483 if (mCheckedRules) { 484 updateState(STATE_LOADED, "Success!"); 485 } else { 486 // if rules cannot be read from both ARA_D and ARA_M applet, 487 // fallback to PKCS15-based ARF. 488 log("No ARA, try ARF next."); 489 if (ar.exception instanceof CommandException 490 && ((CommandException) (ar.exception)).getCommandError() 491 != CommandException.Error.NO_SUCH_ELEMENT) { 492 updateStatusMessage("No ARA due to " 493 + 494 ((CommandException) (ar.exception)).getCommandError()); 495 } 496 mUiccPkcs15 = new UiccPkcs15(mUiccProfile, 497 obtainMessage(EVENT_PKCS15_READ_DONE)); 498 } 499 } 500 } 501 } 502 break; 503 504 case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE: 505 log("EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE"); 506 ar = (AsyncResult) msg.obj; 507 if (ar.exception == null && ar.result != null) { 508 IccIoResult response = (IccIoResult) ar.result; 509 if (response.sw1 == 0x90 && response.sw2 == 0x00 510 && response.payload != null && response.payload.length > 0) { 511 try { 512 mRules += IccUtils.bytesToHexString(response.payload) 513 .toUpperCase(Locale.US); 514 if (isDataComplete()) { 515 //TODO: here's where AccessRules are being updated from the psim 516 // b/139133814 517 mAccessRules.addAll(parseRules(mRules)); 518 if (mAIDInUse == ARAD) { 519 mCheckedRules = true; 520 } else { 521 updateState(STATE_LOADED, "Success!"); 522 } 523 } else { 524 mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, 525 P1, P2_EXTENDED_DATA, P3, DATA, 526 obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, 527 mChannelId, mAIDInUse)); 528 break; 529 } 530 } catch (IllegalArgumentException | IndexOutOfBoundsException ex) { 531 if (mAIDInUse == ARAM) { 532 updateState(STATE_ERROR, "Error parsing rules: " + ex); 533 } 534 } 535 } else { 536 if (mAIDInUse == ARAM) { 537 String errorMsg = "Invalid response: payload=" + response.payload 538 + " sw1=" + response.sw1 + " sw2=" + response.sw2; 539 updateState(STATE_ERROR, errorMsg); 540 } 541 } 542 } else { 543 String errorMsg = "Error reading value from SIM via " 544 + ((mAIDInUse == ARAD) ? "ARAD" : "ARAM") + " due to "; 545 if (ar.exception instanceof CommandException) { 546 CommandException.Error errorCode = 547 ((CommandException) (ar.exception)).getCommandError(); 548 errorMsg += "error code : " + errorCode; 549 } else { 550 errorMsg += "unknown exception : " + ar.exception.getMessage(); 551 } 552 if (mAIDInUse == ARAD) { 553 updateStatusMessage(errorMsg); 554 } else { 555 updateState(STATE_ERROR, errorMsg); 556 } 557 } 558 559 mUiccProfile.iccCloseLogicalChannel(mChannelId, obtainMessage( 560 EVENT_CLOSE_LOGICAL_CHANNEL_DONE, 0, mAIDInUse)); 561 mChannelId = -1; 562 break; 563 564 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 565 log("EVENT_CLOSE_LOGICAL_CHANNEL_DONE"); 566 if (mAIDInUse == ARAD) { 567 // Close logical channel with ARA_D and then open logical channel with ARA_M. 568 mRules = ""; 569 openChannel(ARAM); 570 } 571 break; 572 573 case EVENT_PKCS15_READ_DONE: 574 log("EVENT_PKCS15_READ_DONE"); 575 if (mUiccPkcs15 == null || mUiccPkcs15.getRules() == null) { 576 updateState(STATE_ERROR, "No ARA or ARF."); 577 } else { 578 for (String cert : mUiccPkcs15.getRules()) { 579 UiccAccessRule accessRule = new UiccAccessRule( 580 IccUtils.hexStringToBytes(cert), "", 0x00); 581 mAccessRules.add(accessRule); 582 } 583 updateState(STATE_LOADED, "Success!"); 584 } 585 break; 586 587 default: 588 Rlog.e(LOG_TAG, "Unknown event " + msg.what); 589 } 590 } 591 592 /* 593 * Check if all rule bytes have been read from UICC. 594 * For long payload, we need to fetch it repeatly before start parsing it. 595 */ isDataComplete()596 private boolean isDataComplete() { 597 log("isDataComplete mRules:" + mRules); 598 if (mRules.startsWith(TAG_ALL_REF_AR_DO)) { 599 TLV allRules = new TLV(TAG_ALL_REF_AR_DO); 600 String lengthBytes = allRules.parseLength(mRules); 601 log("isDataComplete lengthBytes: " + lengthBytes); 602 if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() + 603 allRules.length) { 604 log("isDataComplete yes"); 605 return true; 606 } else { 607 log("isDataComplete no"); 608 return false; 609 } 610 } else { 611 throw new IllegalArgumentException("Tags don't match."); 612 } 613 } 614 615 /* 616 * Parses the rules from the input string. 617 */ parseRules(String rules)618 private static List<UiccAccessRule> parseRules(String rules) { 619 log("Got rules: " + rules); 620 621 TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40 622 allRefArDo.parse(rules, true); 623 624 String arDos = allRefArDo.value; 625 List<UiccAccessRule> accessRules = new ArrayList<>(); 626 while (!arDos.isEmpty()) { 627 TLV refArDo = new TLV(TAG_REF_AR_DO); //E2 628 arDos = refArDo.parse(arDos, false); 629 UiccAccessRule accessRule = parseRefArdo(refArDo.value); 630 if (accessRule != null) { 631 accessRules.add(accessRule); 632 } else { 633 Rlog.e(LOG_TAG, "Skip unrecognized rule." + refArDo.value); 634 } 635 } 636 return accessRules; 637 } 638 639 /* 640 * Parses a single rule. 641 */ parseRefArdo(String rule)642 private static UiccAccessRule parseRefArdo(String rule) { 643 log("Got rule: " + rule); 644 645 String certificateHash = null; 646 String packageName = null; 647 String tmp = null; 648 long accessType = 0; 649 650 while (!rule.isEmpty()) { 651 if (rule.startsWith(TAG_REF_DO)) { 652 TLV refDo = new TLV(TAG_REF_DO); //E1 653 rule = refDo.parse(rule, false); 654 // Allow 4F tag with a default value "FF FF FF FF FF FF" to be compatible with 655 // devices having GP access control enforcer: 656 // - If no 4F tag is present, it's a CP rule. 657 // - If 4F tag has value "FF FF FF FF FF FF", it's a CP rule. 658 // - If 4F tag has other values, it's not a CP rule and Android should ignore it. 659 TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1 660 if (refDo.value.startsWith(TAG_AID_REF_DO)) { 661 TLV cpDo = new TLV(TAG_AID_REF_DO); //4F 662 String remain = cpDo.parse(refDo.value, false); 663 if (!cpDo.lengthBytes.equals("06") || !cpDo.value.equals(CARRIER_PRIVILEGE_AID) 664 || remain.isEmpty() || !remain.startsWith(TAG_DEVICE_APP_ID_REF_DO)) { 665 return null; 666 } 667 tmp = deviceDo.parse(remain, false); 668 certificateHash = deviceDo.value; 669 } else if (refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) { 670 tmp = deviceDo.parse(refDo.value, false); 671 certificateHash = deviceDo.value; 672 } else { 673 return null; 674 } 675 if (!tmp.isEmpty()) { 676 if (!tmp.startsWith(TAG_PKG_REF_DO)) { 677 return null; 678 } 679 TLV pkgDo = new TLV(TAG_PKG_REF_DO); //CA 680 pkgDo.parse(tmp, true); 681 packageName = new String(IccUtils.hexStringToBytes(pkgDo.value)); 682 } else { 683 packageName = null; 684 } 685 } else if (rule.startsWith(TAG_AR_DO)) { 686 TLV arDo = new TLV(TAG_AR_DO); //E3 687 rule = arDo.parse(rule, false); 688 // Skip all the irrelevant tags (All the optional tags here are two bytes 689 // according to the spec GlobalPlatform Secure Element Access Control). 690 String remain = arDo.value; 691 while (!remain.isEmpty() && !remain.startsWith(TAG_PERM_AR_DO)) { 692 TLV tmpDo = new TLV(remain.substring(0, 2)); 693 remain = tmpDo.parse(remain, false); 694 } 695 if (remain.isEmpty()) { 696 return null; 697 } 698 TLV permDo = new TLV(TAG_PERM_AR_DO); //DB 699 permDo.parse(remain, true); 700 } else { 701 // Spec requires it must be either TAG_REF_DO or TAG_AR_DO. 702 throw new RuntimeException("Invalid Rule type"); 703 } 704 } 705 706 UiccAccessRule accessRule = new UiccAccessRule( 707 IccUtils.hexStringToBytes(certificateHash), packageName, accessType); 708 return accessRule; 709 } 710 711 /* 712 * Updates the state and notifies the UiccCard that the rules have finished loading. 713 */ updateState(int newState, String statusMessage)714 private void updateState(int newState, String statusMessage) { 715 mState.set(newState); 716 if (mLoadedCallback != null) { 717 mLoadedCallback.sendToTarget(); 718 } 719 720 updateStatusMessage(statusMessage); 721 } 722 updateStatusMessage(String statusMessage)723 private void updateStatusMessage(String statusMessage) { 724 mStatusMessage.log(statusMessage); 725 } 726 log(String msg)727 private static void log(String msg) { 728 if (DBG) Rlog.d(LOG_TAG, msg); 729 } 730 731 /** 732 * Dumps info to Dumpsys - useful for debugging. 733 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)734 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 735 pw.println("UiccCarrierPrivilegeRules: " + this); 736 pw.println(" mState=" + getStateString(mState.get())); 737 pw.println(" mStatusMessage="); 738 mStatusMessage.dump(fd, pw, args); 739 if (mAccessRules != null) { 740 pw.println(" mAccessRules: "); 741 for (UiccAccessRule ar : mAccessRules) { 742 pw.println(" rule='" + ar + "'"); 743 } 744 } else { 745 pw.println(" mAccessRules: null"); 746 } 747 if (mUiccPkcs15 != null) { 748 pw.println(" mUiccPkcs15: " + mUiccPkcs15); 749 mUiccPkcs15.dump(fd, pw, args); 750 } else { 751 pw.println(" mUiccPkcs15: null"); 752 } 753 pw.flush(); 754 } 755 756 /* 757 * Converts state into human readable format. 758 */ getStateString(int state)759 private String getStateString(int state) { 760 switch (state) { 761 case STATE_LOADING: 762 return "STATE_LOADING"; 763 case STATE_LOADED: 764 return "STATE_LOADED"; 765 case STATE_ERROR: 766 return "STATE_ERROR"; 767 default: 768 return "UNKNOWN"; 769 } 770 } 771 } 772