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