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