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