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