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