• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 /* Contributed by Orange */
18 
19 package android.omapi.accesscontrol1.cts;
20 
21 import static org.hamcrest.CoreMatchers.is;
22 import static org.junit.Assert.*;
23 import static org.junit.Assume.assumeTrue;
24 
25 import android.content.pm.PackageManager;
26 import android.os.Build;
27 import android.se.omapi.Channel;
28 import android.se.omapi.Reader;
29 import android.se.omapi.SEService;
30 import android.se.omapi.SEService.OnConnectedListener;
31 import android.se.omapi.Session;
32 
33 import androidx.test.InstrumentationRegistry;
34 
35 import com.android.compatibility.common.util.PropertyUtil;
36 
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Test;
40 
41 import java.util.Timer;
42 import java.util.TimerTask;
43 import java.util.concurrent.Executor;
44 import java.util.concurrent.TimeoutException;
45 
46 public class AccessControlTest {
47     private final static String UICC_READER_PREFIX = "SIM";
48     private final static String ESE_READER_PREFIX = "eSE";
49     private final static String SD_READER_PREFIX = "SD";
50 
51     private final static byte[] AID_40 = new byte[] { (byte) 0xA0, 0x00, 0x00,
52         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
53         0x53, 0x40 };
54     private final static byte[] AID_41 = new byte[] { (byte) 0xA0, 0x00, 0x00,
55         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
56         0x53, 0x41 };
57     private final static byte[] AID_42 = new byte[] { (byte) 0xA0, 0x00, 0x00,
58         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
59         0x53, 0x42 };
60     private final static byte[] AID_43 = new byte[] { (byte) 0xA0, 0x00, 0x00,
61         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
62         0x53, 0x43 };
63     private final static byte[] AID_44 = new byte[] { (byte) 0xA0, 0x00, 0x00,
64         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
65         0x53, 0x44 };
66     private final static byte[] AID_45 = new byte[] { (byte) 0xA0, 0x00, 0x00,
67         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
68         0x53, 0x45 };
69     private final static byte[] AID_46 = new byte[] { (byte) 0xA0, 0x00, 0x00,
70         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
71         0x53, 0x46 };
72     private final static byte[] AID_47 = new byte[] { (byte) 0xA0, 0x00, 0x00,
73         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
74         0x53, 0x47 };
75     private final static byte[] AID_48 = new byte[] { (byte) 0xA0, 0x00, 0x00,
76         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
77         0x53, 0x48 };
78     private final static byte[] AID_49 = new byte[] { (byte) 0xA0, 0x00, 0x00,
79         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
80         0x53, 0x49 };
81     private final static byte[] AID_4A = new byte[] { (byte) 0xA0, 0x00, 0x00,
82         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
83         0x53, (byte) 0x4A };
84     private final static byte[] AID_4B = new byte[] { (byte) 0xA0, 0x00, 0x00,
85         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
86         0x53, (byte) 0x4B };
87     private final static byte[] AID_4C = new byte[] { (byte) 0xA0, 0x00, 0x00,
88         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
89         0x53, (byte) 0x4C };
90     private final static byte[] AID_4D = new byte[] { (byte) 0xA0, 0x00, 0x00,
91         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
92         0x53, (byte) 0x4D };
93     private final static byte[] AID_4E = new byte[] { (byte) 0xA0, 0x00, 0x00,
94         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
95         0x53, (byte) 0x4E };
96     private final static byte[] AID_4F = new byte[] { (byte) 0xA0, 0x00, 0x00,
97         0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
98         0x53, (byte) 0x4F };
99 
100     private final static byte[][] AUTHORIZED_AID = new byte[][] { AID_40,
101         AID_41, AID_42, AID_44, AID_45, AID_47, AID_48, AID_49, AID_4A,
102         AID_4B, AID_4C, AID_4D, AID_4E, AID_4F };
103     private final static byte[][] UNAUTHORIZED_AID = new byte[][] { AID_43,
104         AID_46 };
105 
106     /* Authorized APDU for AID_40 */
107     private final static byte[][] AUTHORIZED_APDU_AID_40 = new byte[][] {
108         { 0x00, 0x06, 0x00, 0x00 }, { (byte) 0xA0, 0x06, 0x00, 0x00 },};
109     /* Unauthorized APDU for AID_40 */
110     private final static byte[][] UNAUTHORIZED_APDU_AID_40 = new byte[][] {
111         { 0x00, 0x08, 0x00, 0x00, 0x00 },
112         { (byte) 0x80, 0x06, 0x00, 0x00 },
113         { (byte) 0xA0, 0x08, 0x00, 0x00, 0x00 },
114         { (byte) 0x94, 0x06, 0x00, 0x00, 0x00 }, };
115 
116     /* Authorized APDU for AID_41 */
117     private final static byte[][] AUTHORIZED_APDU_AID_41 = new byte[][] {
118         { (byte) 0x94, 0x06, 0x00, 0x00 },
119         { (byte) 0x94, 0x08, 0x00, 0x00, 0x00 },
120         { (byte) 0x94, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
121         { (byte) 0x94, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA } };
122     /* Unauthorized APDU for AID_41 */
123     private final static byte[][] UNAUTHORIZED_APDU_AID_41 = new byte[][] {
124         { 0x00, 0x06, 0x00, 0x00 }, { (byte) 0x80, 0x06, 0x00, 0x00 },
125         { (byte) 0xA0, 0x06, 0x00, 0x00 },
126         { 0x00, 0x08, 0x00, 0x00, 0x00 },
127         { (byte) 0x00, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
128         { (byte) 0x80, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
129         { (byte) 0xA0, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
130         { (byte) 0x80, 0x08, 0x00, 0x00, 0x00 },
131         { (byte) 0xA0, 0x08, 0x00, 0x00, 0x00 },
132         { 0x00, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
133         { (byte) 0x80, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
134         { (byte) 0xA0, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
135     };
136 
137     private final long SERVICE_CONNECTION_TIME_OUT = 3000;
138     private SEService seService;
139     private Object serviceMutex = new Object();
140     private Timer connectionTimer;
141     private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask();
142     private boolean connected = false;
143 
144     private final OnConnectedListener mListener = new OnConnectedListener() {
145         public void onConnected() {
146             synchronized (serviceMutex) {
147                 connected = true;
148                 serviceMutex.notify();
149             }
150         }
151     };
152 
153     class SynchronousExecutor implements Executor {
execute(Runnable r)154         public void execute(Runnable r) {
155             r.run();
156         }
157     }
158 
supportsHardware()159     private boolean supportsHardware() {
160         final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
161         boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
162         return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
163     }
164 
165     @Before
setUp()166     public void setUp() throws Exception {
167         assumeTrue(PropertyUtil.getFirstApiLevel() > Build.VERSION_CODES.O_MR1);
168         assumeTrue(supportsHardware());
169         seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
170         connectionTimer = new Timer();
171         connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
172     }
173 
174     @After
tearDown()175     public void tearDown() throws Exception {
176         if (seService != null && seService.isConnected()) {
177             seService.shutdown();
178             connected = false;
179         }
180     }
181 
waitForConnection()182     private void waitForConnection() throws TimeoutException {
183         synchronized (serviceMutex) {
184             if (!connected) {
185                 try {
186                     serviceMutex.wait();
187                  } catch (InterruptedException e) {
188                     e.printStackTrace();
189                  }
190             }
191             if (!connected) {
192                 throw new TimeoutException(
193                     "Service could not be connected after "
194                     + SERVICE_CONNECTION_TIME_OUT + " ms");
195             }
196             if (connectionTimer != null) {
197                 connectionTimer.cancel();
198             }
199         }
200     }
201 
202     @Test
testAuthorizedAID()203     public void testAuthorizedAID() {
204         for (byte[] aid : AUTHORIZED_AID) {
205             testSelectableAid(aid);
206         }
207     }
208 
209     @Test
testUnauthorizedAID()210     public void testUnauthorizedAID() {
211         for (byte[] aid : UNAUTHORIZED_AID) {
212             testUnauthorisedAid(aid);
213         }
214     }
215 
216     @Test
testAuthorizedAPDUAID40()217     public void testAuthorizedAPDUAID40() {
218         for (byte[] apdu : AUTHORIZED_APDU_AID_40) {
219             testTransmitAPDU(AID_40, apdu);
220         }
221     }
222 
223     @Test
testUnauthorisedAPDUAID40()224     public void testUnauthorisedAPDUAID40() {
225         for (byte[] apdu : UNAUTHORIZED_APDU_AID_40) {
226             testUnauthorisedAPDU(AID_40, apdu);
227         }
228     }
229 
230     @Test
testAuthorizedAPDUAID41()231     public void testAuthorizedAPDUAID41() {
232         for (byte[] apdu : AUTHORIZED_APDU_AID_41) {
233             testTransmitAPDU(AID_41, apdu);
234         }
235     }
236 
237     @Test
testUnauthorisedAPDUAID41()238     public void testUnauthorisedAPDUAID41() {
239         for (byte[] apdu : UNAUTHORIZED_APDU_AID_41) {
240             testUnauthorisedAPDU(AID_41, apdu);
241         }
242     }
243 
testSelectableAid(byte[] aid)244     private void testSelectableAid(byte[] aid) {
245         try {
246             waitForConnection();
247             Reader[] readers = seService.getReaders();
248             for (Reader reader : readers) {
249                 Session session = null;
250                 Channel channel = null;
251                 try {
252                     assertTrue(reader.isSecureElementPresent());
253                     session = reader.openSession();
254                     assertNotNull("Null Session", session);
255                     channel = session.openLogicalChannel(aid, (byte) 0x00);
256                     assertNotNull("Null Channel", channel);
257                     byte[] selectResponse = channel.getSelectResponse();
258                     assertNotNull("Null Select Response", selectResponse);
259                     assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
260                     assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
261                     assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
262                 } finally {
263                     if (channel != null) channel.close();
264                     if (session != null) session.close();
265                 }
266             }
267         } catch (Exception e) {
268             fail("Unexpected Exception " + e);
269         }
270     }
271 
testUnauthorisedAid(byte[] aid)272     private void testUnauthorisedAid(byte[] aid) {
273         try {
274             waitForConnection();
275             Reader[] readers = seService.getReaders();
276             for (Reader reader : readers) {
277                 Session session = null;
278                 Channel channel = null;
279                 try {
280                     assertTrue(reader.isSecureElementPresent());
281                     session = reader.openSession();
282                     assertNotNull("Null Session", session);
283                     try {
284                         channel = session.openLogicalChannel(aid, (byte) 0x00);
285                         fail("SecurityException Expected");
286                     } catch (SecurityException e) {
287                         // Expected
288                     }
289                 } finally {
290                     if (channel != null) channel.close();
291                     if (session != null) session.close();
292                 }
293             }
294         } catch (Exception e) {
295             fail("Unexpected Exception " + e);
296         }
297     }
298 
testTransmitAPDU(byte[] aid, byte[] apdu)299     private void testTransmitAPDU(byte[] aid, byte[] apdu) {
300         try {
301             waitForConnection();
302             Reader[] readers = seService.getReaders();
303             for (Reader reader : readers) {
304                 Session session = null;
305                 Channel channel = null;
306                 try {
307                     assertTrue(reader.isSecureElementPresent());
308                     session = reader.openSession();
309                     assertNotNull("Null Session", session);
310                     channel = session.openLogicalChannel(aid, (byte) 0x00);
311                     assertNotNull("Null Channel", channel);
312                     byte[] selectResponse = channel.getSelectResponse();
313                     assertNotNull("Null Select Response", selectResponse);
314                     assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
315                     assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
316                     assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
317                     byte[] apduResponse = channel.transmit(apdu);
318                     assertNotNull("Null Channel", apduResponse);
319                 } finally {
320                     if (channel != null) channel.close();
321                     if (session != null) session.close();
322                 }
323             }
324         } catch (Exception e) {
325             fail("Unexpected Exception " + e);
326         }
327     }
328 
testUnauthorisedAPDU(byte[] aid, byte[] apdu)329     private void testUnauthorisedAPDU(byte[] aid, byte[] apdu) {
330         try {
331             waitForConnection();
332             Reader[] readers = seService.getReaders();
333             for (Reader reader : readers) {
334                 Session session = null;
335                 Channel channel = null;
336                 try {
337                     assertTrue(reader.isSecureElementPresent());
338                     session = reader.openSession();
339                     assertNotNull("Null Session", session);
340                     channel = session.openLogicalChannel(aid, (byte) 0x00);
341                     assertNotNull("Null Channel", channel);
342                     byte[] selectResponse = channel.getSelectResponse();
343                     assertNotNull("Null Select Response", selectResponse);
344                     assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
345                     assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
346                     assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
347                     try {
348                         channel.transmit(apdu);
349                         fail("Security Exception is expected");
350                     } catch (SecurityException e) {
351                         // Expected
352                     }
353                 } finally {
354                     if (channel != null) channel.close();
355                     if (session != null) session.close();
356                 }
357             }
358         } catch (Exception e) {
359             fail("Unexpected Exception " + e);
360         }
361     }
362 
363     /**
364      * Verifies TLV data
365      *
366      * @param tlv
367      * @return true if the data is tlv formatted, false otherwise
368      */
verifyBerTlvData(byte[] tlv)369     private static boolean verifyBerTlvData(byte[] tlv) {
370         if (tlv == null || tlv.length == 0) {
371             throw new RuntimeException("Invalid tlv, null");
372         }
373 
374         int i = 0;
375         byte[] key = new byte[2];
376         key[0] = tlv[i];
377         if ((key[0] & 0x1F) == 0x1F) {
378             // extra byte for TAG field
379             key[1] = tlv[i = i + 1];
380         }
381 
382         int len = tlv[i = i + 1] & 0xFF;
383         if (len > 127) {
384             // more than 1 byte for length
385             int bytesLength = len - 128;
386             len = 0;
387             for (int j = bytesLength - 1; j >= 0; j--) {
388               len += (tlv[i = i + 1] & 0xFF) * Math.pow(10, j);
389             }
390         }
391         return tlv.length == (i + len + 3);
392     }
393 
394     class ServiceConnectionTimerTask extends TimerTask {
395         @Override
run()396         public void run() {
397             synchronized (serviceMutex) {
398                 serviceMutex.notifyAll();
399             }
400         }
401     }
402 }
403