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