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