1a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu/* 2a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Copyright (C) 2016 The Android Open Source Project 3a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * 4a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Licensed under the Apache License, Version 2.0 (the "License"); 5a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * you may not use this file except in compliance with the License. 6a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * You may obtain a copy of the License at 7a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * 8a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * http://www.apache.org/licenses/LICENSE-2.0 9a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * 10a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Unless required by applicable law or agreed to in writing, software 11a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * distributed under the License is distributed on an "AS IS" BASIS, 12a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * See the License for the specific language governing permissions and 14a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * limitations under the License. 15a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu */ 16a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 17a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liupackage com.android.internal.telephony.uicc; 18a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 19a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport android.os.AsyncResult; 20a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport android.os.Binder; 21a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport android.os.Handler; 22a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport android.os.Message; 23a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport android.telephony.Rlog; 24a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport android.telephony.TelephonyManager; 25a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 26a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport com.android.internal.telephony.CommandException; 27a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport com.android.internal.telephony.CommandsInterface; 28a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport com.android.internal.telephony.uicc.IccUtils; 29a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules.TLV; 30a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 31a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.io.ByteArrayInputStream; 32a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.io.FileDescriptor; 33a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.io.PrintWriter; 34a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.lang.IllegalArgumentException; 35a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.lang.IndexOutOfBoundsException; 36a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.util.ArrayList; 37a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.util.Arrays; 38a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liuimport java.util.List; 396ecde9339aae07c53148d6785c3d3c36eec501b1Junda Liuimport java.util.Locale; 40a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 41a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu/** 42a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Class that reads PKCS15-based rules for carrier privileges. 43a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * 44a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * The spec for the rules: 45a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * GP Secure Element Access Control: 46a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * https://www.globalplatform.org/specificationsdevice.asp 47a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * 48a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * The UiccPkcs15 class handles overall flow of finding/selecting PKCS15 applet 49a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * and reading/parsing each file. Because PKCS15 can be selected in 2 different ways: 50a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * via logical channel or EF_DIR, PKCS15Selector is a handler to encapsulate the flow. 51a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Similarly, FileHandler is used for selecting/reading each file, so common codes are 52a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * all in same place. 53a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * 54a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * {@hide} 55a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu */ 56a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liupublic class UiccPkcs15 extends Handler { 57a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String LOG_TAG = "UiccPkcs15"; 58a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final boolean DBG = true; 59a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 60a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // File handler for PKCS15 files, select file and read binary, 61a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // convert to String then send to callback message. 62a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private class FileHandler extends Handler { 63a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // EF path for PKCS15 root, eg. "3F007F50" 64a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // null if logical channel is used for PKCS15 access. 65a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private final String mPkcs15Path; 66a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // Message to send when file has been parsed. 67a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private Message mCallback; 68a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // File id to read data from, eg. "5031" 69a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private String mFileId; 70a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 71a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // async events for the sequence of select and read 72a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu static protected final int EVENT_SELECT_FILE_DONE = 101; 73a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu static protected final int EVENT_READ_BINARY_DONE = 102; 74a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 75a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // pkcs15Path is nullable when using logical channel 76a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public FileHandler(String pkcs15Path) { 77a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Creating FileHandler, pkcs15Path: " + pkcs15Path); 78a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mPkcs15Path = pkcs15Path; 79a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 80a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 81a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public boolean loadFile(String fileId, Message callBack) { 82a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("loadFile: " + fileId); 83a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (fileId == null || callBack == null) return false; 84a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mFileId = fileId; 85a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mCallback = callBack; 86a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu selectFile(); 87a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu return true; 88a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 89a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 90a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private void selectFile() { 91a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (mChannelId >= 0) { 92a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mUiccCard.iccTransmitApduLogicalChannel(mChannelId, 0x00, 0xA4, 0x00, 0x04, 0x02, 93a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mFileId, obtainMessage(EVENT_SELECT_FILE_DONE)); 94a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } else { 95a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("EF based"); 96a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 97a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 98a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 99a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private void readBinary() { 100a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (mChannelId >=0 ) { 101a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mUiccCard.iccTransmitApduLogicalChannel(mChannelId, 0x00, 0xB0, 0x00, 0x00, 0x00, 102a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu "", obtainMessage(EVENT_READ_BINARY_DONE)); 103a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } else { 104a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("EF based"); 105a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 106a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 107a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 108a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu @Override 109a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public void handleMessage(Message msg) { 110a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("handleMessage: " + msg.what); 111a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult ar = (AsyncResult) msg.obj; 112a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (ar.exception != null || ar.result == null) { 113a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Error: " + ar.exception); 114a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult.forMessage(mCallback, null, ar.exception); 115a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mCallback.sendToTarget(); 116a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu return; 117a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 118a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 119a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu switch (msg.what) { 120a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_SELECT_FILE_DONE: 121a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu readBinary(); 122a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 123a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 124a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_READ_BINARY_DONE: 125a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu IccIoResult response = (IccIoResult) ar.result; 1266ecde9339aae07c53148d6785c3d3c36eec501b1Junda Liu String result = IccUtils.bytesToHexString(response.payload) 1276ecde9339aae07c53148d6785c3d3c36eec501b1Junda Liu .toUpperCase(Locale.US); 128a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("IccIoResult: " + response + " payload: " + result); 129a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult.forMessage(mCallback, result, (result == null) ? 130a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu new IccException("Error: null response for " + mFileId) : null); 131a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mCallback.sendToTarget(); 132a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 133a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 134a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu default: 135a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Unknown event" + msg.what); 136a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 137a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 138a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 139a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 140a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private class Pkcs15Selector extends Handler { 141a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String PKCS15_AID = "A000000063504B43532D3135"; 142a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private Message mCallback; 143a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 201; 144a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 145a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public Pkcs15Selector(Message callBack) { 146a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mCallback = callBack; 147c6676c9a97efb78950c8f71ca7330d0bb4b24efdAjay Nambi // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested. 148c6676c9a97efb78950c8f71ca7330d0bb4b24efdAjay Nambi int p2 = 0x04; 149c6676c9a97efb78950c8f71ca7330d0bb4b24efdAjay Nambi mUiccCard.iccOpenLogicalChannel(PKCS15_AID, p2, /* supported P2 value */ 150a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE)); 151a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 152a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 153a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu @Override 154a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public void handleMessage(Message msg) { 155a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("handleMessage: " + msg.what); 156a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult ar; 157a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 158a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu switch (msg.what) { 159a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_OPEN_LOGICAL_CHANNEL_DONE: 160a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu ar = (AsyncResult) msg.obj; 161a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (ar.exception == null && ar.result != null) { 162a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mChannelId = ((int[]) ar.result)[0]; 163a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("mChannelId: " + mChannelId); 164a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult.forMessage(mCallback, null, null); 165a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } else { 166a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("error: " + ar.exception); 167a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult.forMessage(mCallback, null, ar.exception); 168a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // TODO: don't sendToTarget and read EF_DIR to find PKCS15 169a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 170a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mCallback.sendToTarget(); 171a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 172a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 173a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu default: 174a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Unknown event" + msg.what); 175a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 176a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 177a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 178a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 179a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private UiccCard mUiccCard; // Parent 180a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private Message mLoadedCallback; 181a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private int mChannelId = -1; // Channel Id for communicating with UICC. 182a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private List<String> mRules = new ArrayList<String>(); 183a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private Pkcs15Selector mPkcs15Selector; 184a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private FileHandler mFh; 185a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 186a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_SELECT_PKCS15_DONE = 1; 187a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_LOAD_ODF_DONE = 2; 188a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_LOAD_DODF_DONE = 3; 189a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_LOAD_ACMF_DONE = 4; 190a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_LOAD_ACRF_DONE = 5; 191a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_LOAD_ACCF_DONE = 6; 192a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 7; 193a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 194a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public UiccPkcs15(UiccCard uiccCard, Message loadedCallback) { 195a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Creating UiccPkcs15"); 196a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mUiccCard = uiccCard; 197a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mLoadedCallback = loadedCallback; 198a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mPkcs15Selector = new Pkcs15Selector(obtainMessage(EVENT_SELECT_PKCS15_DONE)); 199a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 200a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 201a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu @Override 202a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public void handleMessage(Message msg) { 203a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("handleMessage: " + msg.what); 204a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu AsyncResult ar = (AsyncResult) msg.obj; 205a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 206a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu switch (msg.what) { 207a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_SELECT_PKCS15_DONE: 208a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (ar.exception == null) { 209a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // ar.result is null if using logical channel, 210a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // or string for pkcs15 path if using file access. 211a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mFh = new FileHandler((String)ar.result); 212a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (!mFh.loadFile(ID_ACRF, obtainMessage(EVENT_LOAD_ACRF_DONE))) { 213a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu cleanUp(); 214a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 215a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } else { 216a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("select pkcs15 failed: " + ar.exception); 217a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // select PKCS15 failed, notify uiccCarrierPrivilegeRules 218a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mLoadedCallback.sendToTarget(); 219a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 220a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 221a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 222a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_LOAD_ACRF_DONE: 223a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (ar.exception == null && ar.result != null) { 224a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu String idAccf = parseAcrf((String)ar.result); 225a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (!mFh.loadFile(idAccf, obtainMessage(EVENT_LOAD_ACCF_DONE))) { 226a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu cleanUp(); 227a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 228df3c262824b7e791027d2ec24c4f5d3040d21286fionaxu } else { 229df3c262824b7e791027d2ec24c4f5d3040d21286fionaxu cleanUp(); 230a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 231a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 232a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 233a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_LOAD_ACCF_DONE: 234a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (ar.exception == null && ar.result != null) { 235a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu parseAccf((String)ar.result); 236a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 237a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // We are done here, no more file to read 238a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu cleanUp(); 239a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 240a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 241a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: 242a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; 243a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 244a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu default: 245a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu Rlog.e(LOG_TAG, "Unknown event " + msg.what); 246a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 247a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 248a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 249a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private void cleanUp() { 250a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("cleanUp"); 251a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (mChannelId >= 0) { 252a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mUiccCard.iccCloseLogicalChannel(mChannelId, obtainMessage( 253a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu EVENT_CLOSE_LOGICAL_CHANNEL_DONE)); 254a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mChannelId = -1; 255a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 256a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mLoadedCallback.sendToTarget(); 257a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 258a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 259a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // Constants defined in specs, needed for parsing 260a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String CARRIER_RULE_AID = "FFFFFFFFFFFF"; // AID for carrier privilege rule 261a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String ID_ACRF = "4300"; 262a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String TAG_ASN_SEQUENCE = "30"; 263a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String TAG_ASN_OCTET_STRING = "04"; 264a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static final String TAG_TARGET_AID = "A0"; 265a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 266a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // parse ACRF file to get file id for ACCF file 267a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // data is hex string, return file id if parse success, null otherwise 268a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private String parseAcrf(String data) { 269a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu String ret = null; 270a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 271a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu String acRules = data; 272a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu while (!acRules.isEmpty()) { 273a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvRule = new TLV(TAG_ASN_SEQUENCE); 274a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu try { 275a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu acRules = tlvRule.parse(acRules, false); 276a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu String ruleString = tlvRule.getValue(); 277a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (ruleString.startsWith(TAG_TARGET_AID)) { 278a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // rule string consists of target AID + path, example: 279a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // [A0] 08 [04] 06 FF FF FF FF FF FF [30] 04 [04] 02 43 10 280a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // bytes in [] are tags for the data 281a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvTarget = new TLV(TAG_TARGET_AID); // A0 282a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvAid = new TLV(TAG_ASN_OCTET_STRING); // 04 283a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvAsnPath = new TLV(TAG_ASN_SEQUENCE); // 30 284a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvPath = new TLV(TAG_ASN_OCTET_STRING); // 04 285a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 286a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // populate tlvTarget.value with aid data, 287a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // ruleString has remaining data for path 288a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu ruleString = tlvTarget.parse(ruleString, false); 289a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // parse tlvTarget.value to get actual strings for AID. 290a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // no other tags expected so shouldConsumeAll is true. 291a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu tlvAid.parse(tlvTarget.getValue(), true); 292a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 293a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (CARRIER_RULE_AID.equals(tlvAid.getValue())) { 294a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu tlvAsnPath.parse(ruleString, true); 295a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu tlvPath.parse(tlvAsnPath.getValue(), true); 296a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu ret = tlvPath.getValue(); 297a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 298a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 299a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu continue; // skip current rule as it doesn't have expected TAG 300a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } catch (IllegalArgumentException|IndexOutOfBoundsException ex) { 301a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Error: " + ex); 302a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; // Bad data, ignore all remaining ACRules 303a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 304a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 305a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu return ret; 306a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 307a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 308a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu // parse ACCF and add to mRules 309a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private void parseAccf(String data) { 310a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu String acCondition = data; 311a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu while (!acCondition.isEmpty()) { 312a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvCondition = new TLV(TAG_ASN_SEQUENCE); 313a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu TLV tlvCert = new TLV(TAG_ASN_OCTET_STRING); 314a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu try { 315a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu acCondition = tlvCondition.parse(acCondition, false); 316a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu tlvCert.parse(tlvCondition.getValue(), true); 317a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (!tlvCert.getValue().isEmpty()) { 318a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu mRules.add(tlvCert.getValue()); 319a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 320a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } catch (IllegalArgumentException|IndexOutOfBoundsException ex) { 321a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu log("Error: " + ex); 322a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu break; // Bad data, ignore all remaining acCondition data 323a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 324a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 325a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 326a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 327a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public List<String> getRules() { 328a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu return mRules; 329a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 330a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 331a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu private static void log(String msg) { 332a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (DBG) Rlog.d(LOG_TAG, msg); 333a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 334a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu 335a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu /** 336a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Dumps info to Dumpsys - useful for debugging. 337a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu */ 338a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 339a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu if (mRules != null) { 340a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu pw.println(" mRules:"); 341a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu for (String cert : mRules) { 342a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu pw.println(" " + cert); 343a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 344a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 345a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu } 346a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu} 347