/*
 * Copyright (C) 2022 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.
 */

package android.content.pm.parsing;

import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;

import android.annotation.CheckResult;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
import android.content.pm.parsing.result.ParseInput;
import android.content.pm.parsing.result.ParseResult;
import android.os.Build;
import android.os.FileUtils;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Slog;
import android.util.apk.ApkSignatureVerifier;

import com.android.internal.util.ArrayUtils;
import com.android.modules.utils.build.UnboundedSdkLevel;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;

/** @hide */
public class FrameworkParsingPackageUtils {

    private static final String TAG = "FrameworkParsingPackageUtils";

    /**
     * For those names would be used as a part of the file name. Limits size to 223 and reserves 32
     * for the OS.
     */
    private static final int MAX_FILE_NAME_SIZE = 223;

    public static final int PARSE_IGNORE_OVERLAY_REQUIRED_SYSTEM_PROPERTY = 1 << 7;
    public static final int PARSE_APK_IN_APEX = 1 << 9;

    /**
     * Check if the given name is valid.
     *
     * @param name The name to check.
     * @param requireSeparator {@code true} if the name requires containing a separator at least.
     * @param requireFilename {@code true} to apply file name validation to the given name. It also
     *                        limits length of the name to the {@link #MAX_FILE_NAME_SIZE}.
     * @return Success if it's valid.
     */
    public static String validateName(String name, boolean requireSeparator,
            boolean requireFilename) {
        final int N = name.length();
        boolean hasSep = false;
        boolean front = true;
        for (int i = 0; i < N; i++) {
            final char c = name.charAt(i);
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                front = false;
                continue;
            }
            if (!front) {
                if ((c >= '0' && c <= '9') || c == '_') {
                    continue;
                }
            }
            if (c == '.') {
                hasSep = true;
                front = true;
                continue;
            }
            return "bad character '" + c + "'";
        }
        if (requireFilename) {
            if (!FileUtils.isValidExtFilename(name)) {
                return "Invalid filename";
            } else if (N > MAX_FILE_NAME_SIZE) {
                return "the length of the name is greater than " + MAX_FILE_NAME_SIZE;
            }
        }
        return hasSep || !requireSeparator ? null : "must have at least one '.' separator";
    }

    /**
     * @see #validateName(String, boolean, boolean)
     */
    public static ParseResult validateName(ParseInput input, String name, boolean requireSeparator,
            boolean requireFilename) {
        final String errorMessage = validateName(name, requireSeparator, requireFilename);
        if (errorMessage != null) {
            return input.error(errorMessage);
        }
        return input.success(null);
    }

    /**
     * @return {@link PublicKey} of a given encoded public key.
     */
    public static PublicKey parsePublicKey(final String encodedPublicKey) {
        if (encodedPublicKey == null) {
            Slog.w(TAG, "Could not parse null public key");
            return null;
        }

        try {
            return parsePublicKey(Base64.decode(encodedPublicKey, Base64.DEFAULT));
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
            return null;
        }
    }

    /**
     * @return {@link PublicKey} of the given byte array of a public key.
     */
    public static PublicKey parsePublicKey(final byte[] publicKey) {
        if (publicKey == null) {
            Slog.w(TAG, "Could not parse null public key");
            return null;
        }

        final EncodedKeySpec keySpec;
        try {
            keySpec = new X509EncodedKeySpec(publicKey);
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Could not parse verifier public key; invalid Base64");
            return null;
        }

        /* First try the key as an RSA key. */
        try {
            final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            Slog.wtf(TAG, "Could not parse public key: RSA KeyFactory not included in build");
        } catch (InvalidKeySpecException e) {
            // Not a RSA public key.
        }

        /* Now try it as a ECDSA key. */
        try {
            final KeyFactory keyFactory = KeyFactory.getInstance("EC");
            return keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            Slog.wtf(TAG, "Could not parse public key: EC KeyFactory not included in build");
        } catch (InvalidKeySpecException e) {
            // Not a ECDSA public key.
        }

        /* Now try it as a DSA key. */
        try {
            final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
            return keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            Slog.wtf(TAG, "Could not parse public key: DSA KeyFactory not included in build");
        } catch (InvalidKeySpecException e) {
            // Not a DSA public key.
        }

        /* Not a supported key type */
        return null;
    }

    /**
     * Returns {@code true} if both the property name and value are empty or if the given system
     * property is set to the specified value. Properties can be one or more, and if properties are
     * more than one, they must be separated by comma, and count of names and values must be equal,
     * and also every given system property must be set to the corresponding value.
     * In all other cases, returns {@code false}
     */
    public static boolean checkRequiredSystemProperties(@Nullable String rawPropNames,
            @Nullable String rawPropValues) {
        if (TextUtils.isEmpty(rawPropNames) || TextUtils.isEmpty(rawPropValues)) {
            if (!TextUtils.isEmpty(rawPropNames) || !TextUtils.isEmpty(rawPropValues)) {
                // malformed condition - incomplete
                Slog.w(TAG, "Disabling overlay - incomplete property :'" + rawPropNames
                        + "=" + rawPropValues + "' - require both requiredSystemPropertyName"
                        + " AND requiredSystemPropertyValue to be specified.");
                return false;
            }
            // no valid condition set - so no exclusion criteria, overlay will be included.
            return true;
        }

        final String[] propNames = rawPropNames.split(",");
        final String[] propValues = rawPropValues.split(",");

        if (propNames.length != propValues.length) {
            Slog.w(TAG, "Disabling overlay - property :'" + rawPropNames
                    + "=" + rawPropValues + "' - require both requiredSystemPropertyName"
                    + " AND requiredSystemPropertyValue lists to have the same size.");
            return false;
        }
        for (int i = 0; i < propNames.length; i++) {
            // Check property value: make sure it is both set and equal to expected value
            final String currValue = SystemProperties.get(propNames[i]);
            if (!TextUtils.equals(currValue, propValues[i])) {
                return false;
            }
        }
        return true;
    }

    @CheckResult
    public static ParseResult<SigningDetails> getSigningDetails(ParseInput input,
            String baseCodePath, boolean skipVerify, boolean isStaticSharedLibrary,
            @NonNull SigningDetails existingSigningDetails, int targetSdk) {
        int minSignatureScheme = ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
                targetSdk);
        if (isStaticSharedLibrary) {
            // must use v2 signing scheme
            minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
        }
        final ParseResult<SigningDetails> verified;
        if (skipVerify) {
            // systemDir APKs are already trusted, save time by not verifying; since the
            // signature is not verified and some system apps can have their V2+ signatures
            // stripped allow pulling the certs from the jar signature.
            verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(input, baseCodePath,
                    SigningDetails.SignatureSchemeVersion.JAR);
        } else {
            verified = ApkSignatureVerifier.verify(input, baseCodePath, minSignatureScheme);
        }

        if (verified.isError()) {
            return input.error(verified);
        }

        // Verify that entries are signed consistently with the first pkg
        // we encountered. Note that for splits, certificates may have
        // already been populated during an earlier parse of a base APK.
        if (existingSigningDetails == SigningDetails.UNKNOWN) {
            return verified;
        } else {
            if (!Signature.areExactMatch(existingSigningDetails.getSignatures(),
                    verified.getResult().getSignatures())) {
                return input.error(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
                        baseCodePath + " has mismatched certificates");
            }

            return input.success(existingSigningDetails);
        }
    }

    /**
     * Computes the minSdkVersion to use at runtime. If the package is not compatible with this
     * platform, populates {@code outError[0]} with an error message.
     * <p>
     * If {@code minCode} is not specified, e.g. the value is {@code null}, then behavior varies
     * based on the {@code platformSdkVersion}:
     * <ul>
     * <li>If the platform SDK version is greater than or equal to the
     * {@code minVers}, returns the {@code mniVers} unmodified.
     * <li>Otherwise, returns -1 to indicate that the package is not
     * compatible with this platform.
     * </ul>
     * <p>
     * Otherwise, the behavior varies based on whether the current platform
     * is a pre-release version, e.g. the {@code platformSdkCodenames} array
     * has length > 0:
     * <ul>
     * <li>If this is a pre-release platform and the value specified by
     * {@code targetCode} is contained within the array of allowed pre-release
     * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
     * <li>If this is a released platform, this method will return -1 to
     * indicate that the package is not compatible with this platform.
     * </ul>
     *
     * @param minVers              minSdkVersion number, if specified in the application manifest,
     *                             or 1 otherwise
     * @param minCode              minSdkVersion code, if specified in the application manifest, or
     *                             {@code null} otherwise
     * @param platformSdkVersion   platform SDK version number, typically Build.VERSION.SDK_INT
     * @param platformSdkCodenames array of allowed prerelease SDK codenames for this platform
     * @return the minSdkVersion to use at runtime if successful
     */
    public static ParseResult<Integer> computeMinSdkVersion(@IntRange(from = 1) int minVers,
            @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
            @NonNull String[] platformSdkCodenames, @NonNull ParseInput input) {
        // If it's a release SDK, make sure we meet the minimum SDK requirement.
        if (minCode == null) {
            if (minVers <= platformSdkVersion) {
                return input.success(minVers);
            }

            // We don't meet the minimum SDK requirement.
            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
                    "Requires newer sdk version #" + minVers
                            + " (current version is #" + platformSdkVersion + ")");
        }

        // If it's a pre-release SDK and the codename matches this platform, we
        // definitely meet the minimum SDK requirement.
        if (matchTargetCode(platformSdkCodenames, minCode)) {
            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
        }

        // STOPSHIP: hack for the pre-release SDK
        if (platformSdkCodenames.length == 0
                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
                        minCode)) {
            Slog.w(TAG, "Parsed package requires min development platform " + minCode
                    + ", returning current version " + Build.VERSION.SDK_INT);
            return input.success(Build.VERSION.SDK_INT);
        }

        // Otherwise, we're looking at an incompatible pre-release SDK.
        if (platformSdkCodenames.length > 0) {
            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
                    "Requires development platform " + minCode
                            + " (current platform is any of "
                            + Arrays.toString(platformSdkCodenames) + ")");
        } else {
            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
                    "Requires development platform " + minCode
                            + " but this is a release platform.");
        }
    }

    /**
     * Computes the targetSdkVersion to use at runtime. If the package is not compatible with this
     * platform, populates {@code outError[0]} with an error message.
     * <p>
     * If {@code targetCode} is not specified, e.g. the value is {@code null}, then the {@code
     * targetVers} will be returned unmodified.
     * <p>
     * When {@code allowUnknownCodenames} is false, the behavior varies based on whether the
     * current platform is a pre-release version, e.g. the {@code platformSdkCodenames} array has
     * length > 0:
     * <ul>
     * <li>If this is a pre-release platform and the value specified by
     * {@code targetCode} is contained within the array of allowed pre-release
     * codenames, this method will return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
     * <li>If this is a released platform, this method will return -1 to
     * indicate that the package is not compatible with this platform.
     * </ul>
     * <p>
     * When {@code allowUnknownCodenames} is true, any codename that is not known (presumed to be
     * a codename announced after the build of the current device) is allowed and this method will
     * return {@link Build.VERSION_CODES#CUR_DEVELOPMENT}.
     *
     * @param targetVers            targetSdkVersion number, if specified in the application
     *                              manifest, or 0 otherwise
     * @param targetCode            targetSdkVersion code, if specified in the application manifest,
     *                              or {@code null} otherwise
     * @param platformSdkCodenames  array of allowed pre-release SDK codenames for this platform
     * @param allowUnknownCodenames allow unknown codenames, if true this method will accept unknown
     *                              (presumed to be future) codenames
     * @return the targetSdkVersion to use at runtime if successful
     */
    public static ParseResult<Integer> computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
            @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
            @NonNull ParseInput input, boolean allowUnknownCodenames) {
        // If it's a release SDK, return the version number unmodified.
        if (targetCode == null) {
            return input.success(targetVers);
        }

        // If it's a pre-release SDK and the codename matches this platform, it
        // definitely targets this SDK.
        if (matchTargetCode(platformSdkCodenames, targetCode)) {
            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
        }

        // STOPSHIP: hack for the pre-release SDK
        if (platformSdkCodenames.length == 0
                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
                        targetCode)) {
            Slog.w(TAG, "Parsed package requires development platform " + targetCode
                    + ", returning current version " + Build.VERSION.SDK_INT);
            return input.success(Build.VERSION.SDK_INT);
        }

        try {
            if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
                return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
            }
        } catch (IllegalArgumentException e) {
            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
        }

        // Otherwise, we're looking at an incompatible pre-release SDK.
        if (platformSdkCodenames.length > 0) {
            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
                    "Requires development platform " + targetCode
                            + " (current platform is any of "
                            + Arrays.toString(platformSdkCodenames) + ")");
        } else {
            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
                    "Requires development platform " + targetCode
                            + " but this is a release platform.");
        }
    }

    /**
     * Computes the maxSdkVersion. If the package is not compatible with this platform, populates
     * {@code outError[0]} with an error message.
     * <p>
     * {@code maxVers} is compared against {@code platformSdkVersion}. If {@code maxVers} is less
     * than the {@code platformSdkVersion} then populates {@code outError[0]} with an error message.
     * Otherwise, it returns {@code maxVers} unmodified.
     *
     * @param maxVers maxSdkVersion number, if specified in the application manifest, or {@code
     *                Integer.MAX_VALUE} otherwise
     * @param platformSdkVersion   platform SDK version number, typically Build.VERSION.SDK_INT
     * @return the maxSdkVersion that was recognised or an error if the condition is not satisfied
     */
    public static ParseResult<Integer> computeMaxSdkVersion(@IntRange(from = 0) int maxVers,
            @IntRange(from = 1) int platformSdkVersion, @NonNull ParseInput input) {
        if (platformSdkVersion > maxVers) {
            return input.error(PackageManager.INSTALL_FAILED_NEWER_SDK,
                    "Requires max SDK version " + maxVers + " but is "
                            + platformSdkVersion);
        } else {
            return input.success(maxVers);
        }
    }

    /**
     * Matches a given {@code targetCode} against a set of release codeNames. Target codes can
     * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form {@code
     * [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}).
     */
    private static boolean matchTargetCode(@NonNull String[] codeNames,
            @NonNull String targetCode) {
        final String targetCodeName;
        final int targetCodeIdx = targetCode.indexOf('.');
        if (targetCodeIdx == -1) {
            targetCodeName = targetCode;
        } else {
            targetCodeName = targetCode.substring(0, targetCodeIdx);
        }
        return ArrayUtils.contains(codeNames, targetCodeName);
    }
}
