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.compat.annotation.UnsupportedAppUsage; 20 import android.content.pm.PackageInfo; 21 import android.content.pm.PackageManager; 22 import android.content.pm.Signature; 23 import android.os.AsyncResult; 24 import android.os.Binder; 25 import android.os.Build; 26 import android.os.Handler; 27 import android.os.Message; 28 import android.telephony.TelephonyManager; 29 import android.telephony.UiccAccessRule; 30 import android.text.TextUtils; 31 import android.util.IndentingPrintWriter; 32 import android.util.LocalLog; 33 34 import com.android.internal.annotations.VisibleForTesting; 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(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 131 private Integer length; 132 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 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(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 191 private AtomicInteger mState; 192 private List<UiccAccessRule> mAccessRules; 193 private String mRules; 194 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 195 private Message mLoadedCallback; 196 // LocalLog buffer to hold important status messages for debugging. 197 private LocalLog mStatusMessage = new LocalLog(64); 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 @VisibleForTesting UiccCarrierPrivilegeRules(List<UiccAccessRule> rules)232 public UiccCarrierPrivilegeRules(List<UiccAccessRule> rules) { 233 mAccessRules = rules; 234 mState = new AtomicInteger(STATE_LOADED); 235 mRules = ""; 236 mStatusMessage.log("Loaded from test rules."); 237 } 238 239 /** 240 * Returns true if the carrier privilege rules have finished loading. 241 */ areCarrierPriviligeRulesLoaded()242 public boolean areCarrierPriviligeRulesLoaded() { 243 return mState.get() != STATE_LOADING; 244 } 245 246 /** 247 * Returns true if the carrier privilege rules have finished loading and some rules were 248 * specified. 249 */ hasCarrierPrivilegeRules()250 public boolean hasCarrierPrivilegeRules() { 251 return mState.get() != STATE_LOADING && mAccessRules != null && mAccessRules.size() > 0; 252 } 253 254 /** 255 * Returns package names for privilege rules. 256 * Return empty list if no rules defined or package name is empty string. 257 */ getPackageNames()258 public List<String> getPackageNames() { 259 List<String> pkgNames = new ArrayList<String>(); 260 if (mAccessRules != null) { 261 for (UiccAccessRule ar : mAccessRules) { 262 if (!TextUtils.isEmpty(ar.getPackageName())) { 263 pkgNames.add(ar.getPackageName()); 264 } 265 } 266 } 267 return pkgNames; 268 } 269 270 /** 271 * Returns list of access rules. 272 */ getAccessRules()273 public List<UiccAccessRule> getAccessRules() { 274 if (mAccessRules == null) { 275 return Collections.emptyList(); 276 } 277 return Collections.unmodifiableList(mAccessRules); 278 } 279 280 /** 281 * Returns the status of the carrier privileges for the input certificate and package name. 282 * 283 * @param signature The signature of the certificate. 284 * @param packageName name of the package. 285 * @return Access status. 286 */ getCarrierPrivilegeStatus(Signature signature, String packageName)287 public int getCarrierPrivilegeStatus(Signature signature, String packageName) { 288 int state = mState.get(); 289 if (state == STATE_LOADING) { 290 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 291 } else if (state == STATE_ERROR) { 292 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 293 } 294 295 for (UiccAccessRule ar : mAccessRules) { 296 int accessStatus = ar.getCarrierPrivilegeStatus(signature, packageName); 297 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 298 return accessStatus; 299 } 300 } 301 302 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 303 } 304 305 /** 306 * Returns the status of the carrier privileges for the input package name. 307 * 308 * @param packageManager PackageManager for getting signatures. 309 * @param packageName name of the package. 310 * @return Access status. 311 */ getCarrierPrivilegeStatus(PackageManager packageManager, String packageName)312 public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) { 313 try { 314 // Short-circuit if there are no rules to check against, so we don't need to fetch 315 // the package info with signatures. 316 if (!hasCarrierPrivilegeRules()) { 317 int state = mState.get(); 318 if (state == STATE_LOADING) { 319 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 320 } else if (state == STATE_ERROR) { 321 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 322 } 323 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 324 } 325 // Include DISABLED_UNTIL_USED components. This facilitates cases where a carrier app 326 // is disabled by default, and some other component wants to enable it when it has 327 // gained carrier privileges (as an indication that a matching SIM has been inserted). 328 PackageInfo pInfo = packageManager.getPackageInfo(packageName, 329 PackageManager.GET_SIGNING_CERTIFICATES 330 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 331 | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS); 332 return getCarrierPrivilegeStatus(pInfo); 333 } catch (PackageManager.NameNotFoundException ex) { 334 log("Package " + packageName + " not found for carrier privilege status check"); 335 } 336 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 337 } 338 339 /** 340 * Returns the status of the carrier privileges for the input package info. 341 * 342 * @param packageInfo PackageInfo for the package, containing the package signatures. 343 * @return Access status. 344 */ getCarrierPrivilegeStatus(PackageInfo packageInfo)345 public int getCarrierPrivilegeStatus(PackageInfo packageInfo) { 346 int state = mState.get(); 347 if (state == STATE_LOADING) { 348 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 349 } else if (state == STATE_ERROR) { 350 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 351 } 352 353 for (UiccAccessRule ar : mAccessRules) { 354 int accessStatus = ar.getCarrierPrivilegeStatus(packageInfo); 355 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 356 return accessStatus; 357 } 358 } 359 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 360 } 361 362 /** 363 * Returns the status of the carrier privileges for the caller of the current transaction. 364 * 365 * @param packageManager PackageManager for getting signatures and package names. 366 * @return Access status. 367 */ getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager)368 public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) { 369 return getCarrierPrivilegeStatusForUid(packageManager, Binder.getCallingUid()); 370 } 371 372 /** 373 * Returns the status of the carrier privileges for the caller of the current transaction. 374 * 375 * @param packageManager PackageManager for getting signatures and package names. 376 * @return Access status. 377 */ getCarrierPrivilegeStatusForUid( PackageManager packageManager, int uid)378 public int getCarrierPrivilegeStatusForUid( 379 PackageManager packageManager, int uid) { 380 String[] packages = packageManager.getPackagesForUid(uid); 381 382 if (packages != null) { 383 for (String pkg : packages) { 384 int accessStatus = getCarrierPrivilegeStatus(packageManager, pkg); 385 if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { 386 return accessStatus; 387 } 388 } 389 } 390 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 391 } 392 393 /** 394 * The following three situations could be due to logical channels temporarily unavailable, so 395 * we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS: 1. MISSING_RESOURCE, 396 * 2. NO_SUCH_ELEMENT and the status code is 6985, 3. INTERNAL_ERR and the status code is 6999. 397 */ shouldRetry(AsyncResult ar, int retryCount)398 public static boolean shouldRetry(AsyncResult ar, int retryCount) { 399 if (ar.exception instanceof CommandException && retryCount < MAX_RETRY) { 400 CommandException.Error error = ((CommandException) (ar.exception)).getCommandError(); 401 int[] results = (int[]) ar.result; 402 int statusCode = 0; 403 if (ar.result != null && results.length == 3) { 404 byte[] bytes = new byte[]{(byte) results[1], (byte) results[2]}; 405 statusCode = Integer.parseInt(IccUtils.bytesToHexString(bytes), 16); 406 log("status code: " + String.valueOf(statusCode)); 407 } 408 return (error == CommandException.Error.MISSING_RESOURCE) 409 || (error == CommandException.Error.NO_SUCH_ELEMENT 410 && statusCode == STATUS_CODE_CONDITION_NOT_SATISFIED) 411 || (error == CommandException.Error.INTERNAL_ERR 412 && statusCode == STATUS_CODE_APPLET_SELECT_FAILED); 413 } 414 return false; 415 } 416 417 @Override handleMessage(Message msg)418 public void handleMessage(Message msg) { 419 AsyncResult ar; 420 mAIDInUse = msg.arg2; // 0 means ARA-D and 1 means ARA-M. 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 mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3, 430 DATA, false /*isEs10Command*/, obtainMessage( 431 EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, mChannelId, mAIDInUse)); 432 } else { 433 if (shouldRetry(ar, mRetryCount)) { 434 log("should retry"); 435 mRetryCount++; 436 removeCallbacks(mRetryRunnable); 437 postDelayed(mRetryRunnable, RETRY_INTERVAL_MS); 438 } else { 439 if (mAIDInUse == ARAD) { 440 // Open logical channel with ARA_M. 441 mRules = ""; 442 openChannel(ARAM); 443 } 444 if (mAIDInUse == ARAM) { 445 if (mCheckedRules) { 446 updateState(STATE_LOADED, "Success!"); 447 } else { 448 // if rules cannot be read from both ARA_D and ARA_M applet, 449 // fallback to PKCS15-based ARF. 450 log("No ARA, try ARF next."); 451 if (ar.exception instanceof CommandException 452 && ((CommandException) (ar.exception)).getCommandError() 453 != CommandException.Error.NO_SUCH_ELEMENT) { 454 updateStatusMessage("No ARA due to " 455 + 456 ((CommandException) (ar.exception)).getCommandError()); 457 } 458 mUiccPkcs15 = new UiccPkcs15(mUiccProfile, 459 obtainMessage(EVENT_PKCS15_READ_DONE)); 460 } 461 } 462 } 463 } 464 break; 465 466 case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE: 467 log("EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE"); 468 ar = (AsyncResult) msg.obj; 469 if (ar.exception == null && ar.result != null) { 470 IccIoResult response = (IccIoResult) ar.result; 471 if (response.sw1 == 0x90 && response.sw2 == 0x00 472 && response.payload != null && response.payload.length > 0) { 473 try { 474 mRules += IccUtils.bytesToHexString(response.payload) 475 .toUpperCase(Locale.US); 476 if (isDataComplete()) { 477 //TODO: here's where AccessRules are being updated from the psim 478 // b/139133814 479 mAccessRules.addAll(parseRules(mRules)); 480 if (mAIDInUse == ARAD) { 481 mCheckedRules = true; 482 } else { 483 updateState(STATE_LOADED, "Success!"); 484 } 485 } else { 486 mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, 487 P1, P2_EXTENDED_DATA, P3, DATA, false /*isEs10Command*/, 488 obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, 489 mChannelId, mAIDInUse)); 490 break; 491 } 492 } catch (IllegalArgumentException | IndexOutOfBoundsException ex) { 493 if (mAIDInUse == ARAM) { 494 updateState(STATE_ERROR, "Error parsing rules: " + ex); 495 } 496 } 497 } else { 498 if (mAIDInUse == ARAM) { 499 String errorMsg = "Invalid response: payload=" 500 + IccUtils.bytesToHexString(response.payload) 501 + " sw1=" + response.sw1 + " sw2=" + response.sw2; 502 updateState(STATE_ERROR, errorMsg); 503 } 504 } 505 } else { 506 String errorMsg = "Error reading value from SIM via " 507 + ((mAIDInUse == ARAD) ? "ARAD" : "ARAM") + " due to "; 508 if (ar.exception instanceof CommandException) { 509 CommandException.Error errorCode = 510 ((CommandException) (ar.exception)).getCommandError(); 511 errorMsg += "error code : " + errorCode; 512 } else { 513 errorMsg += "unknown exception : " + ar.exception.getMessage(); 514 } 515 if (mAIDInUse == ARAD) { 516 updateStatusMessage(errorMsg); 517 } else { 518 updateState(STATE_ERROR, errorMsg); 519 } 520 } 521 522 mUiccProfile.iccCloseLogicalChannel(mChannelId, false /*isEs10*/, obtainMessage( 523 EVENT_CLOSE_LOGICAL_CHANNEL_DONE, 0, mAIDInUse)); 524 mChannelId = -1; 525 break; 526 527 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 528 log("EVENT_CLOSE_LOGICAL_CHANNEL_DONE"); 529 if (mAIDInUse == ARAD) { 530 // Close logical channel with ARA_D and then open logical channel with ARA_M. 531 mRules = ""; 532 openChannel(ARAM); 533 } 534 break; 535 536 case EVENT_PKCS15_READ_DONE: 537 log("EVENT_PKCS15_READ_DONE"); 538 if (mUiccPkcs15 == null || mUiccPkcs15.getRules() == null) { 539 updateState(STATE_ERROR, "No ARA or ARF."); 540 } else { 541 for (String cert : mUiccPkcs15.getRules()) { 542 UiccAccessRule accessRule = new UiccAccessRule( 543 IccUtils.hexStringToBytes(cert), "", 0x00); 544 mAccessRules.add(accessRule); 545 } 546 updateState(STATE_LOADED, "Success!"); 547 } 548 break; 549 550 default: 551 Rlog.e(LOG_TAG, "Unknown event " + msg.what); 552 } 553 } 554 555 /* 556 * Check if all rule bytes have been read from UICC. 557 * For long payload, we need to fetch it repeatly before start parsing it. 558 */ isDataComplete()559 private boolean isDataComplete() { 560 log("isDataComplete mRules:" + mRules); 561 if (mRules.startsWith(TAG_ALL_REF_AR_DO)) { 562 TLV allRules = new TLV(TAG_ALL_REF_AR_DO); 563 String lengthBytes = allRules.parseLength(mRules); 564 log("isDataComplete lengthBytes: " + lengthBytes); 565 if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() + 566 allRules.length) { 567 log("isDataComplete yes"); 568 return true; 569 } else { 570 log("isDataComplete no"); 571 return false; 572 } 573 } else { 574 throw new IllegalArgumentException("Tags don't match."); 575 } 576 } 577 578 /* 579 * Parses the rules from the input string. 580 */ parseRules(String rules)581 private static List<UiccAccessRule> parseRules(String rules) { 582 log("Got rules: " + rules); 583 584 TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40 585 allRefArDo.parse(rules, true); 586 587 String arDos = allRefArDo.value; 588 List<UiccAccessRule> accessRules = new ArrayList<>(); 589 while (!arDos.isEmpty()) { 590 TLV refArDo = new TLV(TAG_REF_AR_DO); //E2 591 arDos = refArDo.parse(arDos, false); 592 UiccAccessRule accessRule = parseRefArdo(refArDo.value); 593 if (accessRule != null) { 594 accessRules.add(accessRule); 595 } else { 596 Rlog.e(LOG_TAG, "Skip unrecognized rule." + refArDo.value); 597 } 598 } 599 return accessRules; 600 } 601 602 /* 603 * Parses a single rule. 604 */ parseRefArdo(String rule)605 private static UiccAccessRule parseRefArdo(String rule) { 606 log("Got rule: " + rule); 607 608 String certificateHash = null; 609 String packageName = null; 610 String tmp = null; 611 long accessType = 0; 612 613 while (!rule.isEmpty()) { 614 if (rule.startsWith(TAG_REF_DO)) { 615 TLV refDo = new TLV(TAG_REF_DO); //E1 616 rule = refDo.parse(rule, false); 617 // Allow 4F tag with a default value "FF FF FF FF FF FF" to be compatible with 618 // devices having GP access control enforcer: 619 // - If no 4F tag is present, it's a CP rule. 620 // - If 4F tag has value "FF FF FF FF FF FF", it's a CP rule. 621 // - If 4F tag has other values, it's not a CP rule and Android should ignore it. 622 TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1 623 if (refDo.value.startsWith(TAG_AID_REF_DO)) { 624 TLV cpDo = new TLV(TAG_AID_REF_DO); //4F 625 String remain = cpDo.parse(refDo.value, false); 626 if (!cpDo.lengthBytes.equals("06") || !cpDo.value.equals(CARRIER_PRIVILEGE_AID) 627 || remain.isEmpty() || !remain.startsWith(TAG_DEVICE_APP_ID_REF_DO)) { 628 return null; 629 } 630 tmp = deviceDo.parse(remain, false); 631 certificateHash = deviceDo.value; 632 } else if (refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) { 633 tmp = deviceDo.parse(refDo.value, false); 634 certificateHash = deviceDo.value; 635 } else { 636 return null; 637 } 638 if (!tmp.isEmpty()) { 639 if (!tmp.startsWith(TAG_PKG_REF_DO)) { 640 return null; 641 } 642 TLV pkgDo = new TLV(TAG_PKG_REF_DO); //CA 643 pkgDo.parse(tmp, true); 644 packageName = new String(IccUtils.hexStringToBytes(pkgDo.value)); 645 } else { 646 packageName = null; 647 } 648 } else if (rule.startsWith(TAG_AR_DO)) { 649 TLV arDo = new TLV(TAG_AR_DO); //E3 650 rule = arDo.parse(rule, false); 651 // Skip all the irrelevant tags (All the optional tags here are two bytes 652 // according to the spec GlobalPlatform Secure Element Access Control). 653 String remain = arDo.value; 654 while (!remain.isEmpty() && !remain.startsWith(TAG_PERM_AR_DO)) { 655 TLV tmpDo = new TLV(remain.substring(0, 2)); 656 remain = tmpDo.parse(remain, false); 657 } 658 if (remain.isEmpty()) { 659 return null; 660 } 661 TLV permDo = new TLV(TAG_PERM_AR_DO); //DB 662 permDo.parse(remain, true); 663 } else { 664 // Spec requires it must be either TAG_REF_DO or TAG_AR_DO. 665 throw new RuntimeException("Invalid Rule type"); 666 } 667 } 668 669 UiccAccessRule accessRule = new UiccAccessRule( 670 IccUtils.hexStringToBytes(certificateHash), packageName, accessType); 671 return accessRule; 672 } 673 674 /* 675 * Updates the state and notifies the UiccCard that the rules have finished loading. 676 */ updateState(int newState, String statusMessage)677 private void updateState(int newState, String statusMessage) { 678 mState.set(newState); 679 if (mLoadedCallback != null) { 680 mLoadedCallback.sendToTarget(); 681 } 682 683 updateStatusMessage(statusMessage); 684 } 685 updateStatusMessage(String statusMessage)686 private void updateStatusMessage(String statusMessage) { 687 mStatusMessage.log(statusMessage); 688 } 689 log(String msg)690 private static void log(String msg) { 691 if (DBG) Rlog.d(LOG_TAG, msg); 692 } 693 694 /** 695 * Dumps info to Dumpsys - useful for debugging. 696 */ dump(FileDescriptor fd, PrintWriter printWriter, String[] args)697 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 698 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 699 pw.println("UiccCarrierPrivilegeRules:"); 700 pw.increaseIndent(); 701 pw.println("mState=" + getStateString(mState.get())); 702 pw.println("mStatusMessage="); 703 mStatusMessage.dump(fd, pw, args); 704 if (mAccessRules != null) { 705 pw.println("mAccessRules: "); 706 pw.increaseIndent(); 707 for (UiccAccessRule ar : mAccessRules) { 708 pw.println(" rule='" + ar + "'"); 709 } 710 pw.decreaseIndent(); 711 } else { 712 pw.println(" mAccessRules: null"); 713 } 714 if (mUiccPkcs15 != null) { 715 pw.println(" mUiccPkcs15: " + mUiccPkcs15); 716 mUiccPkcs15.dump(fd, pw, args); 717 } else { 718 pw.println(" mUiccPkcs15: null"); 719 } 720 pw.decreaseIndent(); 721 pw.flush(); 722 } 723 724 /* 725 * Converts state into human readable format. 726 */ getStateString(int state)727 private String getStateString(int state) { 728 switch (state) { 729 case STATE_LOADING: 730 return "STATE_LOADING"; 731 case STATE_LOADED: 732 return "STATE_LOADED"; 733 case STATE_ERROR: 734 return "STATE_ERROR"; 735 default: 736 return "UNKNOWN"; 737 } 738 } 739 } 740