UiccCarrierPrivilegeRules.java revision 32bbe4213fc554ebf00553cd9935d17fe7530aa1
14baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal/*
24baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Copyright (C) 2014 The Android Open Source Project
34baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
44baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Licensed under the Apache License, Version 2.0 (the "License");
54baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * you may not use this file except in compliance with the License.
64baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * You may obtain a copy of the License at
74baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
84baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *      http://www.apache.org/licenses/LICENSE-2.0
94baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Unless required by applicable law or agreed to in writing, software
114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * distributed under the License is distributed on an "AS IS" BASIS,
124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * See the License for the specific language governing permissions and
144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * limitations under the License.
154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */
164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalpackage com.android.internal.telephony.uicc;
184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
19c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.Intent;
20c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.pm.PackageInfo;
21c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.pm.PackageManager;
22c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.pm.ResolveInfo;
234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.content.pm.Signature;
244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.AsyncResult;
25c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.os.Binder;
264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.Handler;
274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.Message;
284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.telephony.Rlog;
294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.telephony.TelephonyManager;
304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport com.android.internal.telephony.CommandsInterface;
324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.io.ByteArrayInputStream;
354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.lang.IllegalArgumentException;
364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.MessageDigest;
374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.NoSuchAlgorithmException;
384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.Certificate;
394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.CertificateException;
404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.CertificateFactory;
414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.X509Certificate;
424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.ArrayList;
434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.Arrays;
444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.List;
454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.Locale;
467f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawalimport java.util.concurrent.atomic.AtomicInteger;
474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal/**
494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Class that reads and stores the carrier privileged rules from the UICC.
504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * The rules are read when the class is created, hence it should only be created
524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * after the UICC can be read. And it should be deleted when a UICC is changed.
534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * The spec for the rules:
55e5b5f10d2d09f62c265381cab0816edfbdf566f0Junda Liu *     GP Secure Element Access Control:
56e5b5f10d2d09f62c265381cab0816edfbdf566f0Junda Liu *     http://www.globalplatform.org/specifications/review/GPD_SE_Access_Control_v1.0.20.pdf
57e5b5f10d2d09f62c265381cab0816edfbdf566f0Junda Liu *     Extension spec:
58e5b5f10d2d09f62c265381cab0816edfbdf566f0Junda Liu *     https://code.google.com/p/seek-for-android/
594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * TODO: Notifications.
624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
634baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * {@hide}
644baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */
654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalpublic class UiccCarrierPrivilegeRules extends Handler {
664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String LOG_TAG = "UiccCarrierPrivilegeRules";
674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
68e5b5f10d2d09f62c265381cab0816edfbdf566f0Junda Liu    private static final String AID = "A00000015141434C00";
694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int CLA = 0x80;
70004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final int COMMAND = 0xB0;
71004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final int P1 = 0x00;
72004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final int P2 = 0x00;
734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int P3 = 0x00;
744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String DATA = "";
754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
76004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    /*
77004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     * Rules format:
78004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   ALL_REF_AR_DO = TAG_ALL_REF_AR_DO + len + [REF_AR_DO]*n
79004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   REF_AR_DO = TAG_REF_AR_DO + len + REF-DO + AR-DO
80004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *
81004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   REF_DO = TAG_REF_DO + len + DEVICE_APP_ID_REF_DO + (optional) PKG_REF_DO
82004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   AR_DO = TAG_AR_DO + len + PERM_AR_DO
83004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *
84004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   DEVICE_APP_ID_REF_DO = TAG_DEVICE_APP_ID_REF_DO + len + sha1 hexstring of cert (20 bytes)
85004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   PKG_REF_DO = TAG_PKG_REF_DO + len + package name
86004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   PERM_AR_DO = TAG_PERM_AR_DO + len + detailed permission (8 bytes)
87004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *
88004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     * Data objects hierarchy by TAG:
89004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     * FF40
90004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   E2
91004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *     E1
92004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *       C1
93004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *       CA
94004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *     E3
95004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *       DB
96004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     */
974baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // Values from the data standard.
984baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_ALL_REF_AR_DO = "FF40";
994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_REF_AR_DO = "E2";
1004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_REF_DO = "E1";
1014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_DEVICE_APP_ID_REF_DO = "C1";
1024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_PKG_REF_DO = "CA";
103004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final String TAG_AR_DO = "E3";
104004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final String TAG_PERM_AR_DO = "DB";
1054baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1;
1074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2;
1084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 3;
1094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // State of the object.
1114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int STATE_LOADING  = 0;
1124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int STATE_LOADED   = 1;
1134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int STATE_ERROR    = 2;
1144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // Describes a single rule.
1164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static class AccessRule {
1174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public byte[] certificateHash;
1184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public String packageName;
1194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public long accessType;   // This bit is not currently used, but reserved for future use.
1204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        AccessRule(byte[] certificateHash, String packageName, long accessType) {
1224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            this.certificateHash = certificateHash;
1234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            this.packageName = packageName;
1244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            this.accessType = accessType;
1254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        boolean matches(byte[] certHash, String packageName) {
1284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal          return certHash != null && Arrays.equals(this.certificateHash, certHash) &&
1294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                (this.packageName == null || this.packageName.equals(packageName));
1304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        @Override
1334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public String toString() {
1344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return "cert: " + certificateHash + " pkg: " + packageName +
1354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                " access: " + accessType;
1364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
1384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // Used for parsing the data from the UICC.
1404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static class TLV {
1414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        private String tag;
1424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        private Integer length;
1434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        private String value;
1444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public TLV(String tag) {
1464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            this.tag = tag;
1474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public String parse(String data, boolean shouldConsumeAll) {
150004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu            Rlog.d(LOG_TAG, "Parse TLV: " + tag);
1514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (!data.startsWith(tag)) {
1524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("Tags don't match.");
1534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            int index = tag.length();
1554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (index + 2 > data.length()) {
1564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("No length.");
1574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            length = new Integer(2 * Integer.parseInt(
1594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                    data.substring(index, index + 2), 16));
1604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            index += 2;
1614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            int remainingLength = data.length() - (index + length);
1634baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (remainingLength < 0) {
1644baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("Not enough data.");
1654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (shouldConsumeAll && (remainingLength != 0)) {
1674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("Did not consume all.");
1684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            value = data.substring(index, index + length);
1704baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
171004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu            Rlog.d(LOG_TAG, "Got TLV: " + tag + "," + length + "," + value);
1724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return data.substring(index + length);
1744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
1764baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private UiccCard mUiccCard;  // Parent
1784baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private AtomicInteger mState;
1794baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private List<AccessRule> mAccessRules;
1804baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1814baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    public UiccCarrierPrivilegeRules(UiccCard uiccCard) {
1824baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.d(LOG_TAG, "Creating UiccCarrierPrivilegeRules");
1834baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        mUiccCard = uiccCard;
1844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        mState = new AtomicInteger(STATE_LOADING);
1854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1864baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        // Start loading the rules.
1874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        mUiccCard.iccOpenLogicalChannel(AID,
1884baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, null));
1894baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
1904baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1914baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /**
192c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * Returns the status of the carrier privileges for the input certificate and package name.
1934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     *
1944baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * @param signature The signature of the certificate.
1954baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * @param packageName name of the package.
1964baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * @return Access status.
1974baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
198c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
1994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.d(LOG_TAG, "hasCarrierPrivileges: " + signature + " : " + packageName);
2004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        int state = mState.get();
2014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        if (state == STATE_LOADING) {
2024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            Rlog.d(LOG_TAG, "Rules not loaded.");
2034baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2044baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        } else if (state == STATE_ERROR) {
2054baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            Rlog.d(LOG_TAG, "Error loading rules.");
2064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
2074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
2084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
2094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        byte[] certHash = getCertHash(signature);
2104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        if (certHash == null) {
2114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal          return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
2134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.e(LOG_TAG, "Checking: " + IccUtils.bytesToHexString(certHash) + " : " + packageName);
2144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
2154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        for (AccessRule ar : mAccessRules) {
2164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (ar.matches(certHash, packageName)) {
217004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                Rlog.d(LOG_TAG, "Match found!");
2184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
2204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
2214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
2224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.d(LOG_TAG, "No matching rule found. Returning false.");
2234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
2254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
226c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    /**
227c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * Returns the status of the carrier privileges for the input package name.
228c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     *
229c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageManager PackageManager for getting signatures.
230c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageName name of the package.
231c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @return Access status.
232c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     */
233c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) {
234c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        try {
235c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            PackageInfo pInfo = packageManager.getPackageInfo(packageName,
236c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                PackageManager.GET_SIGNATURES);
237c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            Signature[] signatures = pInfo.signatures;
238c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            for (Signature sig : signatures) {
239c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                int accessStatus = getCarrierPrivilegeStatus(sig, pInfo.packageName);
240c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
241c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                    return accessStatus;
242c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                }
243c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
244c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        } catch (PackageManager.NameNotFoundException ex) {
245c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            Rlog.e(LOG_TAG, "NameNotFoundException", ex);
246c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
247c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
248c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
249c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
250c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    /**
251c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * Returns the status of the carrier privileges for the caller of the current transaction.
252c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     *
253c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageManager PackageManager for getting signatures and package names.
254c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @return Access status.
255c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     */
256c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) {
257c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        String[] packages = packageManager.getPackagesForUid(Binder.getCallingUid());
258c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
259c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        for (String pkg : packages) {
260c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            int accessStatus = getCarrierPrivilegeStatus(packageManager, pkg);
261c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
262c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                return accessStatus;
263c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
264c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
265c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
266c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
267c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
268c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    /**
2697f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     * Returns the package name of the carrier app that should handle the input intent.
270c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     *
271c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageManager PackageManager for getting receivers.
272c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param intent Intent that will be broadcast.
2737f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     * @return list of carrier app package names that can handle the intent.
2747f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     *         Returns null if there is an error and an empty list if there
2757f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     *         are no matching packages.
276c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     */
2777f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal    public List<String> getCarrierPackageNamesForBroadcastIntent(
278c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            PackageManager packageManager, Intent intent) {
2797f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal        List<String> packages = new ArrayList<String>();
280c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        List<ResolveInfo> receivers = packageManager.queryBroadcastReceivers(intent, 0);
281c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        for (ResolveInfo resolveInfo : receivers) {
282c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            if (resolveInfo.activityInfo == null) {
283c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                continue;
284c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
285c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            String packageName = resolveInfo.activityInfo.packageName;
2867f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            int status = getCarrierPrivilegeStatus(packageManager, packageName);
2877f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            if (status == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2887f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal                packages.add(packageName);
2897f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            } else if (status != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
2907f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal                // Any status apart from HAS_ACCESS and NO_ACCESS is considered an error.
2917f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal                return null;
292c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
293c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
294c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
2957f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal        return packages;
296c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
297c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
2984baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    @Override
2994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    public void handleMessage(Message msg) {
3004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        AsyncResult ar;
3014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        switch (msg.what) {
3034baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3044baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal          case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
3054baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              Rlog.d(LOG_TAG, "EVENT_OPEN_LOGICAL_CHANNEL_DONE");
3064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              ar = (AsyncResult) msg.obj;
3074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              if (ar.exception == null && ar.result != null) {
3084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  int channelId = ((int[]) ar.result)[0];
3094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  mUiccCard.iccTransmitApduLogicalChannel(channelId, CLA, COMMAND, P1, P2, P3, DATA,
3104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                      obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(channelId)));
3114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              } else {
3124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  Rlog.e(LOG_TAG, "Error opening channel");
3134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  mState.set(STATE_ERROR);
3144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              }
3154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              break;
3164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal          case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE:
3184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              Rlog.d(LOG_TAG, "EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE");
3194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              ar = (AsyncResult) msg.obj;
3204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              if (ar.exception == null && ar.result != null) {
3214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  IccIoResult response = (IccIoResult) ar.result;
3224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  if (response.payload != null && response.sw1 == 0x90 && response.sw2 == 0x00) {
3234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                      try {
3244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                          mAccessRules = parseRules(IccUtils.bytesToHexString(response.payload));
3254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                          mState.set(STATE_LOADED);
3264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                      } catch (IllegalArgumentException ex) {
3274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                          Rlog.e(LOG_TAG, "Error parsing rules: " + ex);
3284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                          mState.set(STATE_ERROR);
3294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                      }
3304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                   } else {
3314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                      Rlog.e(LOG_TAG, "Invalid response: payload=" + response.payload +
3324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                              " sw1=" + response.sw1 + " sw2=" + response.sw2);
3334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                   }
3344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              } else {
3354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  Rlog.e(LOG_TAG, "Error reading value from SIM.");
3364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                  mState.set(STATE_ERROR);
3374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              }
3384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              int channelId = (Integer) ar.userObj;
3404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              mUiccCard.iccCloseLogicalChannel(channelId, obtainMessage(
3414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                      EVENT_CLOSE_LOGICAL_CHANNEL_DONE));
3424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              break;
3434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal          case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
3454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              Rlog.d(LOG_TAG, "EVENT_CLOSE_LOGICAL_CHANNEL_DONE");
3464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              break;
3474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal          default:
3494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal              Rlog.e(LOG_TAG, "Unknown event " + msg.what);
3504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
3514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
3524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /*
3544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * Parses the rules from the input string.
3554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
3564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static List<AccessRule> parseRules(String rules) {
3574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        rules = rules.toUpperCase(Locale.US);
3584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.d(LOG_TAG, "Got rules: " + rules);
3594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
360004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu        TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40
3614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        allRefArDo.parse(rules, true);
3624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3634baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        String arDos = allRefArDo.value;
3644baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        List<AccessRule> accessRules = new ArrayList<AccessRule>();
3654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        while (!arDos.isEmpty()) {
366004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu            TLV refArDo = new TLV(TAG_REF_AR_DO); //E2
3674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            arDos = refArDo.parse(arDos, false);
36832bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            AccessRule accessRule = parseRefArdo(refArDo.value);
36932bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            if (accessRule != null) {
37032bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                accessRules.add(accessRule);
37132bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            } else {
37232bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu              Rlog.e(LOG_TAG, "Skip unrecognized rule." + refArDo.value);
37332bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            }
3744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
3754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return accessRules;
3764baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
3774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3784baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /*
3794baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * Parses a single rule.
3804baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
3814baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static AccessRule parseRefArdo(String rule) {
3824baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.d(LOG_TAG, "Got rule: " + rule);
3834baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        String certificateHash = null;
3854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        String packageName = null;
386004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu        String tmp = null;
3874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        long accessType = 0;
3884baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3894baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        while (!rule.isEmpty()) {
3904baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (rule.startsWith(TAG_REF_DO)) {
391004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV refDo = new TLV(TAG_REF_DO); //E1
3924baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                rule = refDo.parse(rule, false);
3934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
39432bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                // Skip unrelated rules.
39532bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                if (!refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
39632bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                    return null;
39732bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                }
39832bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu
399004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1
400004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                tmp = deviceDo.parse(refDo.value, false);
401004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                certificateHash = deviceDo.value;
402004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu
403004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                if (!tmp.isEmpty()) {
40432bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                  if (!tmp.startsWith(TAG_PKG_REF_DO)) {
40532bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                      return null;
40632bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                  }
407004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                  TLV pkgDo = new TLV(TAG_PKG_REF_DO); //CA
408004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                  pkgDo.parse(tmp, true);
409004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                  packageName = new String(IccUtils.hexStringToBytes(pkgDo.value));
4104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                } else {
411004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                  packageName = null;
4124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                }
4134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            } else if (rule.startsWith(TAG_AR_DO)) {
414004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV arDo = new TLV(TAG_AR_DO); //E3
4154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                rule = arDo.parse(rule, false);
4164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
41732bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                // Skip unrelated rules.
41832bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                if (!arDo.value.startsWith(TAG_PERM_AR_DO)) {
41932bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                    return null;
42032bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                }
42132bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu
422004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV permDo = new TLV(TAG_PERM_AR_DO); //DB
4234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                permDo.parse(arDo.value, true);
4244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                Rlog.e(LOG_TAG, permDo.value);
4254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            } else  {
42632bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                // Spec requires it must be either TAG_REF_DO or TAG_AR_DO.
4274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new RuntimeException("Invalid Rule type");
4284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
4294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
4304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.e(LOG_TAG, "Adding: " + certificateHash + " : " + packageName + " : " + accessType);
4324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        AccessRule accessRule = new AccessRule(IccUtils.hexStringToBytes(certificateHash),
4344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            packageName, accessType);
4354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.e(LOG_TAG, "Parsed rule: " + accessRule);
4364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return accessRule;
4374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
4384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /*
4404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * Converts a Signature into a Certificate hash usable for comparison.
4414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
4424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static byte[] getCertHash(Signature signature) {
4434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        // TODO: Is the following sufficient.
4444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        try {
4454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
4464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            X509Certificate cert = (X509Certificate) certFactory.generateCertificate(
4474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                    new ByteArrayInputStream(signature.toByteArray()));
4484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            MessageDigest md = MessageDigest.getInstance("SHA");
4504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return md.digest(cert.getEncoded());
4514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        } catch (CertificateException ex) {
4524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            Rlog.e(LOG_TAG, "CertificateException: " + ex);
4534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        } catch (NoSuchAlgorithmException ex) {
4544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            Rlog.e(LOG_TAG, "NoSuchAlgorithmException: " + ex);
4554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
4564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        Rlog.e(LOG_TAG, "Cannot compute cert hash");
4584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return null;
4594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
4604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal}
461