UiccCarrierPrivilegeRules.java revision 4baf17fd699249d1b387903b6db7328ad3f7b3e2
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 194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.content.pm.Signature; 204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.AsyncResult; 214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.Handler; 224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.Message; 234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.telephony.Rlog; 244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.telephony.TelephonyManager; 254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport com.android.internal.telephony.CommandsInterface; 274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils; 284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.io.ByteArrayInputStream; 304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.lang.IllegalArgumentException; 314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.MessageDigest; 324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.NoSuchAlgorithmException; 334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.Certificate; 344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.CertificateException; 354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.CertificateFactory; 364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.security.cert.X509Certificate; 374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.ArrayList; 384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.concurrent.atomic.AtomicInteger; 394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.Arrays; 404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.List; 414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.Locale; 424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal/** 444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Class that reads and stores the carrier privileged rules from the UICC. 454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * 464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * The rules are read when the class is created, hence it should only be created 474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * after the UICC can be read. And it should be deleted when a UICC is changed. 484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * 494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * The spec for the rules: 504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * TODO: Put link here. 514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * 524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * 534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * TODO: Notifications. 544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * 554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * {@hide} 564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalpublic class UiccCarrierPrivilegeRules extends Handler { 584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String LOG_TAG = "UiccCarrierPrivilegeRules"; 594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // TODO: These are temporary values. Put real ones here. 614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String AID = "A0000000015141434D"; 624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int CLA = 0x80; 634baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int COMMAND = 0xCA; 644baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int P1 = 0xFF; 654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int P2 = 0x40; 664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int P3 = 0x00; 674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String DATA = ""; 684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // Values from the data standard. 704baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_ALL_REF_AR_DO = "FF40"; 714baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_REF_AR_DO = "E2"; 724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_REF_DO = "E1"; 734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_AR_DO = "E3"; 744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_DEVICE_APP_ID_REF_DO = "C1"; 754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_PERM_AR_DO = "DB"; 764baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final String TAG_PKG_REF_DO = "CA"; 774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 784baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1; 794baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2; 804baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 3; 814baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 824baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // State of the object. 834baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int STATE_LOADING = 0; 844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int STATE_LOADED = 1; 854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static final int STATE_ERROR = 2; 864baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // Describes a single rule. 884baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static class AccessRule { 894baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public byte[] certificateHash; 904baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public String packageName; 914baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public long accessType; // This bit is not currently used, but reserved for future use. 924baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal AccessRule(byte[] certificateHash, String packageName, long accessType) { 944baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal this.certificateHash = certificateHash; 954baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal this.packageName = packageName; 964baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal this.accessType = accessType; 974baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 984baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal boolean matches(byte[] certHash, String packageName) { 1004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return certHash != null && Arrays.equals(this.certificateHash, certHash) && 1014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal (this.packageName == null || this.packageName.equals(packageName)); 1024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1034baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1044baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal @Override 1054baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public String toString() { 1064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return "cert: " + certificateHash + " pkg: " + packageName + 1074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal " access: " + accessType; 1084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // Used for parsing the data from the UICC. 1124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static class TLV { 1134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private String tag; 1144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private Integer length; 1154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private String value; 1164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public TLV(String tag) { 1184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal this.tag = tag; 1194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public String parse(String data, boolean shouldConsumeAll) { 1224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (!data.startsWith(tag)) { 1234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal throw new IllegalArgumentException("Tags don't match."); 1244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal int index = tag.length(); 1264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (index + 2 > data.length()) { 1274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal throw new IllegalArgumentException("No length."); 1284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal length = new Integer(2 * Integer.parseInt( 1304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal data.substring(index, index + 2), 16)); 1314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal index += 2; 1324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal int remainingLength = data.length() - (index + length); 1344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (remainingLength < 0) { 1354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal throw new IllegalArgumentException("Not enough data."); 1364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (shouldConsumeAll && (remainingLength != 0)) { 1384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal throw new IllegalArgumentException("Did not consume all."); 1394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal value = data.substring(index, index + length); 1414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Got TLV: " + tag + "," + length + "," + value); 1434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return data.substring(index + length); 1454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private UiccCard mUiccCard; // Parent 1494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private AtomicInteger mState; 1504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private List<AccessRule> mAccessRules; 1514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public UiccCarrierPrivilegeRules(UiccCard uiccCard) { 1534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "Creating UiccCarrierPrivilegeRules"); 1544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mUiccCard = uiccCard; 1554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mState = new AtomicInteger(STATE_LOADING); 1564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // Start loading the rules. 1584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mUiccCard.iccOpenLogicalChannel(AID, 1594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, null)); 1604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal /** 1634baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Returns true if the certificate and packageName has carrier privileges. 1644baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * 1654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * @param signature The signature of the certificate. 1664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * @param packageName name of the package. 1674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * @return Access status. 1684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 1694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public int hasCarrierPrivileges(Signature signature, String packageName) { 1704baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "hasCarrierPrivileges: " + signature + " : " + packageName); 1714baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal int state = mState.get(); 1724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (state == STATE_LOADING) { 1734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "Rules not loaded."); 1744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED; 1754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else if (state == STATE_ERROR) { 1764baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "Error loading rules."); 1774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES; 1784baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1794baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1804baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal byte[] certHash = getCertHash(signature); 1814baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (certHash == null) { 1824baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 1834baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Checking: " + IccUtils.bytesToHexString(certHash) + " : " + packageName); 1854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1864baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal for (AccessRule ar : mAccessRules) { 1874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (ar.matches(certHash, packageName)) { 1884baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 1894baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1904baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1914baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1924baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "No matching rule found. Returning false."); 1934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; 1944baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 1954baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 1964baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal @Override 1974baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal public void handleMessage(Message msg) { 1984baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal AsyncResult ar; 1994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal switch (msg.what) { 2014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal case EVENT_OPEN_LOGICAL_CHANNEL_DONE: 2034baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "EVENT_OPEN_LOGICAL_CHANNEL_DONE"); 2044baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal ar = (AsyncResult) msg.obj; 2054baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (ar.exception == null && ar.result != null) { 2064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal int channelId = ((int[]) ar.result)[0]; 2074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mUiccCard.iccTransmitApduLogicalChannel(channelId, CLA, COMMAND, P1, P2, P3, DATA, 2084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, new Integer(channelId))); 2094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else { 2104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Error opening channel"); 2114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mState.set(STATE_ERROR); 2124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal break; 2144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE: 2164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE"); 2174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal ar = (AsyncResult) msg.obj; 2184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (ar.exception == null && ar.result != null) { 2194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal IccIoResult response = (IccIoResult) ar.result; 2204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (response.payload != null && response.sw1 == 0x90 && response.sw2 == 0x00) { 2214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal try { 2224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mAccessRules = parseRules(IccUtils.bytesToHexString(response.payload)); 2234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mState.set(STATE_LOADED); 2244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } catch (IllegalArgumentException ex) { 2254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Error parsing rules: " + ex); 2264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mState.set(STATE_ERROR); 2274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else { 2294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Invalid response: payload=" + response.payload + 2304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal " sw1=" + response.sw1 + " sw2=" + response.sw2); 2314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else { 2334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Error reading value from SIM."); 2344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mState.set(STATE_ERROR); 2354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal int channelId = (Integer) ar.userObj; 2384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal mUiccCard.iccCloseLogicalChannel(channelId, obtainMessage( 2394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal EVENT_CLOSE_LOGICAL_CHANNEL_DONE)); 2404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal break; 2414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 2434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "EVENT_CLOSE_LOGICAL_CHANNEL_DONE"); 2444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal break; 2454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal default: 2474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Unknown event " + msg.what); 2484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal /* 2524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Parses the rules from the input string. 2534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 2544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static List<AccessRule> parseRules(String rules) { 2554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal rules = rules.toUpperCase(Locale.US); 2564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "Got rules: " + rules); 2574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal /* 2594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Rules format. 2604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * ALL_REF_AR_DO = TAG_ALL_REF_AR_DO + len + [REF_AR_DO]xn 2614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * REF_AR_DO = TAG_REF_AR_DO + len + REF-DO | AR-DO 2624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 2634baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); 2644baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal allRefArDo.parse(rules, true); 2654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal String arDos = allRefArDo.value; 2674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal List<AccessRule> accessRules = new ArrayList<AccessRule>(); 2684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal while (!arDos.isEmpty()) { 2694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV refArDo = new TLV(TAG_REF_AR_DO); 2704baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal arDos = refArDo.parse(arDos, false); 2714baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal accessRules.add(parseRefArdo(refArDo.value)); 2724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return accessRules; 2744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 2754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2764baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal /* 2774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Parses a single rule. 2784baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 2794baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static AccessRule parseRefArdo(String rule) { 2804baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.d(LOG_TAG, "Got rule: " + rule); 2814baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2824baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal /* 2834baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * REF_AR_DO = TAG_REF_AR_DO + len + REF-DO | AR-DO 2844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * REF_DO = TAG_REF_DO + len + DEVICE_APP_ID_REF_DO | PKG_REF_DO 2854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * AR_DO = TAG_AR_DO + len + PERM_AR_DO 2864baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * DEVICE_APP_ID_REF_DO = TAG_DEVICE_APP_ID_REF_DO + 20 | 0 + 20 byte hash (padded with FF) 2874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * PKG_REF_DO = TAG_PKG_REF_DO + 20 + 20 byte hash of package name (padded with FF) 2884baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * PERM_AR_DO = TAG_PERM_AR_DO + 8 + 8 bytes 2894baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 2904baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2914baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal String certificateHash = null; 2924baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal String packageName = null; 2934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal long accessType = 0; 2944baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 2954baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal while (!rule.isEmpty()) { 2964baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (rule.startsWith(TAG_REF_DO)) { 2974baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV refDo = new TLV(TAG_REF_DO); 2984baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal rule = refDo.parse(rule, false); 2994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal if (refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) { 3014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); 3024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal deviceDo.parse(refDo.value, true); 3034baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal certificateHash = deviceDo.value; 3044baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else if (refDo.value.startsWith(TAG_PKG_REF_DO)) { 3054baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV pkgDo = new TLV(TAG_PKG_REF_DO); 3064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal pkgDo.parse(refDo.value, true); 3074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal packageName = pkgDo.value; 3084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else { 3094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal throw new IllegalArgumentException( 3104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal "Invalid REF_DO value tag: " + refDo.value); 3114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 3124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else if (rule.startsWith(TAG_AR_DO)) { 3134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV arDo = new TLV(TAG_AR_DO); 3144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal rule = arDo.parse(rule, false); 3154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal TLV permDo = new TLV(TAG_PERM_AR_DO); 3174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal permDo.parse(arDo.value, true); 3184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, permDo.value); 3194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } else { 3204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // TODO: Mayabe just throw away rules that are not parseable. 3214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal throw new RuntimeException("Invalid Rule type"); 3224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 3234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 3244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Adding: " + certificateHash + " : " + packageName + " : " + accessType); 3264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal AccessRule accessRule = new AccessRule(IccUtils.hexStringToBytes(certificateHash), 3284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal packageName, accessType); 3294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Parsed rule: " + accessRule); 3304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return accessRule; 3314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 3324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal /* 3344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Converts a Signature into a Certificate hash usable for comparison. 3354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */ 3364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal private static byte[] getCertHash(Signature signature) { 3374baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal // TODO: Is the following sufficient. 3384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal try { 3394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); 3404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal X509Certificate cert = (X509Certificate) certFactory.generateCertificate( 3414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal new ByteArrayInputStream(signature.toByteArray())); 3424baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal MessageDigest md = MessageDigest.getInstance("SHA"); 3444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return md.digest(cert.getEncoded()); 3454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } catch (CertificateException ex) { 3464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "CertificateException: " + ex); 3474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } catch (NoSuchAlgorithmException ex) { 3484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "NoSuchAlgorithmException: " + ex); 3494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 3504baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal 3514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal Rlog.e(LOG_TAG, "Cannot compute cert hash"); 3524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal return null; 3534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal } 3544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal} 355