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