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