/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Contributed by Orange */

package android.omapi.accesscontrol3.cts;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeTrue;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;

import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;
import android.support.test.InstrumentationRegistry;
import android.os.Build;
import com.android.compatibility.common.util.PropertyUtil;

public class AccessControlTest {
    private final static String UICC_READER_PREFIX = "SIM";
    private final static String ESE_READER_PREFIX = "eSE";
    private final static String SD_READER_PREFIX = "SD";

    private final static byte[] AID_40 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x40 };
    private final static byte[] AID_41 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x41 };
    private final static byte[] AID_42 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x42 };
    private final static byte[] AID_43 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x43 };
    private final static byte[] AID_44 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x44 };
    private final static byte[] AID_45 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x45 };
    private final static byte[] AID_46 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x46 };
    private final static byte[] AID_47 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x47 };
    private final static byte[] AID_48 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x48 };
    private final static byte[] AID_49 = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, 0x49 };
    private final static byte[] AID_4A = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, (byte) 0x4A };
    private final static byte[] AID_4B = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, (byte) 0x4B };
    private final static byte[] AID_4C = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, (byte) 0x4C };
    private final static byte[] AID_4D = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, (byte) 0x4D };
    private final static byte[] AID_4E = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, (byte) 0x4E };
    private final static byte[] AID_4F = new byte[] { (byte) 0xA0, 0x00, 0x00,
        0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54,
        0x53, (byte) 0x4F };

    private final static byte[][] AUTHORIZED_AID = new byte[][] { AID_40,
        AID_41, AID_45, AID_46 };
    private final static byte[][] UNAUTHORIZED_AID = new byte[][] { AID_42,
        AID_43, AID_44, AID_47, AID_48, AID_49, AID_4A, AID_4B, AID_4C, AID_4D, AID_4E,
        AID_4F };

    /* Authorized APDU for AID_40 */
    private final static byte[][] AUTHORIZED_APDU_AID_40 = new byte[][] {
        { 0x00, 0x06, 0x00, 0x00 }, { (byte) 0x80, 0x06, 0x00, 0x00 },
        { (byte) 0xA0, 0x06, 0x00, 0x00 },
        { (byte) 0x94, 0x06, 0x00, 0x00 },
        { 0x00, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { (byte) 0x80, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { (byte) 0xA0, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { (byte) 0x94, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { 0x00, 0x08, 0x00, 0x00, 0x00 },
        { (byte) 0x80, 0x08, 0x00, 0x00, 0x00 },
        { (byte) 0xA0, 0x08, 0x00, 0x00, 0x00 },
        { (byte) 0x94, 0x08, 0x00, 0x00, 0x00 },
        { 0x00, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
        { (byte) 0x80, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
        { (byte) 0xA0, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
        { (byte) 0x94, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 }};

    /* Authorized APDU for AID_41 */
    private final static byte[][] AUTHORIZED_APDU_AID_41 = new byte[][] {
        { (byte) 0x94, 0x06, 0x00, 0x00 },
        { (byte) 0x94, 0x08, 0x00, 0x00, 0x00 },
        { (byte) 0x94, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
        { (byte) 0x94, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA } };
    /* Unauthorized APDU for AID_41 */
    private final static byte[][] UNAUTHORIZED_APDU_AID_41 = new byte[][] {
        { 0x00, 0x06, 0x00, 0x00 }, { (byte) 0x80, 0x06, 0x00, 0x00 },
        { (byte) 0xA0, 0x06, 0x00, 0x00 },
        { 0x00, 0x08, 0x00, 0x00, 0x00 },
        { (byte) 0x00, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { (byte) 0x80, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { (byte) 0xA0, 0x0A, 0x00, 0x00, 0x01, (byte) 0xAA },
        { (byte) 0x80, 0x08, 0x00, 0x00, 0x00 },
        { (byte) 0xA0, 0x08, 0x00, 0x00, 0x00 },
        { 0x00, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
        { (byte) 0x80, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
        { (byte) 0xA0, (byte) 0x0C, 0x00, 0x00, 0x01, (byte) 0xAA, 0x00 },
    };

    private final long SERVICE_CONNECTION_TIME_OUT = 3000;
    private SEService seService;
    private Object serviceMutex = new Object();
    private Timer connectionTimer;
    private ServiceConnectionTimerTask mTimerTask = new ServiceConnectionTimerTask();
    private boolean connected = false;

    private final OnConnectedListener mListener = new OnConnectedListener() {
        @Override
        public void onConnected() {
            synchronized (serviceMutex) {
                connected = true;
                serviceMutex.notify();
            }
        }
    };

    class SynchronousExecutor implements Executor {
        public void execute(Runnable r) {
            r.run();
        }
    }

    private boolean supportsHardware() {
        final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
        boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
        return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
    }

    @Before
    public void setUp() throws Exception {
        assumeTrue(PropertyUtil.getFirstApiLevel() > Build.VERSION_CODES.O_MR1);
        assumeTrue(supportsHardware());
        seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
        connectionTimer = new Timer();
        connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
    }

    @After
    public void tearDown() throws Exception {
        if (seService != null && seService.isConnected()) {
            seService.shutdown();
            connected = false;
        }
    }

    private void waitForConnection() throws TimeoutException {
        synchronized (serviceMutex) {
            if (!connected) {
                try {
                    serviceMutex.wait();
                 } catch (InterruptedException e) {
                    e.printStackTrace();
                 }
            }
            if (!connected) {
                throw new TimeoutException(
                    "Service could not be connected after "
                    + SERVICE_CONNECTION_TIME_OUT + " ms");
            }
            if (connectionTimer != null) {
                connectionTimer.cancel();
            }
        }
    }

    @Test
    public void testAuthorizedAID() {
        for (byte[] aid : AUTHORIZED_AID) {
            testSelectableAid(aid);
        }
    }

    @Test
    public void testUnauthorizedAID() {
        for (byte[] aid : UNAUTHORIZED_AID) {
            testUnauthorisedAid(aid);
        }
    }

    @Test
    public void testAuthorizedAPDUAID40() {
        for (byte[] apdu : AUTHORIZED_APDU_AID_40) {
            testTransmitAPDU(AID_40, apdu);
        }
    }

    @Test
    public void testAuthorizedAPDUAID41() {
        for (byte[] apdu : AUTHORIZED_APDU_AID_41) {
            testTransmitAPDU(AID_41, apdu);
        }
    }

    @Test
    public void testUnauthorisedAPDUAID41() {
        for (byte[] apdu : UNAUTHORIZED_APDU_AID_41) {
            testUnauthorisedAPDU(AID_41, apdu);
        }
    }

    private void testSelectableAid(byte[] aid) {
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    session = reader.openSession();
                    assertNotNull("Null Session", session);
                    channel = session.openLogicalChannel(aid, (byte) 0x00);
                    assertNotNull("Null Channel", channel);
                    byte[] selectResponse = channel.getSelectResponse();
                    assertNotNull("Null Select Response", selectResponse);
                    assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
                    assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
                    assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    private void testUnauthorisedAid(byte[] aid) {
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    session = reader.openSession();
                    assertNotNull("Null Session", session);
                    try {
                        channel = session.openLogicalChannel(aid, (byte) 0x00);
                        fail("SecurityException Expected");
                    } catch (SecurityException e) {
                        // Expected
                    }
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    private void testTransmitAPDU(byte[] aid, byte[] apdu) {
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    session = reader.openSession();
                    assertNotNull("Null Session", session);
                    channel = session.openLogicalChannel(aid, (byte) 0x00);
                    assertNotNull("Null Channel", channel);
                    byte[] selectResponse = channel.getSelectResponse();
                    assertNotNull("Null Select Response", selectResponse);
                    assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
                    assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
                    assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
                    byte[] apduResponse = channel.transmit(apdu);
                    assertNotNull("Null Channel", apduResponse);
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    private void testUnauthorisedAPDU(byte[] aid, byte[] apdu) {
        try {
            waitForConnection();
            Reader[] readers = seService.getReaders();
            for (Reader reader : readers) {
                Session session = null;
                Channel channel = null;
                try {
                    assertTrue(reader.isSecureElementPresent());
                    session = reader.openSession();
                    assertNotNull("Null Session", session);
                    channel = session.openLogicalChannel(aid, (byte) 0x00);
                    assertNotNull("Null Channel", channel);
                    byte[] selectResponse = channel.getSelectResponse();
                    assertNotNull("Null Select Response", selectResponse);
                    assertThat(selectResponse[selectResponse.length - 1] & 0xFF, is(0x00));
                    assertThat(selectResponse[selectResponse.length - 2] & 0xFF, is(0x90));
                    assertTrue("Select Response is not complete", verifyBerTlvData(selectResponse));
                    try {
                        channel.transmit(apdu);
                        fail("Security Exception is expected");
                    } catch (SecurityException e) {
                        // Expected
                    }
                } finally {
                    if (channel != null) channel.close();
                    if (session != null) session.close();
                }
            }
        } catch (Exception e) {
            fail("Unexpected Exception " + e);
        }
    }

    /**
     * Verifies TLV data
     *
     * @param tlv
     * @return true if the data is tlv formatted, false otherwise
     */
    private static boolean verifyBerTlvData(byte[] tlv) {
        if (tlv == null || tlv.length == 0) {
            throw new RuntimeException("Invalid tlv, null");
        }

        int i = 0;
        byte[] key = new byte[2];
        key[0] = tlv[i];
        if ((key[0] & 0x1F) == 0x1F) {
            // extra byte for TAG field
            key[1] = tlv[i = i + 1];
        }

        int len = tlv[i = i + 1] & 0xFF;
        if (len > 127) {
            // more than 1 byte for length
            int bytesLength = len - 128;
            len = 0;
            for (int j = bytesLength - 1; j >= 0; j--) {
              len += (tlv[i = i + 1] & 0xFF) * Math.pow(10, j);
            }
        }
        return tlv.length == (i + len + 3);
    }

    class ServiceConnectionTimerTask extends TimerTask {
        @Override
        public void run() {
            synchronized (serviceMutex) {
                serviceMutex.notifyAll();
            }
        }
    }
}
