/*
 * 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) 2014-2017, The Linux Foundation.
 */

/*
 * Copyright 2012 Giesecke & Devrient GmbH.
 *
 * 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.
 */

package com.android.se.security;

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;

import com.android.se.Channel;
import com.android.se.SecureElementService;
import com.android.se.Terminal;
import com.android.se.security.ChannelAccess.ACCESS;
import com.android.se.security.ara.AraController;
import com.android.se.security.arf.ArfController;

import java.io.IOException;
import java.io.PrintWriter;
import java.security.AccessControlException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;

/** Reads and Maintains the ARF and ARA access control for a particular Secure Element */
public class AccessControlEnforcer {

    private final String mTag = "SecureElement-AccessControlEnforcer";
    private PackageManager mPackageManager = null;
    private boolean mNoRuleFound = false;
    private AraController mAraController = null;
    private boolean mUseAra = true;
    private ArfController mArfController = null;
    private boolean mUseArf = false;
    private AccessRuleCache mAccessRuleCache = null;
    private boolean mRulesRead = false;
    private Terminal mTerminal = null;
    private ChannelAccess mInitialChannelAccess = new ChannelAccess();
    private boolean mFullAccess = false;

    public AccessControlEnforcer(Terminal terminal) {

        mTerminal = terminal;
        mAccessRuleCache = new AccessRuleCache();
    }

    public static byte[] getDefaultAccessControlAid() {
        return AraController.getAraMAid();
    }

    public PackageManager getPackageManager() {
        return mPackageManager;
    }

    public void setPackageManager(PackageManager packageManager) {
        mPackageManager = packageManager;
    }

    public Terminal getTerminal() {
        return mTerminal;
    }

    public AccessRuleCache getAccessRuleCache() {
        return mAccessRuleCache;
    }

    /** Resets the Access Control for the Secure Element */
    public synchronized void reset() {
        // Destroy any previous Controler
        // in order to reset the ACE
        Log.i(mTag, "Reset the ACE for terminal:" + mTerminal.getName());
        mAccessRuleCache.reset();
        mAraController = null;
        mArfController = null;
    }

