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