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