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.accesscontrol1.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_42, AID_44, AID_45, AID_47, AID_48, AID_49, AID_4A,
    100         AID_4B, AID_4C, AID_4D, AID_4E, AID_4F };
    101     private final static byte[][] UNAUTHORIZED_AID = new byte[][] { AID_43,
    102         AID_46 };
    103 
    104     /* Authorized APDU for AID_40 */
    105     private final static byte[][] AUTHORIZED_APDU_AID_40 = new byte[][] {
    106         { 0x00, 0x06, 0x00, 0x00 }, { (byte) 0xA0, 0x06, 0x00, 0x00 },};
    107     /* Unauthorized APDU for AID_40 */
    108     private final static byte[][] UNAUTHORIZED_APDU_AID_40 = new byte[][] {
    109         { 0x00, 0x08, 0x00, 0x00, 0x00 },
    110         { (byte) 0x80, 0x06, 0x00, 0x00 },
    111         { (byte) 0xA0, 0x08, 0x00, 0x00, 0x00 },
    112         { (byte) 0x94, 0x06, 0x00, 0x00, 0x00 }, };
    113 
    114     /* Authorized APDU for AID_41 */
    115     private final static byte[][] AUTHORIZED_APDU_AID_41 = new byte[][] {
    116         { (byte) 0x94, 0x06, 0x00, 0x00 },
    117         { (byte) 0x94, 0x08, 0x00, 0x00, 0x00 },
    118         { (byte) 0x94, (byte) 0xC0, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
    119         { (byte) 0x94, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA } };
    120     /* Unauthorized APDU for AID_41 */
    121     private final static byte[][] UNAUTHORIZED_APDU_AID_41 = new byte[][] {
    122         { 0x00, 0x06, 0x00, 0x00 }, { (byte) 0x80, 0x06, 0x00, 0x00 },
    123         { (byte) 0xA0, 0x06, 0x00, 0x00 },
    124         { 0x00, 0x08, 0x00, 0x00, 0x00 },
    125         { (byte) 0x00, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
    126         { (byte) 0x80, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
    127         { (byte) 0xA0, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
    128         { (byte) 0x80, 0x08, 0x00, 0x00, 0x00 },
    129         { (byte) 0xA0, 0x08, 0x00, 0x00, 0x00 },
    130         { 0x00, (byte) 0xC0, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
    131         { (byte) 0x80, (byte) 0xC0, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
    132         { (byte) 0xA0, (byte) 0xC0, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
    133     };
    134 
    135     private final long SERVICE_CONNECTION_TIME_OUT = 3000;
    136     private SEService seService;
    137     private Object serviceMutex = new Object();
    138     private Timer connectionTimer;
    139     private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask();
    140     private boolean connected = false;
    141 
    142     private final OnConnectedListener mListener = new OnConnectedListener() {
    143         public void onConnected() {
    144             synchronized (serviceMutex) {
    145                 connected = true;
    146                 serviceMutex.notify();
    147             }
    148         }
    149     };
    150 
    151     class SynchronousExecutor implements Executor {
    152         public void execute(Runnable r) {
    153             r.run();
    154         }
    155     }
    156 
    157     private boolean supportsHardware() {
    158         final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
    159         boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
    160         return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
    161     }
    162 
    163     @Before
    164     public void setUp() throws Exception {
    165         assumeTrue(supportsHardware());
    166         seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
    167         connectionTimer = new Timer();
    168         connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
    169     }
    170 
    171     @After
    172     public void tearDown() throws Exception {
    173         if (seService != null && seService.isConnected()) {
    174             seService.shutdown();
    175             connected = false;
    176         }
    177     }
    178 
    179     private void waitForConnection() throws TimeoutException {
    180         synchronized (serviceMutex) {
    181             if (!connected) {
    182                 try {
    183                     serviceMutex.wait();
    184                  } catch (InterruptedException e) {
    185                     e.printStackTrace();
    186                  }
    187             }
    188             if (!connected) {
    189                 throw new TimeoutException(
    190                     "Service could not be connected after "
    191                     + SERVICE_CONNECTION_TIME_OUT + " ms");
    192             }
    193             if (connectionTimer != null) {
    194                 connectionTimer.cancel();
    195             }
    196         }
    197     }
    198 
    199     @Test
    200     public void testAuthorizedAID() {
    201         for (byte[] aid : AUTHORIZED_AID) {
    202             testSelectableAid(aid);
    203         }
    204     }
    205 
    206     @Test
    207     public void testUnauthorizedAID() {
    208         for (byte[] aid : UNAUTHORIZED_AID) {
    209             testUnauthorisedAid(aid);
    210         }
    211     }
    212 
    213     @Test
    214     public void testAuthorizedAPDUAID40() {
    215         for (byte[] apdu : AUTHORIZED_APDU_AID_40) {
    216             testTransmitAPDU(AID_40, apdu);
    217         }
    218     }
    219 
    220     @Test
    221     public void testUnauthorisedAPDUAID40() {
    222         for (byte[] apdu : UNAUTHORIZED_APDU_AID_40) {
    223             testUnauthorisedAPDU(AID_40, apdu);
    224         }
    225     }
    226 
    227     @Test
    228     public void testAuthorizedAPDUAID41() {
    229         for (byte[] apdu : AUTHORIZED_APDU_AID_41) {
    230             testTransmitAPDU(AID_41, apdu);
    231         }
    232     }
    233 
    234     @Test
    235     public void testUnauthorisedAPDUAID41() {
    236         for (byte[] apdu : UNAUTHORIZED_APDU_AID_41) {
    237             testUnauthorisedAPDU(AID_41, apdu);
    238         }
    239     }
    240 
    241     private void testSelectableAid(byte[] aid) {
    242         Session session = null;
    243         Channel channel = null;
    244         try {
    245             waitForConnection();
    246             Reader[] readers = seService.getReaders();
    247             for (Reader reader : readers) {
    248                 assertTrue(reader.isSecureElementPresent());
    249                 session = reader.openSession();
    250                 assertNotNull("Null Session", session);
    251                 channel = session.openLogicalChannel(aid, (byte) 0x00);
    252                 assertNotNull("Null Channel", channel);
    253                 byte[] selectResponse = channel.getSelectResponse();
    254                 assertNotNull("Null Select Response", selectResponse);
    255                 assertEquals(selectResponse[selectResponse.length - 1] & 0xFF, 0x00);
    256                 assertEquals(selectResponse[selectResponse.length - 2] & 0xFF, 0x90);
    257                 assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
    258             }
    259         } catch (Exception e) {
    260             fail("Unexpected Exception " + e);
    261         } finally{
    262             if (channel != null)
    263                 channel.close();
    264             if (session != null)
    265                 session.close();
    266         }
    267     }
    268 
    269     private void testUnauthorisedAid(byte[] aid) {
    270         Session session = null;
    271         Channel channel = null;
    272         try {
    273             waitForConnection();
    274             Reader[] readers = seService.getReaders();
    275 
    276             for (Reader reader : readers) {
    277                 assertTrue(reader.isSecureElementPresent());
    278                 session = reader.openSession();
    279                 assertNotNull("Null Session", session);
    280                 channel = session.openLogicalChannel(aid, (byte) 0x00);
    281                 fail("SecurityException Expected ");
    282             }
    283         } catch(SecurityException ex){ }
    284         catch (Exception e) {
    285             fail("Unexpected Exception " + e);
    286         }
    287         if (channel != null)
    288             channel.close();
    289         if (session != null)
    290             session.close();
    291     }
    292 
    293     private void testTransmitAPDU(byte[] aid, byte[] apdu) {
    294         Session session = null;
    295         Channel channel = null;
    296         try {
    297             waitForConnection();
    298             Reader[] readers = seService.getReaders();
    299 
    300             for (Reader reader : readers) {
    301                 assertTrue(reader.isSecureElementPresent());
    302                 session = reader.openSession();
    303                 assertNotNull("Null Session", session);
    304                 channel = session.openLogicalChannel(aid, (byte) 0x00);
    305                 assertNotNull("Null Channel", channel);
    306                 byte[] selectResponse = channel.getSelectResponse();
    307                 assertNotNull("Null Select Response", selectResponse);
    308                 assertEquals(selectResponse[selectResponse.length - 1] & 0xFF, 0x00);
    309                 assertEquals(selectResponse[selectResponse.length - 2] & 0xFF, 0x90);
    310                 assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
    311                 byte[] apduResponse = channel.transmit(apdu);
    312                 assertNotNull("Null Channel", apduResponse);
    313             }
    314         } catch (Exception e) {
    315             fail("Unexpected Exception " + e);
    316         }
    317         if (channel != null)
    318             channel.close();
    319         if (session != null)
    320             session.close();
    321     }
    322 
    323     private void testUnauthorisedAPDU(byte[] aid, byte[] apdu) {
    324         Session session = null;
    325         Channel channel = null;
    326         boolean exceptionOnTransmit = false;
    327         try {
    328             waitForConnection();
    329             Reader[] readers = seService.getReaders();
    330 
    331             for (Reader reader : readers) {
    332                 assertTrue(reader.isSecureElementPresent());
    333                 session = reader.openSession();
    334                 assertNotNull("Null Session", session);
    335                 channel = session.openLogicalChannel(aid, (byte) 0x00);
    336                 assertNotNull("Null Channel", channel);
    337                 byte[] selectResponse = channel.getSelectResponse();
    338                 assertNotNull("Null Select Response", selectResponse);
    339                 assertEquals(selectResponse[selectResponse.length - 1] & 0xFF, 0x00);
    340                 assertEquals(selectResponse[selectResponse.length - 2] & 0xFF, 0x90);
    341                 assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
    342                 exceptionOnTransmit = true;
    343                 channel.transmit(apdu);
    344                 fail("Security Exception is expected");
    345             }
    346         } catch (SecurityException ex) {
    347           if (!exceptionOnTransmit) {
    348             fail("Unexpected SecurityException onSelect" + ex);
    349           }
    350         } catch (Exception e) {
    351           fail("Unexpected Exception " + e);
    352         } finally {
    353             if(channel != null)
    354                 channel.close();
    355             if (session != null)
    356                 session.close();
    357         }
    358     }
    359 
    360     /**
    361      * Verifies TLV data
    362      *
    363      * @param tlv
    364      * @return true if the data is tlv formatted, false otherwise
    365      */
    366     private static boolean verifyBerTlvData(byte[] tlv) {
    367         if (tlv == null || tlv.length == 0) {
    368             throw new RuntimeException("Invalid tlv, null");
    369         }
    370 
    371         int i = 0;
    372         byte[] key = new byte[2];
    373         key[0] = tlv[i];
    374         if ((key[0] & 0x1F) == 0x1F) {
    375             // extra byte for TAG field
    376             key[1] = tlv[i = i + 1];
    377         }
    378 
    379         int len = tlv[i = i + 1] & 0xFF;
    380         if (len > 127) {
    381             // more than 1 byte for length
    382             int bytesLength = len - 128;
    383             len = 0;
    384             for (int j = bytesLength - 1; j >= 0; j--) {
    385               len += (tlv[i = i + 1] & 0xFF) * Math.pow(10, j);
    386             }
    387         }
    388         return tlv.length == (i + len + 3);
    389     }
    390 
    391     class ServiceConnectionTimerTask extends TimerTask {
    392         @Override
    393         public void run() {
    394             synchronized (serviceMutex) {
    395                 serviceMutex.notifyAll();
    396             }
    397         }
    398     }
    399 }
    400