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