1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /*
17  * Copyright (c) 2015-2017, The Linux Foundation.
18  */
19 
20 /*
21  * Contributed by: Giesecke & Devrient GmbH.
22  */
23 
24 package com.android.se;
25 
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.PackageManager.NameNotFoundException;
31 import android.hardware.secure_element.V1_0.ISecureElement;
32 import android.hardware.secure_element.V1_0.ISecureElementHalCallback;
33 import android.hardware.secure_element.V1_0.LogicalChannelResponse;
34 import android.hardware.secure_element.V1_0.SecureElementStatus;
35 import android.os.Build;
36 import android.os.Handler;
37 import android.os.HwBinder;
38 import android.os.Message;
39 import android.os.RemoteException;
40 import android.os.ServiceSpecificException;
41 import android.os.UserHandle;
42 import android.se.omapi.ISecureElementListener;
43 import android.se.omapi.ISecureElementReader;
44 import android.se.omapi.ISecureElementSession;
45 import android.se.omapi.SEService;
46 import android.util.Log;
47 
48 import com.android.se.SecureElementService.SecureElementSession;
49 import com.android.se.internal.ByteArrayConverter;
50 import com.android.se.security.AccessControlEnforcer;
51 import com.android.se.security.ChannelAccess;
52 
53 import java.io.IOException;
54 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Collection;
58 import java.util.HashMap;
59 import java.util.Map;
60 import java.util.MissingResourceException;
61 import java.util.NoSuchElementException;
62 
63 /**
64  * Each Terminal represents a Secure Element.
65  * Communicates to the SE via SecureElement HAL.
66  */
67 public class Terminal {
68 
69     private final String mTag;
70     private final Map<Integer, Channel> mChannels = new HashMap<Integer, Channel>();
71     private final Object mLock = new Object();
72     private final String mName;
73     public boolean mIsConnected = false;
74     private Context mContext;
75     private boolean mDefaultApplicationSelectedOnBasicChannel = true;
76 
77     private static final boolean DEBUG = Build.IS_DEBUGGABLE;
78     private static final int GET_SERVICE_DELAY_MILLIS = 4 * 1000;
79     private static final int EVENT_GET_HAL = 1;
80 
81     private final int mMaxGetHalRetryCount = 5;
82     private int mGetHalRetryCount = 0;
83 
84     private ISecureElement mSEHal;
85     private android.hardware.secure_element.V1_2.ISecureElement mSEHal12;
86 
87     /** For each Terminal there will be one AccessController object. */
88     private AccessControlEnforcer mAccessControlEnforcer;
89 
90     private static final String SECURE_ELEMENT_PRIVILEGED_OPERATION_PERMISSION =
91             "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
92 
93     public static final byte[] ISD_R_AID =
94             new byte[]{
95                     (byte) 0xA0,
96                     (byte) 0x00,
97                     (byte) 0x00,
98                     (byte) 0x05,
99                     (byte) 0x59,
100                     (byte) 0x10,
101                     (byte) 0x10,
102                     (byte) 0xFF,
103                     (byte) 0xFF,
104                     (byte) 0xFF,
105                     (byte) 0xFF,
106                     (byte) 0x89,
107                     (byte) 0x00,
108                     (byte) 0x00,
109                     (byte) 0x01,
110                     (byte) 0x00,
111             };
112 
113     private ISecureElementHalCallback.Stub mHalCallback = new ISecureElementHalCallback.Stub() {
114         @Override
115         public void onStateChange(boolean state) {
116             stateChange(state, "");
117         }
118     };
119 
120     private android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub mHalCallback11 =
121             new android.hardware.secure_element.V1_1.ISecureElementHalCallback.Stub() {
122         @Override
123         public void onStateChange_1_1(boolean state, String reason) {
124             stateChange(state, reason);
125         }
126 
127         public void onStateChange(boolean state) {
128             return;
129         }
130     };
131 
stateChange(boolean state, String reason)132     private void stateChange(boolean state, String reason) {
133         synchronized (mLock) {
134             Log.i(mTag, "OnStateChange:" + state + " reason:" + reason);
135             mIsConnected = state;
136             if (!state) {
137                 if (mAccessControlEnforcer != null) {
138                     mAccessControlEnforcer.reset();
139                 }
140                 SecureElementStatsLog.write(
141                         SecureElementStatsLog.SE_STATE_CHANGED,
142                         SecureElementStatsLog.SE_STATE_CHANGED__STATE__DISCONNECTED,
143                         reason,
144                         mName);
145             } else {
146                 // If any logical channel in use is in the channel list, it should be closed
147                 // because the access control enfocer allowed to open it by checking the access
148                 // rules retrieved before. Now we are going to retrieve the rules again and
149                 // the new rules can be different from the previous ones.
150                 closeChannels();
151                 try {
152                     initializeAccessControl();
153                 } catch (Exception e) {
154                     // ignore
155                 }
156                 mDefaultApplicationSelectedOnBasicChannel = true;
157                 SecureElementStatsLog.write(
158                         SecureElementStatsLog.SE_STATE_CHANGED,
159                         SecureElementStatsLog.SE_STATE_CHANGED__STATE__CONNECTED,
160                         reason,
161                         mName);
162             }
163 
164             sendStateChangedBroadcast(state);
165         }
166     }
167 
sendStateChangedBroadcast(boolean state)168     private void sendStateChangedBroadcast(boolean state) {
169         Intent intent = new Intent(SEService.ACTION_SECURE_ELEMENT_STATE_CHANGED);
170         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
171         intent.putExtra(SEService.EXTRA_READER_NAME, mName);
172         intent.putExtra(SEService.EXTRA_READER_STATE, state);
173         mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
174     };
175 
176     class SecureElementDeathRecipient implements HwBinder.DeathRecipient {
177         @Override
serviceDied(long cookie)178         public void serviceDied(long cookie) {
179             Log.e(mTag, mName + " died");
180             SecureElementStatsLog.write(
181                     SecureElementStatsLog.SE_STATE_CHANGED,
182                     SecureElementStatsLog.SE_STATE_CHANGED__STATE__HALCRASH,
183                     "HALCRASH",
184                     mName);
185             synchronized (mLock) {
186                 mIsConnected = false;
187                 if (mAccessControlEnforcer != null) {
188                     mAccessControlEnforcer.reset();
189                 }
190             }
191             mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_GET_HAL, 0),
192                     GET_SERVICE_DELAY_MILLIS);
193         }
194     }
195 
196     private HwBinder.DeathRecipient mDeathRecipient = new SecureElementDeathRecipient();
197 
198     private Handler mHandler = new Handler() {
199         @Override
200         public void handleMessage(Message message) {
201             switch (message.what) {
202                 case EVENT_GET_HAL:
203                     try {
204                         if (mName.startsWith(SecureElementService.ESE_TERMINAL)) {
205                             initialize(true);
206                         } else {
207                             initialize(false);
208                         }
209                     } catch (Exception e) {
210                         Log.e(mTag, mName + " could not be initialized again");
211                         if (mGetHalRetryCount < mMaxGetHalRetryCount) {
212                             mGetHalRetryCount++;
213                             sendMessageDelayed(obtainMessage(EVENT_GET_HAL, 0),
214                                     GET_SERVICE_DELAY_MILLIS);
215                         } else {
216                             Log.e(mTag, mName + " reach maximum retry count");
217                         }
218                     }
219                     break;
220                 default:
221                     break;
222             }
223         }
224     };
225 
Terminal(String name, Context context)226     public Terminal(String name, Context context) {
227         mContext = context;
228         mName = name;
229         mTag = "SecureElement-Terminal-" + getName();
230     }
231 
232     /**
233      * Initializes the terminal
234      *
235      * @throws NoSuchElementException if there is no HAL implementation for the specified SE name
236      * @throws RemoteException if there is a failure communicating with the remote
237      */
initialize(boolean retryOnFail)238     public void initialize(boolean retryOnFail) throws NoSuchElementException, RemoteException {
239         android.hardware.secure_element.V1_1.ISecureElement mSEHal11 = null;
240         synchronized (mLock) {
241             try {
242                 mSEHal = mSEHal11 = mSEHal12 =
243                         android.hardware.secure_element.V1_2.ISecureElement.getService(mName,
244                                                                                        retryOnFail);
245             } catch (Exception e) {
246                 Log.d(mTag, "SE Hal V1.2 is not supported");
247             }
248             if (mSEHal12 == null) {
249                 try {
250                     mSEHal = mSEHal11 =
251                             android.hardware.secure_element.V1_1.ISecureElement.getService(mName,
252                                     retryOnFail);
253                 } catch (Exception e) {
254                     Log.d(mTag, "SE Hal V1.1 is not supported");
255                 }
256 
257                 if (mSEHal11 == null) {
258                     mSEHal = ISecureElement.getService(mName, retryOnFail);
259                     if (mSEHal == null) {
260                         throw new NoSuchElementException("No HAL is provided for " + mName);
261                     }
262                 }
263             }
264             if (mSEHal11 != null || mSEHal12 != null) {
265                 mSEHal11.init_1_1(mHalCallback11);
266             } else {
267                 mSEHal.init(mHalCallback);
268             }
269             mSEHal.linkToDeath(mDeathRecipient, 0);
270         }
271         Log.i(mTag, mName + " was initialized");
272         SecureElementStatsLog.write(
273                 SecureElementStatsLog.SE_STATE_CHANGED,
274                 SecureElementStatsLog.SE_STATE_CHANGED__STATE__INITIALIZED,
275                 "INIT",
276                 mName);
277     }
278 
byteArrayToArrayList(byte[] array)279     private ArrayList<Byte> byteArrayToArrayList(byte[] array) {
280         ArrayList<Byte> list = new ArrayList<Byte>();
281         if (array == null) {
282             return list;
283         }
284 
285         for (Byte b : array) {
286             list.add(b);
287         }
288         return list;
289     }
290 
arrayListToByteArray(ArrayList<Byte> list)291     private byte[] arrayListToByteArray(ArrayList<Byte> list) {
292         Byte[] byteArray = list.toArray(new Byte[list.size()]);
293         int i = 0;
294         byte[] result = new byte[list.size()];
295         for (Byte b : byteArray) {
296             result[i++] = b.byteValue();
297         }
298         return result;
299     }
300 
301     /**
302      * Closes the given channel
303      */
closeChannel(Channel channel)304     public void closeChannel(Channel channel) {
305         if (channel == null) {
306             return;
307         }
308         synchronized (mLock) {
309             if (mIsConnected) {
310                 try {
311                     byte status = mSEHal.closeChannel((byte) channel.getChannelNumber());
312                     /* For Basic Channels, errors are expected.
313                      * Underlying implementations use this call as an indication when there
314                      * aren't any users actively using the channel, and the chip can go
315                      * into low power state.
316                      */
317                     if (!channel.isBasicChannel() && status != SecureElementStatus.SUCCESS) {
318                         Log.e(mTag, "Error closing channel " + channel.getChannelNumber());
319                     }
320                 } catch (RemoteException e) {
321                     Log.e(mTag, "Exception in closeChannel() " + e);
322                 }
323             }
324             mChannels.remove(channel.getChannelNumber(), channel);
325             if (mChannels.get(channel.getChannelNumber()) != null) {
326                 Log.e(mTag, "Removing channel failed");
327             }
328         }
329     }
330 
331     /**
332      * Cleans up all the channels in use.
333      */
closeChannels()334     public void closeChannels() {
335         synchronized (mLock) {
336             Collection<Channel> col = mChannels.values();
337             Channel[] channelList = col.toArray(new Channel[col.size()]);
338             for (Channel channel : channelList) {
339                 channel.close();
340             }
341         }
342     }
343 
344     /**
345      * Closes the terminal.
346      */
close()347     public void close() {
348         synchronized (mLock) {
349             if (mSEHal != null) {
350                 try {
351                     mSEHal.unlinkToDeath(mDeathRecipient);
352                 } catch (RemoteException e) {
353                     // ignore
354                 }
355             }
356         }
357     }
358 
getName()359     public String getName() {
360         return mName;
361     }
362 
363     /**
364      * Returns the ATR of the Secure Element, or null if not available.
365      */
getAtr()366     public byte[] getAtr() {
367         if (!mIsConnected) {
368             return null;
369         }
370 
371         try {
372             ArrayList<Byte> responseList = mSEHal.getAtr();
373             if (responseList.isEmpty()) {
374                 return null;
375             }
376             byte[] atr = arrayListToByteArray(responseList);
377             if (DEBUG) {
378                 Log.i(mTag, "ATR : " + ByteArrayConverter.byteArrayToHexString(atr));
379             }
380             return atr;
381         } catch (RemoteException e) {
382             Log.e(mTag, "Exception in getAtr()" + e);
383             return null;
384         }
385     }
386 
387     /**
388      * Selects the default application on the basic channel.
389      *
390      * If there is an exception selecting the default application, select
391      * is performed with the default access control aid.
392      */
selectDefaultApplication()393     public void selectDefaultApplication() {
394         try {
395             select(null);
396         } catch (NoSuchElementException e) {
397             if (getAccessControlEnforcer() != null) {
398                 try {
399                     select(mAccessControlEnforcer.getDefaultAccessControlAid());
400                 } catch (Exception ignore) {
401                 }
402             }
403         } catch (Exception ignore) {
404         }
405     }
406 
select(byte[] aid)407     private void select(byte[] aid) throws IOException {
408         int commandSize = (aid == null ? 0 : aid.length) + 5;
409         byte[] selectCommand = new byte[commandSize];
410         selectCommand[0] = 0x00;
411         selectCommand[1] = (byte) 0xA4;
412         selectCommand[2] = 0x04;
413         selectCommand[3] = 0x00;
414         if (aid != null && aid.length != 0) {
415             selectCommand[4] = (byte) aid.length;
416             System.arraycopy(aid, 0, selectCommand, 5, aid.length);
417         } else {
418             selectCommand[4] = 0x00;
419         }
420         byte[] selectResponse = transmit(selectCommand);
421         if (selectResponse.length < 2) {
422             selectResponse = null;
423             throw new NoSuchElementException("Response length is too small");
424         }
425         int sw1 = selectResponse[selectResponse.length - 2] & 0xFF;
426         int sw2 = selectResponse[selectResponse.length - 1] & 0xFF;
427         if (sw1 != 0x90 || sw2 != 0x00) {
428             selectResponse = null;
429             throw new NoSuchElementException("Status word is incorrect");
430         }
431     }
432 
433     /**
434      * Opens a Basic Channel with the given AID and P2 paramters
435      */
openBasicChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, int pid)436     public Channel openBasicChannel(SecureElementSession session, byte[] aid, byte p2,
437             ISecureElementListener listener, String packageName, int pid) throws IOException,
438             NoSuchElementException {
439         if (aid != null && aid.length == 0) {
440             aid = null;
441         } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
442             throw new IllegalArgumentException("AID out of range");
443         } else if (!mIsConnected) {
444             throw new IOException("Secure Element is not connected");
445         }
446 
447         ChannelAccess channelAccess = null;
448         if (packageName != null) {
449             Log.w(mTag, "Enable access control on basic channel for " + packageName);
450             SecureElementStatsLog.write(
451                     SecureElementStatsLog.SE_OMAPI_REPORTED,
452                     SecureElementStatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL,
453                     mName,
454                     packageName);
455             try {
456                 // For application without privilege permission or carrier privilege,
457                 // openBasicChannel with UICC terminals should be rejected.
458                 channelAccess = setUpChannelAccess(aid, packageName, pid, true);
459             } catch (MissingResourceException e) {
460                 return null;
461             }
462         }
463 
464         synchronized (mLock) {
465             if (mChannels.get(0) != null) {
466                 Log.e(mTag, "basic channel in use");
467                 return null;
468             }
469             if (aid == null && !mDefaultApplicationSelectedOnBasicChannel) {
470                 Log.e(mTag, "default application is not selected");
471                 return null;
472             }
473 
474             ArrayList<byte[]> responseList = new ArrayList<byte[]>();
475             byte[] status = new byte[1];
476 
477             try {
478                 mSEHal.openBasicChannel(byteArrayToArrayList(aid), p2,
479                         new ISecureElement.openBasicChannelCallback() {
480                             @Override
481                             public void onValues(ArrayList<Byte> responseObject, byte halStatus) {
482                                 status[0] = halStatus;
483                                 responseList.add(arrayListToByteArray(responseObject));
484                                 return;
485                             }
486                         });
487             } catch (RemoteException e) {
488                 throw new IOException(e.getMessage());
489             }
490 
491             byte[] selectResponse = responseList.get(0);
492             if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
493                 return null;
494             } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
495                 throw new UnsupportedOperationException("OpenBasicChannel() failed");
496             } else if (status[0] == SecureElementStatus.IOERROR) {
497                 throw new IOException("OpenBasicChannel() failed");
498             } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
499                 throw new NoSuchElementException("OpenBasicChannel() failed");
500             }
501 
502             Channel basicChannel = new Channel(session, this, 0, selectResponse, aid,
503                     listener);
504             basicChannel.setChannelAccess(channelAccess);
505 
506             if (aid != null) {
507                 mDefaultApplicationSelectedOnBasicChannel = false;
508             }
509             mChannels.put(0, basicChannel);
510             return basicChannel;
511         }
512     }
513 
514     /**
515      * Opens a logical Channel without Channel Access initialization.
516      */
openLogicalChannelWithoutChannelAccess(byte[] aid)517     public Channel openLogicalChannelWithoutChannelAccess(byte[] aid) throws IOException,
518             NoSuchElementException {
519         return openLogicalChannel(null, aid, (byte) 0x00, null, null, 0);
520     }
521 
522     /**
523      * Opens a logical Channel with AID.
524      */
openLogicalChannel(SecureElementSession session, byte[] aid, byte p2, ISecureElementListener listener, String packageName, int pid)525     public Channel openLogicalChannel(SecureElementSession session, byte[] aid, byte p2,
526             ISecureElementListener listener, String packageName, int pid) throws IOException,
527             NoSuchElementException {
528         if (aid != null && aid.length == 0) {
529             aid = null;
530         } else if (aid != null && (aid.length < 5 || aid.length > 16)) {
531             throw new IllegalArgumentException("AID out of range");
532         } else if (!mIsConnected) {
533             throw new IOException("Secure Element is not connected");
534         }
535 
536         ChannelAccess channelAccess = null;
537         if (packageName != null) {
538             Log.w(mTag, "Enable access control on logical channel for " + packageName);
539             SecureElementStatsLog.write(
540                     SecureElementStatsLog.SE_OMAPI_REPORTED,
541                     SecureElementStatsLog.SE_OMAPI_REPORTED__OPERATION__OPEN_CHANNEL,
542                     mName,
543                     packageName);
544             try {
545                 channelAccess = setUpChannelAccess(aid, packageName, pid, false);
546             } catch (MissingResourceException | UnsupportedOperationException e) {
547                 return null;
548             }
549         }
550 
551         synchronized (mLock) {
552             LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
553             byte[] status = new byte[1];
554 
555             try {
556                 mSEHal.openLogicalChannel(byteArrayToArrayList(aid), p2,
557                         new ISecureElement.openLogicalChannelCallback() {
558                             @Override
559                             public void onValues(LogicalChannelResponse response, byte halStatus) {
560                                 status[0] = halStatus;
561                                 responseArray[0] = response;
562                                 return;
563                             }
564                         });
565             } catch (RemoteException e) {
566                 throw new IOException(e.getMessage());
567             }
568 
569             if (status[0] == SecureElementStatus.CHANNEL_NOT_AVAILABLE) {
570                 return null;
571             } else if (status[0] == SecureElementStatus.UNSUPPORTED_OPERATION) {
572                 throw new UnsupportedOperationException("OpenLogicalChannel() failed");
573             } else if (status[0] == SecureElementStatus.IOERROR) {
574                 throw new IOException("OpenLogicalChannel() failed");
575             } else if (status[0] == SecureElementStatus.NO_SUCH_ELEMENT_ERROR) {
576                 throw new NoSuchElementException("OpenLogicalChannel() failed");
577             }
578             if (responseArray[0].channelNumber <= 0 || status[0] != SecureElementStatus.SUCCESS) {
579                 return null;
580             }
581             int channelNumber = responseArray[0].channelNumber;
582             byte[] selectResponse = arrayListToByteArray(responseArray[0].selectResponse);
583             Channel logicalChannel = new Channel(session, this, channelNumber,
584                     selectResponse, aid, listener);
585             logicalChannel.setChannelAccess(channelAccess);
586 
587             mChannels.put(channelNumber, logicalChannel);
588             return logicalChannel;
589         }
590     }
591 
592     /**
593      * Returns true if the given AID can be selected on the Terminal
594      */
isAidSelectable(byte[] aid)595     public boolean isAidSelectable(byte[] aid) {
596         if (aid == null) {
597             throw new NullPointerException("aid must not be null");
598         } else if (!mIsConnected) {
599             Log.e(mTag, "Secure Element is not connected");
600             return false;
601         }
602 
603         synchronized (mLock) {
604             LogicalChannelResponse[] responseArray = new LogicalChannelResponse[1];
605             byte[] status = new byte[1];
606             try {
607                 mSEHal.openLogicalChannel(byteArrayToArrayList(aid), (byte) 0x00,
608                         new ISecureElement.openLogicalChannelCallback() {
609                             @Override
610                             public void onValues(LogicalChannelResponse response, byte halStatus) {
611                                 status[0] = halStatus;
612                                 responseArray[0] = response;
613                                 return;
614                             }
615                         });
616                 if (status[0] == SecureElementStatus.SUCCESS) {
617                     mSEHal.closeChannel(responseArray[0].channelNumber);
618                     return true;
619                 }
620                 return false;
621             } catch (RemoteException e) {
622                 Log.e(mTag, "Error in isAidSelectable() returning false" + e);
623                 return false;
624             }
625         }
626     }
627 
628     /**
629      * Transmits the specified command and returns the response.
630      *
631      * @param cmd the command APDU to be transmitted.
632      * @return the response received.
633      */
transmit(byte[] cmd)634     public byte[] transmit(byte[] cmd) throws IOException {
635         if (!mIsConnected) {
636             Log.e(mTag, "Secure Element is not connected");
637             throw new IOException("Secure Element is not connected");
638         }
639 
640         byte[] rsp = transmitInternal(cmd);
641         int sw1 = rsp[rsp.length - 2] & 0xFF;
642         int sw2 = rsp[rsp.length - 1] & 0xFF;
643 
644         if (sw1 == 0x6C) {
645             cmd[cmd.length - 1] = rsp[rsp.length - 1];
646             rsp = transmit(cmd);
647         } else if (sw1 == 0x61) {
648             do {
649                 byte[] getResponseCmd = new byte[]{
650                         cmd[0], (byte) 0xC0, 0x00, 0x00, (byte) sw2
651                 };
652                 byte[] tmp = transmitInternal(getResponseCmd);
653                 byte[] aux = rsp;
654                 rsp = new byte[aux.length + tmp.length - 2];
655                 System.arraycopy(aux, 0, rsp, 0, aux.length - 2);
656                 System.arraycopy(tmp, 0, rsp, aux.length - 2, tmp.length);
657                 sw1 = rsp[rsp.length - 2] & 0xFF;
658                 sw2 = rsp[rsp.length - 1] & 0xFF;
659             } while (sw1 == 0x61);
660         }
661         return rsp;
662     }
663 
transmitInternal(byte[] cmd)664     private byte[] transmitInternal(byte[] cmd) throws IOException {
665         ArrayList<Byte> response;
666         try {
667             response = mSEHal.transmit(byteArrayToArrayList(cmd));
668         } catch (RemoteException e) {
669             throw new IOException(e.getMessage());
670         }
671         if (response.isEmpty()) {
672             throw new IOException("Error in transmit()");
673         }
674         byte[] rsp = arrayListToByteArray(response);
675         if (DEBUG) {
676             Log.i(mTag, "Sent : " + ByteArrayConverter.byteArrayToHexString(cmd));
677             Log.i(mTag, "Received : " + ByteArrayConverter.byteArrayToHexString(rsp));
678         }
679         return rsp;
680     }
681 
682     /**
683      * Checks if the application is authorized to receive the transaction event.
684      */
isNfcEventAllowed(PackageManager packageManager, byte[] aid, String[] packageNames)685     public boolean[] isNfcEventAllowed(PackageManager packageManager, byte[] aid,
686             String[] packageNames) {
687         if (!mIsConnected) {
688             // Return if not connected
689             return null;
690         }
691         // Return if the access control enforcer failed in previous attempt or no rule was found.
692         if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) {
693             Log.i(mTag, "isNfcEventAllowed: No access rules for checking.");
694             return null;
695         }
696         mAccessControlEnforcer.setPackageManager(packageManager);
697 
698         synchronized (mLock) {
699             try {
700                 return mAccessControlEnforcer.isNfcEventAllowed(aid, packageNames);
701             } catch (Exception e) {
702                 Log.i(mTag, "isNfcEventAllowed Exception: " + e.getMessage());
703                 return null;
704             }
705         }
706     }
707 
708     /**
709      * Returns true if the Secure Element is present
710      */
isSecureElementPresent()711     public boolean isSecureElementPresent() {
712         try {
713             return mSEHal.isCardPresent();
714         } catch (RemoteException e) {
715             Log.e(mTag, "Error in isSecureElementPresent() " + e);
716             return false;
717         }
718     }
719 
720     /**
721      * Reset the Secure Element. Return true if success, false otherwise.
722      */
reset()723     public boolean reset() {
724         if (mSEHal12 == null) {
725             return false;
726         }
727         mContext.enforceCallingOrSelfPermission(
728                 android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION,
729                 "Need SECURE_ELEMENT_PRIVILEGED_OPERATION permission");
730 
731         try {
732             byte status = mSEHal12.reset();
733             // Successfully trigger reset. HAL service should send onStateChange
734             // after secure element reset and initialization process complete
735             if (status == SecureElementStatus.SUCCESS) {
736                 return true;
737             }
738             Log.e(mTag, "Error reseting terminal " + mName);
739         } catch (RemoteException e) {
740             Log.e(mTag, "Exception in reset()" + e);
741         }
742         return false;
743     }
744 
745     /**
746      * Initialize the Access Control and set up the channel access.
747      */
setUpChannelAccess(byte[] aid, String packageName, int pid, boolean isBasicChannel)748     private ChannelAccess setUpChannelAccess(byte[] aid, String packageName, int pid,
749             boolean isBasicChannel) throws IOException, MissingResourceException {
750         boolean checkRefreshTag = true;
751         if (isPrivilegedApplication(packageName)) {
752             return ChannelAccess.getPrivilegeAccess(packageName, pid);
753         }
754         // Attempt to initialize the access control enforcer if it failed
755         // due to a kind of temporary failure or no rule was found in the previous attempt.
756         // For privilege access, do not attempt to initialize the access control enforcer
757         // if no rule was found in the previous attempt.
758         if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) {
759             initializeAccessControl();
760             // Just finished to initialize the access control enforcer.
761             // It is too much to check the refresh tag in this case.
762             checkRefreshTag = false;
763         }
764         mAccessControlEnforcer.setPackageManager(mContext.getPackageManager());
765 
766         // Check carrier privilege when AID is not ISD-R
767         if (getName().startsWith(SecureElementService.UICC_TERMINAL)
768                 && !Arrays.equals(aid, ISD_R_AID)) {
769             try {
770                 PackageManager pm = mContext.getPackageManager();
771                 if (pm != null) {
772                     PackageInfo pkgInfo =
773                             pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
774                     // Do not check the refresh tag for carrier privilege
775                     if (mAccessControlEnforcer.checkCarrierPrivilege(pkgInfo, false)) {
776                         Log.i(mTag, "setUp PrivilegeAccess for CarrierPrivilegeApplication. ");
777                         return ChannelAccess.getCarrierPrivilegeAccess(packageName, pid);
778                     }
779                 }
780             } catch (NameNotFoundException ne) {
781                 Log.e(mTag, "checkCarrierPrivilege(): packageInfo is not found. ");
782             } catch (Exception e) {
783                 Log.e(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage());
784             }
785             if (isBasicChannel) {
786                 throw new MissingResourceException("openBasicChannel is not allowed.", "", "");
787             } else if (aid == null) {
788                 // openLogicalChannel with null aid is only allowed for privilege applications
789                 throw new UnsupportedOperationException(
790                         "null aid is not accepted in UICC terminal.");
791             }
792         }
793 
794         synchronized (mLock) {
795             try {
796                 ChannelAccess channelAccess =
797                         mAccessControlEnforcer.setUpChannelAccess(aid, packageName,
798                                 checkRefreshTag);
799                 channelAccess.setCallingPid(pid);
800                 return channelAccess;
801             } catch (IOException | MissingResourceException e) {
802                 throw e;
803             } catch (Exception e) {
804                 throw new SecurityException("Exception in setUpChannelAccess()" + e);
805             }
806         }
807     }
808 
809     /**
810      * Initializes the Access Control for this Terminal
811      */
initializeAccessControl()812     private synchronized void initializeAccessControl() throws IOException,
813             MissingResourceException {
814         synchronized (mLock) {
815             if (mAccessControlEnforcer == null) {
816                 mAccessControlEnforcer = new AccessControlEnforcer(this);
817             }
818             try {
819                 mAccessControlEnforcer.initialize();
820             } catch (IOException | MissingResourceException e) {
821                 // Retrieving access rules failed because of an IO error happened between
822                 // the terminal and the secure element or the lack of a logical channel available.
823                 // It might be a temporary failure, so the terminal shall attempt to cache
824                 // the access rules again later.
825                 mAccessControlEnforcer = null;
826                 throw e;
827             }
828         }
829     }
830 
831     /**
832      * Checks if Secure Element Privilege permission exists for the given package
833      */
isPrivilegedApplication(String packageName)834     private boolean isPrivilegedApplication(String packageName) {
835         PackageManager pm = mContext.getPackageManager();
836         if (pm != null) {
837             return (pm.checkPermission(SECURE_ELEMENT_PRIVILEGED_OPERATION_PERMISSION,
838                     packageName) == PackageManager.PERMISSION_GRANTED);
839         }
840         return false;
841     }
842 
getAccessControlEnforcer()843     public AccessControlEnforcer getAccessControlEnforcer() {
844         return mAccessControlEnforcer;
845     }
846 
getContext()847     public Context getContext() {
848         return mContext;
849     }
850 
851     /**
852      * Checks if Carrier Privilege exists for the given package
853      */
checkCarrierPrivilegeRules(PackageInfo pInfo)854     public boolean checkCarrierPrivilegeRules(PackageInfo pInfo) {
855         boolean checkRefreshTag = true;
856         if (mAccessControlEnforcer == null || mAccessControlEnforcer.isNoRuleFound()) {
857             try {
858                 initializeAccessControl();
859             } catch (IOException e) {
860                 return false;
861             }
862             checkRefreshTag = false;
863         }
864         mAccessControlEnforcer.setPackageManager(mContext.getPackageManager());
865 
866         synchronized (mLock) {
867             try {
868                 return mAccessControlEnforcer.checkCarrierPrivilege(pInfo, checkRefreshTag);
869             } catch (Exception e) {
870                 Log.i(mTag, "checkCarrierPrivilege() Exception: " + e.getMessage());
871                 return false;
872             }
873         }
874     }
875 
876     /** Dump data for debug purpose . */
dump(PrintWriter writer)877     public void dump(PrintWriter writer) {
878         writer.println("SECURE ELEMENT SERVICE TERMINAL: " + mName);
879         writer.println();
880 
881         writer.println("mIsConnected:" + mIsConnected);
882         writer.println();
883 
884         /* Dump the list of currunlty openned channels */
885         writer.println("List of open channels:");
886 
887         for (Channel channel : mChannels.values()) {
888             writer.println("channel " + channel.getChannelNumber() + ": ");
889             writer.println("package: " + channel.getChannelAccess().getPackageName());
890             writer.println("pid: " + channel.getChannelAccess().getCallingPid());
891             writer.println("aid selected: " + channel.hasSelectedAid());
892             writer.println("basic channel: " + channel.isBasicChannel());
893             writer.println();
894         }
895         writer.println();
896 
897         /* Dump ACE data */
898         if (mAccessControlEnforcer != null) {
899             mAccessControlEnforcer.dump(writer);
900         }
901     }
902 
903     // Implementation of the SecureElement Reader interface according to OMAPI.
904     final class SecureElementReader extends ISecureElementReader.Stub {
905 
906         private final SecureElementService mService;
907         private final ArrayList<SecureElementSession> mSessions =
908                 new ArrayList<SecureElementSession>();
909 
SecureElementReader(SecureElementService service)910         SecureElementReader(SecureElementService service) {
911             mService = service;
912         }
913 
getAtr()914         public byte[] getAtr() {
915             return Terminal.this.getAtr();
916         }
917 
918         @Override
isSecureElementPresent()919         public boolean isSecureElementPresent() throws RemoteException {
920             return Terminal.this.isSecureElementPresent();
921         }
922 
923         @Override
closeSessions()924         public void closeSessions() {
925             synchronized (mLock) {
926                 while (mSessions.size() > 0) {
927                     try {
928                         mSessions.get(0).close();
929                     } catch (Exception ignore) {
930                     }
931                 }
932                 mSessions.clear();
933             }
934         }
935 
removeSession(SecureElementSession session)936         public void removeSession(SecureElementSession session) {
937             if (session == null) {
938                 throw new NullPointerException("session is null");
939             }
940 
941             synchronized (mLock) {
942                 mSessions.remove(session);
943                 if (mSessions.size() == 0) {
944                     mDefaultApplicationSelectedOnBasicChannel = true;
945                 }
946             }
947         }
948 
949         @Override
openSession()950         public ISecureElementSession openSession() throws RemoteException {
951             if (!isSecureElementPresent()) {
952                 throw new ServiceSpecificException(SEService.IO_ERROR,
953                         "Secure Element is not present.");
954             }
955 
956             synchronized (mLock) {
957                 SecureElementSession session = mService.new SecureElementSession(this);
958                 mSessions.add(session);
959                 return session;
960             }
961         }
962 
getTerminal()963         Terminal getTerminal() {
964             return Terminal.this;
965         }
966 
967         @Override
reset()968         public boolean reset() {
969             return Terminal.this.reset();
970         }
971     }
972 }
973