    /** Initializes the Access Control for the Secure Element */
    public synchronized void initialize() throws IOException, MissingResourceException {
        boolean status = true;
        String denyMsg = "";
        // allow access to set up access control for a channel
        mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.ALLOWED);
        mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.ALLOWED);
        mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.ALLOWED, "");

        readSecurityProfile();
        mNoRuleFound = false;

        // 1 - Let's try to use ARA
        if (mUseAra && mAraController == null) {
            mAraController = new AraController(mAccessRuleCache, mTerminal);
        }

        if (mUseAra && mAraController != null) {
            try {
                mAraController.initialize();
                Log.i(mTag, "ARA applet is used for:" + mTerminal.getName());
                // disable other access methods
                mUseArf = false;
                mFullAccess = false;
            } catch (IOException | MissingResourceException e) {
                throw e;
            } catch (Exception e) {
                // ARA cannot be used since we got an exception during initialization
                mUseAra = false;
                denyMsg = e.getLocalizedMessage();
                if (e instanceof NoSuchElementException) {
                    Log.i(mTag, "No ARA applet found in: " + mTerminal.getName());
                    if (!mUseArf) {
                        // ARA does not exist on the secure element right now,
                        // but it might be installed later.
                        mNoRuleFound = true;
                        status = mFullAccess;
                    }
                } else if (mTerminal.getName().startsWith(SecureElementService.UICC_TERMINAL)) {
                    // A possible explanation could simply be due to the fact that the UICC is old
                    // and does not support logical channel (and is not compliant with GP spec).
                    // We should simply act as if no ARA was available in this case.
                    if (!mUseArf) {
                        // Only ARA was the candidate to retrieve access rules,
                        // but it is not 100% sure if the expected ARA really does not exist.
                        // Full access should not be granted in this case.
                        mFullAccess = false;
                        status = false;
                    }
                } else {
                    // ARA is available but doesn't work properly.
                    // We are going to disable everything per security req.
                    mUseArf = false;
                    mFullAccess = false;
                    status = false;
                    Log.i(mTag, "Problem accessing ARA, Access DENIED "
                            + e.getLocalizedMessage());
                }
            }
        }

        // 2 - Let's try to use ARF since ARA cannot be used
        if (mUseArf && mArfController == null) {
            mArfController = new ArfController(mAccessRuleCache, mTerminal);
        }

        if (mUseArf && mArfController != null) {
            try {
                mArfController.initialize();
                // disable other access methods
                Log.i(mTag, "ARF rules are used for:" + mTerminal.getName());
                mFullAccess = false;
            } catch (IOException | MissingResourceException e) {
                throw e;
            } catch (Exception e) {
                // ARF cannot be used since we got an exception
                mUseArf = false;
                denyMsg = e.getLocalizedMessage();
                Log.e(mTag, e.getMessage());
                if (e instanceof NoSuchElementException) {
                    Log.i(mTag, "No ARF found in: " + mTerminal.getName());
                    // ARF does not exist on the secure element right now,
                    // but it might be added later.
                    mNoRuleFound = true;
                    status = mFullAccess;
                } else {
                    // It is not 100% sure if the expected ARF really does not exist.
                    // No ARF might be due to a kind of temporary problem,
                    // so full access should not be granted in this case.
                    mFullAccess = false;
                    status = false;
                }
            }
        }

        /* 4 - Let's block everything since neither ARA, ARF or fullaccess can be used */
        if (!mUseArf && !mUseAra && !mFullAccess) {
            mInitialChannelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED);
            mInitialChannelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
            mInitialChannelAccess.setAccess(ChannelAccess.ACCESS.DENIED, denyMsg);
            Log.i(mTag, "Deny any access to:" + mTerminal.getName());
        }

        mRulesRead = status;
    }

    /**
     * Returns the result of the previous attempt to select ARA and/or ARF.
     *
     * @return true if no rule was found in the previous attempt.
     */
    public boolean isNoRuleFound() {
        return mNoRuleFound;
    }

    /** Check if the Channel has permission for the given APDU */
    public synchronized void checkCommand(Channel channel, byte[] command) {
        ChannelAccess ca = channel.getChannelAccess();
        if (ca == null) {
            throw new AccessControlException(mTag + "Channel access not set");
        }
        String reason = ca.getReason();
        if (reason.length() == 0) {
            reason = "Command not allowed!";
        }
        if (ca.getAccess() != ACCESS.ALLOWED) {
            throw new AccessControlException(mTag + reason);
        }
        if (ca.isUseApduFilter()) {
            ApduFilter[] accessConditions = ca.getApduFilter();
            if (accessConditions == null || accessConditions.length == 0) {
                throw new AccessControlException(mTag + "Access Rule not available:"
                        + reason);
            }
            for (ApduFilter ac : accessConditions) {
                if (CommandApdu.compareHeaders(command, ac.getMask(), ac.getApdu())) {
                    return;
                }
            }
            throw new AccessControlException(mTag + "Access Rule does not match: "
                    + reason);
        }
        if (ca.getApduAccess() == ChannelAccess.ACCESS.ALLOWED) {
            return;
        } else {
            throw new AccessControlException(mTag + "APDU access NOT allowed");
        }
    }

    /** Sets up the Channel Access for the given Package */
    public ChannelAccess setUpChannelAccess(byte[] aid, String packageName, boolean checkRefreshTag)
            throws IOException, MissingResourceException {
        ChannelAccess channelAccess = null;
        // check result of channel access during initialization procedure
        if (mInitialChannelAccess.getAccess() == ChannelAccess.ACCESS.DENIED) {
            throw new AccessControlException(
                    mTag + "access denied: " + mInitialChannelAccess.getReason());
        }
        // this is the new GP Access Control Enforcer implementation
        if (mUseAra || mUseArf) {
            channelAccess = internal_setUpChannelAccess(aid, packageName,
                    checkRefreshTag);
        }
        if (channelAccess == null || (channelAccess.getApduAccess() != ChannelAccess.ACCESS.ALLOWED
                && !channelAccess.isUseApduFilter())) {
            if (mFullAccess) {
                // if full access is set then we reuse the initial channel access,
                // since we got so far it allows everything with a descriptive reason.
                channelAccess = mInitialChannelAccess;
            } else {
                throw new AccessControlException(mTag + "no APDU access allowed!");
            }
        }
        channelAccess.setPackageName(packageName);
        return channelAccess.clone();
    }

    private synchronized ChannelAccess internal_setUpChannelAccess(byte[] aid,
            String packageName, boolean checkRefreshTag) throws IOException,
            MissingResourceException {
        if (packageName == null || packageName.isEmpty()) {
            throw new AccessControlException("package names must be specified");
        }
        try {
            // estimate SHA-1 and SHA-256 hash values of the device application's certificate.
            List<byte[]> appCertHashes = getAppCertHashes(packageName);
            // APP certificates must be available => otherwise Exception
            if (appCertHashes == null || appCertHashes.size() == 0) {
                throw new AccessControlException(
                        "Application certificates are invalid or do not exist.");
            }
            if (checkRefreshTag) {
                updateAccessRuleIfNeed();
            }
            return getAccessRule(aid, appCertHashes);
        } catch (IOException | MissingResourceException e) {
            throw e;
        } catch (Throwable exp) {
            throw new AccessControlException(exp.getMessage());
        }
    }

    /** Fetches the Access Rules for the given application and AID pair */
    public ChannelAccess getAccessRule(
            byte[] aid, List<byte []> appCertHashes)
            throws AccessControlException {
        ChannelAccess channelAccess = null;
        // if read all is true get rule from cache.
        if (mRulesRead) {
            // get rules from internal storage
            channelAccess = mAccessRuleCache.findAccessRule(aid, appCertHashes);
        }
        // if no rule was found return an empty access rule
        // with all access denied.
        if (channelAccess == null) {
            channelAccess = new ChannelAccess();
            channelAccess.setAccess(ChannelAccess.ACCESS.DENIED, "no access rule found!");
            channelAccess.setApduAccess(ChannelAccess.ACCESS.DENIED);
            channelAccess.setNFCEventAccess(ChannelAccess.ACCESS.DENIED);
        }
        return channelAccess;
    }

    /**
     * Returns hashes of certificate chain for one package.
     */
    private List<byte[]> getAppCertHashes(String packageName)
            throws NoSuchAlgorithmException, AccessControlException {
        if (packageName == null || packageName.length() == 0) {
            throw new AccessControlException("Package Name not defined");
        }
        PackageInfo foundPkgInfo;
        try {
            foundPkgInfo = mPackageManager.getPackageInfo(packageName,
                    PackageManager.GET_SIGNATURES);
        } catch (NameNotFoundException ne) {
            throw new AccessControlException("Package does not exist");
        }
        if (foundPkgInfo == null) {
            throw new AccessControlException("Package does not exist");
        }
        MessageDigest md = MessageDigest.getInstance("SHA");
        MessageDigest md256 = MessageDigest.getInstance("SHA-256");
        if (md == null || md256 == null) {
            throw new AccessControlException("Hash can not be computed");
        }
        List<byte[]> appCertHashes = new ArrayList<byte[]>();
        for (Signature signature : foundPkgInfo.signatures) {
            appCertHashes.add(md.digest(signature.toByteArray()));
            appCertHashes.add(md256.digest(signature.toByteArray()));
        }
        return appCertHashes;
    }

    /** Returns true if the given application is allowed to recieve NFC Events */
    public synchronized boolean[] isNfcEventAllowed(byte[] aid,
            String[] packageNames) {
        if (mUseAra || mUseArf) {
            return internal_isNfcEventAllowed(aid, packageNames);
        } else {
            // if ARA and ARF is not available and
            // - terminal DOES NOT belong to a UICC -> mFullAccess is true
            // - terminal belongs to a UICC -> mFullAccess is false
            boolean[] ret = new boolean[packageNames.length];
            for (int i = 0; i < ret.length; i++) {
                ret[i] = mFullAccess;
            }
            return ret;
        }
    }

    private synchronized boolean[] internal_isNfcEventAllowed(byte[] aid,
            String[] packageNames) {
        int i = 0;
        boolean[] nfcEventFlags = new boolean[packageNames.length];
        for (String packageName : packageNames) {
            // estimate hash value of the device application's certificate.
            try {
                List<byte[]> appCertHashes = getAppCertHashes(packageName);
                // APP certificates must be available => otherwise Exception
                if (appCertHashes == null || appCertHashes.size() == 0) {
                    nfcEventFlags[i] = false;
                } else {
                    ChannelAccess channelAccess = getAccessRule(aid, appCertHashes);
                    nfcEventFlags[i] =
                            (channelAccess.getNFCEventAccess() == ChannelAccess.ACCESS.ALLOWED);
                }
            } catch (Exception e) {
                Log.w(mTag, " Access Rules for NFC: " + e.getLocalizedMessage());
                nfcEventFlags[i] = false;
            }
            i++;
        }
        return nfcEventFlags;
    }

    private void updateAccessRuleIfNeed() throws IOException {
        if (mUseAra && mAraController != null) {
            try {
                mAraController.initialize();
                mUseArf = false;
                mFullAccess = false;
            } catch (IOException | MissingResourceException e) {
                // There was a communication error between the terminal and the secure element
                // or failure in retrieving rules due to the lack of a new logical channel.
                // These errors must be distinguished from other ones.
                throw e;
            } catch (Exception e) {
                throw new AccessControlException("No ARA applet found in " + mTerminal.getName());
            }
        } else if (mUseArf && mArfController != null) {
            try {
                mArfController.initialize();
            } catch (IOException | MissingResourceException e) {
                // There was a communication error between the terminal and the secure element
                // or failure in retrieving rules due to the lack of a new logical channel.
                // These errors must be distinguished from other ones.
                throw e;
            } catch (Exception e) {
                Log.e(mTag, e.getMessage());
            }
        }
    }

    /** Debug information to be used by dumpsys */
    public void dump(PrintWriter writer) {
        writer.println(mTag + ":");

        writer.println("mUseArf: " + mUseArf);
        writer.println("mUseAra: " + mUseAra);
        writer.println("mInitialChannelAccess:");
        writer.println(mInitialChannelAccess.toString());
        writer.println();

        /* Dump the access rule cache */
        if (mAccessRuleCache != null) mAccessRuleCache.dump(writer);
    }

    private void readSecurityProfile() {
        if (!Build.IS_DEBUGGABLE) {
            mUseArf = true;
            mUseAra = true;
            mFullAccess = false; // Per default we don't grant full access.
        } else {
            String level = SystemProperties.get("service.seek", "useara usearf");
            level = SystemProperties.get("persist.service.seek", level);

            if (level.contains("usearf")) {
                mUseArf = true;
            } else {
                mUseArf = false;
            }
            if (level.contains("useara")) {
                mUseAra = true;
            } else {
                mUseAra = false;
            }
            if (level.contains("fullaccess")) {
                mFullAccess = true;
            } else {
                mFullAccess = false;
            }
        }
        if (!mTerminal.getName().startsWith(SecureElementService.UICC_TERMINAL)) {
            // It shall be allowed to grant full access if no rule can be retrieved
            // from the secure element except for UICC.
            mFullAccess = true;
            // ARF is supported only on UICC.
            mUseArf = false;
        }
        Log.i(
                mTag,
                "Allowed ACE mode: ara=" + mUseAra + " arf=" + mUseArf + " fullaccess="
                        + mFullAccess);
    }
}
