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