/*
 * Copyright (C) 2017 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.
 */
/*
 * Copyright (c) 2015-2017, The Linux Foundation.
 */
/*
 * Contributed by: Giesecke & Devrient GmbH.
 */

package com.android.se;

import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.se.omapi.ISecureElementChannel;
import android.se.omapi.ISecureElementListener;
import android.se.omapi.SEService;
import android.util.Log;

import com.android.se.SecureElementService.SecureElementSession;
import com.android.se.security.ChannelAccess;

import java.io.IOException;

/**
 * Represents a Channel opened with the Secure Element
 */
public class Channel implements IBinder.DeathRecipient {

    private final String mTag = "SecureElement-Channel";
    private final int mChannelNumber;
    private final Object mLock = new Object();
    private IBinder mBinder = null;
    private boolean mIsClosed;
    private SecureElementSession mSession;
    private Terminal mTerminal;
    private byte[] mSelectResponse;
    private ChannelAccess mChannelAccess = null;
    private int mCallingPid = 0;
    private byte[] mAid = null;

    Channel(SecureElementSession session, Terminal terminal, int channelNumber,
            byte[] selectResponse, byte[] aid, ISecureElementListener listener) {
        if (terminal == null) {
            throw new IllegalArgumentException("Arguments can't be null");
        }
        mSession = session;
        mTerminal = terminal;
        mIsClosed = false;
        mSelectResponse = selectResponse;
        mChannelNumber = channelNumber;
        mAid = aid;
        if (listener != null) {
            try {
                mBinder = listener.asBinder();
                mBinder.linkToDeath(this, 0);
            } catch (RemoteException e) {
                Log.e(mTag, "Failed to register client listener");
            }
        }
    }

    /**
     * Close this channel if the client died.
     */
    public void binderDied() {
        try {
            Log.e(mTag, Thread.currentThread().getName() + " Client "
                    + mBinder.toString() + " died");
            close();
        } catch (Exception ignore) {
        }
    }

    /**
     * Closes the channel.
     */
    public void close() {
        synchronized (mLock) {
            if (isClosed())
                return;
            mIsClosed = true;
        }
        if (isBasicChannel()) {
            Log.i(mTag, "Close basic channel - Select without AID ...");
            mTerminal.selectDefaultApplication();
        }

        mTerminal.closeChannel(this);
        if (mBinder != null) {
            mBinder.unlinkToDeath(this, 0);
        }
        if (mSession != null) {
            mSession.removeChannel(this);
        }
    }

    /**
     * Transmits the given byte and returns the response.
     */
    public byte[] transmit(byte[] command) throws IOException {
        if (isClosed()) {
            throw new IllegalStateException("Channel is closed");
        }
        if (command == null) {
            throw new NullPointerException("Command must not be null");
        }
        if (mChannelAccess == null) {
            throw new SecurityException("Channel access not set");
        }
        if (mChannelAccess.getCallingPid() != mCallingPid) {
            throw new SecurityException("Wrong Caller PID.");
        }

        // Validate the APDU command format and throw IllegalArgumentException, if necessary.
        CommandApduValidator.execute(command);

        if (((command[0] & (byte) 0x80) == 0)
                && ((command[0] & (byte) 0x60) != (byte) 0x20)) {
            // ISO command
            if (command[1] == (byte) 0x70) {
                throw new SecurityException("MANAGE CHANNEL command not allowed");
            }
            if ((command[1] == (byte) 0xA4) && (command[2] == (byte) 0x04)) {
                // SELECT by DF name is only allowed for CarrierPrivilege applications
                // or system privilege applications
                if (ChannelAccess.ACCESS.ALLOWED != mChannelAccess.getPrivilegeAccess()) {
                    throw new SecurityException("SELECT by DF name command not allowed");
                }
            }
        }

        checkCommand(command);
        synchronized (mLock) {
            // set channel number bits
            command[0] = setChannelToClassByte(command[0], mChannelNumber);
            return mTerminal.transmit(command);
        }
    }

    private boolean selectNext() throws IOException {
        if (isClosed()) {
            throw new IllegalStateException("Channel is closed");
        } else if (mChannelAccess == null) {
            throw new IllegalStateException("Channel access not set.");
        } else if (mChannelAccess.getCallingPid() != mCallingPid) {
            throw new SecurityException("Wrong Caller PID.");
        } else if (mAid == null || mAid.length == 0) {
            throw new UnsupportedOperationException("No aid given");
        }

        byte[] selectCommand = new byte[5 + mAid.length];
        selectCommand[0] = 0x00;
        selectCommand[1] = (byte) 0xA4;
        selectCommand[2] = 0x04;
        selectCommand[3] = 0x02; // next occurrence
        selectCommand[4] = (byte) mAid.length;
        System.arraycopy(mAid, 0, selectCommand, 5, mAid.length);

        // set channel number bits
        selectCommand[0] = setChannelToClassByte(selectCommand[0], mChannelNumber);

        byte[] bufferSelectResponse = mTerminal.transmit(selectCommand);

        if (bufferSelectResponse.length < 2) {
            throw new UnsupportedOperationException("Transmit failed");
        }
        int sw1 = bufferSelectResponse[bufferSelectResponse.length - 2] & 0xFF;
        int sw2 = bufferSelectResponse[bufferSelectResponse.length - 1] & 0xFF;
        int sw = (sw1 << 8) | sw2;

        if (((sw & 0xF000) == 0x9000) || ((sw & 0xFF00) == 0x6200)
                || ((sw & 0xFF00) == 0x6300)) {
            mSelectResponse = bufferSelectResponse.clone();
            return true;
        } else if ((sw & 0xFF00) == 0x6A00) {
            return false;
        } else {
            throw new UnsupportedOperationException("Unsupported operation");
        }
    }

    /**
     * Returns a copy of the given CLA byte where the channel number bits are set
     * as specified by the given channel number
     *
     * <p>See GlobalPlatform Card Specification 2.2.0.7: 11.1.4 Class Byte Coding
     *
     * @param cla           the CLA byte. Won't be modified
     * @param channelNumber within [0..3] (for first inter-industry class byte
     *                      coding) or [4..19] (for further inter-industry class byte coding)
     * @return the CLA byte with set channel number bits. The seventh bit
     * indicating the used coding
     * (first/further interindustry class byte coding) might be modified
     */
    private byte setChannelToClassByte(byte cla, int channelNumber) {
        if (channelNumber < 4) {
            // b7 = 0 indicates the first interindustry class byte coding
            cla = (byte) ((cla & 0xBC) | channelNumber);
        } else if (channelNumber < 20) {
            // b7 = 1 indicates the further interindustry class byte coding
            boolean isSm = (cla & 0x0C) != 0;
            cla = (byte) ((cla & 0xB0) | 0x40 | (channelNumber - 4));
            if (isSm) {
                cla |= 0x20;
            }
        } else {
            throw new IllegalArgumentException("Channel number must be within [0..19]");
        }
        return cla;
    }

    public ChannelAccess getChannelAccess() {
        return this.mChannelAccess;
    }

    public void setChannelAccess(ChannelAccess channelAccess) {
        this.mChannelAccess = channelAccess;
    }

    private void setCallingPid(int pid) {
        mCallingPid = pid;
    }

    private void checkCommand(byte[] command) {
        if (mTerminal.getAccessControlEnforcer() != null) {
            // check command if it complies to the access rules.
            // if not an exception is thrown
            mTerminal.getAccessControlEnforcer().checkCommand(this, command);
        } else {
            // Allow access to Privileged App even if Access Control Enforcer is
            // not initialized
            if (ChannelAccess.ACCESS.ALLOWED != mChannelAccess.getPrivilegeAccess()) {
                throw new SecurityException("Access Controller not set for Terminal: "
                        + mTerminal.getName());
            }
        }
    }

    /**
     * true if aid could be selected during opening the channel
     * false if aid could not be or was not selected.
     *
     * @return boolean.
     */
    public boolean hasSelectedAid() {
        return (mAid != null);
    }

    public int getChannelNumber() {
        return mChannelNumber;
    }

    /**
     * Returns the data as received from the application select command
     * inclusively the status word.
     *
     * The returned byte array contains the data bytes in the following order:
     * first data byte, ... , last data byte, sw1, sw2
     *
     * @return null if an application SELECT command has not been performed or
     * the selection response can not be retrieved by the reader
     * implementation.
     */
    public byte[] getSelectResponse() {
        return (hasSelectedAid() ? mSelectResponse : null);
    }

    public boolean isBasicChannel() {
        return (mChannelNumber == 0) ? true : false;
    }

    public boolean isClosed() {
        return mIsClosed;
    }

    // Implementation of the SecureElement Channel interface according to OMAPI.
    final class SecureElementChannel extends ISecureElementChannel.Stub {

        @Override
        public void close() throws RemoteException {
            Channel.this.close();
        }

        @Override
        public boolean isClosed() throws RemoteException {
            return Channel.this.isClosed();
        }

        @Override
        public boolean isBasicChannel() throws RemoteException {
            return Channel.this.isBasicChannel();
        }

        @Override
        public byte[] getSelectResponse() throws RemoteException {
            return Channel.this.getSelectResponse();
        }

        @Override
        public byte[] transmit(byte[] command) throws RemoteException {
            Channel.this.setCallingPid(Binder.getCallingPid());
            try {
                return Channel.this.transmit(command);
            } catch (IOException e) {
                throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage());
            }
        }

        @Override
        public boolean selectNext() throws RemoteException {
            Channel.this.setCallingPid(Binder.getCallingPid());
            try {
                return Channel.this.selectNext();
            } catch (IOException e) {
                throw new ServiceSpecificException(SEService.IO_ERROR, e.getMessage());
            }
        }
    }
}
