/*
 * Copyright (C) 2020 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.integrity;

import static com.android.internal.util.Preconditions.checkArgument;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.annotations.VisibleForTesting;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * Represents a simple formula consisting of an app install metadata field and a value.
 *
 * <p>Instances of this class are immutable.
 *
 * @hide
 */
@VisibleForTesting
public abstract class AtomicFormula extends IntegrityFormula {

    /** @hide */
    @IntDef(
            value = {
                    PACKAGE_NAME,
                    APP_CERTIFICATE,
                    INSTALLER_NAME,
                    INSTALLER_CERTIFICATE,
                    VERSION_CODE,
                    PRE_INSTALLED,
            })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Key {
    }

    /** @hide */
    @IntDef(value = {EQ, GT, GTE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Operator {
    }

    /**
     * Package name of the app.
     *
     * <p>Can only be used in {@link StringAtomicFormula}.
     */
    public static final int PACKAGE_NAME = 0;

    /**
     * SHA-256 of the app certificate of the app.
     *
     * <p>Can only be used in {@link StringAtomicFormula}.
     */
    public static final int APP_CERTIFICATE = 1;

    /**
     * Package name of the installer. Will be empty string if installed by the system (e.g., adb).
     *
     * <p>Can only be used in {@link StringAtomicFormula}.
     */
    public static final int INSTALLER_NAME = 2;

    /**
     * SHA-256 of the cert of the installer. Will be empty string if installed by the system (e.g.,
     * adb).
     *
     * <p>Can only be used in {@link StringAtomicFormula}.
     */
    public static final int INSTALLER_CERTIFICATE = 3;

    /**
     * Version code of the app.
     *
     * <p>Can only be used in {@link LongAtomicFormula}.
     */
    public static final int VERSION_CODE = 4;

    /**
     * If the app is pre-installed on the device.
     *
     * <p>Can only be used in {@link BooleanAtomicFormula}.
     */
    public static final int PRE_INSTALLED = 5;

    public static final int EQ = 0;
    public static final int GT = 1;
    public static final int GTE = 2;

    private final @Key int mKey;

    public AtomicFormula(@Key int key) {
        checkArgument(isValidKey(key), String.format("Unknown key: %d", key));
        mKey = key;
    }

    /** An {@link AtomicFormula} with an key and long value. */
    public static final class LongAtomicFormula extends AtomicFormula implements Parcelable {
        private final Long mValue;
        private final @Operator Integer mOperator;

        /**
         * Constructs an empty {@link LongAtomicFormula}. This should only be used as a base.
         *
         * <p>This formula will always return false.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with long value
         */
        public LongAtomicFormula(@Key int key) {
            super(key);
            checkArgument(
                    key == VERSION_CODE,
                    String.format(
                            "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
            mValue = null;
            mOperator = null;
        }

        /**
         * Constructs a new {@link LongAtomicFormula}.
         *
         * <p>This formula will hold if and only if the corresponding information of an install
         * specified by {@code key} is of the correct relationship to {@code value} as specified by
         * {@code operator}.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with long value
         */
        public LongAtomicFormula(@Key int key, @Operator int operator, long value) {
            super(key);
            checkArgument(
                    key == VERSION_CODE,
                    String.format(
                            "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
            checkArgument(
                    isValidOperator(operator), String.format("Unknown operator: %d", operator));
            mOperator = operator;
            mValue = value;
        }

        LongAtomicFormula(Parcel in) {
            super(in.readInt());
            mValue = in.readLong();
            mOperator = in.readInt();
        }

        @NonNull
        public static final Creator<LongAtomicFormula> CREATOR =
                new Creator<LongAtomicFormula>() {
                    @Override
                    public LongAtomicFormula createFromParcel(Parcel in) {
                        return new LongAtomicFormula(in);
                    }

                    @Override
                    public LongAtomicFormula[] newArray(int size) {
                        return new LongAtomicFormula[size];
                    }
                };

        @Override
        public int getTag() {
            return IntegrityFormula.LONG_ATOMIC_FORMULA_TAG;
        }

        @Override
        public boolean matches(AppInstallMetadata appInstallMetadata) {
            if (mValue == null || mOperator == null) {
                return false;
            }

            long metadataValue = getLongMetadataValue(appInstallMetadata, getKey());
            switch (mOperator) {
                case EQ:
                    return metadataValue == mValue;
                case GT:
                    return metadataValue > mValue;
                case GTE:
                    return metadataValue >= mValue;
                default:
                    throw new IllegalArgumentException(
                            String.format("Unexpected operator %d", mOperator));
            }
        }

        @Override
        public boolean isAppCertificateFormula() {
            return false;
        }

        @Override
        public boolean isInstallerFormula() {
            return false;
        }

        @Override
        public String toString() {
            if (mValue == null || mOperator == null) {
                return String.format("(%s)", keyToString(getKey()));
            }
            return String.format(
                    "(%s %s %s)", keyToString(getKey()), operatorToString(mOperator), mValue);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            LongAtomicFormula that = (LongAtomicFormula) o;
            return getKey() == that.getKey()
                    && mValue == that.mValue
                    && mOperator == that.mOperator;
        }

        @Override
        public int hashCode() {
            return Objects.hash(getKey(), mOperator, mValue);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            if (mValue == null || mOperator == null) {
                throw new IllegalStateException("Cannot write an empty LongAtomicFormula.");
            }
            dest.writeInt(getKey());
            dest.writeLong(mValue);
            dest.writeInt(mOperator);
        }

        public Long getValue() {
            return mValue;
        }

        public Integer getOperator() {
            return mOperator;
        }

        private static boolean isValidOperator(int operator) {
            return operator == EQ
                    || operator == GT
                    || operator == GTE;
        }

        private static long getLongMetadataValue(AppInstallMetadata appInstallMetadata, int key) {
            switch (key) {
                case AtomicFormula.VERSION_CODE:
                    return appInstallMetadata.getVersionCode();
                default:
                    throw new IllegalStateException("Unexpected key in IntAtomicFormula" + key);
            }
        }
    }

    /** An {@link AtomicFormula} with a key and string value. */
    public static final class StringAtomicFormula extends AtomicFormula implements Parcelable {
        private final String mValue;
        // Indicates whether the value is the actual value or the hashed value.
        private final Boolean mIsHashedValue;

        /**
         * Constructs an empty {@link StringAtomicFormula}. This should only be used as a base.
         *
         * <p>An empty formula will always match to false.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with string value
         */
        public StringAtomicFormula(@Key int key) {
            super(key);
            checkArgument(
                    key == PACKAGE_NAME
                            || key == APP_CERTIFICATE
                            || key == INSTALLER_CERTIFICATE
                            || key == INSTALLER_NAME,
                    String.format(
                            "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
            mValue = null;
            mIsHashedValue = null;
        }

        /**
         * Constructs a new {@link StringAtomicFormula}.
         *
         * <p>This formula will hold if and only if the corresponding information of an install
         * specified by {@code key} equals {@code value}.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with string value
         */
        public StringAtomicFormula(@Key int key, @NonNull String value, boolean isHashed) {
            super(key);
            checkArgument(
                    key == PACKAGE_NAME
                            || key == APP_CERTIFICATE
                            || key == INSTALLER_CERTIFICATE
                            || key == INSTALLER_NAME,
                    String.format(
                            "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
            mValue = value;
            mIsHashedValue = isHashed;
        }

        /**
         * Constructs a new {@link StringAtomicFormula} together with handling the necessary
         * hashing for the given key.
         *
         * <p> The value will be hashed with SHA256 and the hex digest will be computed; for
         * all cases except when the key is PACKAGE_NAME or INSTALLER_NAME and the value
         * is less than 33 characters.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with string value.
         */
        public StringAtomicFormula(@Key int key, @NonNull String value) {
            super(key);
            checkArgument(
                    key == PACKAGE_NAME
                            || key == APP_CERTIFICATE
                            || key == INSTALLER_CERTIFICATE
                            || key == INSTALLER_NAME,
                    String.format(
                            "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
            mValue = hashValue(key, value);
            mIsHashedValue = !mValue.equals(value);
        }

        StringAtomicFormula(Parcel in) {
            super(in.readInt());
            mValue = in.readStringNoHelper();
            mIsHashedValue = in.readByte() != 0;
        }

        @NonNull
        public static final Creator<StringAtomicFormula> CREATOR =
                new Creator<StringAtomicFormula>() {
                    @Override
                    public StringAtomicFormula createFromParcel(Parcel in) {
                        return new StringAtomicFormula(in);
                    }

                    @Override
                    public StringAtomicFormula[] newArray(int size) {
                        return new StringAtomicFormula[size];
                    }
                };

        @Override
        public int getTag() {
            return IntegrityFormula.STRING_ATOMIC_FORMULA_TAG;
        }

        @Override
        public boolean matches(AppInstallMetadata appInstallMetadata) {
            if (mValue == null || mIsHashedValue == null) {
                return false;
            }
            return getStringMetadataValue(appInstallMetadata, getKey()).equals(mValue);
        }

        @Override
        public boolean isAppCertificateFormula() {
            return getKey() == APP_CERTIFICATE;
        }

        @Override
        public boolean isInstallerFormula() {
            return getKey() == INSTALLER_NAME || getKey() == INSTALLER_CERTIFICATE;
        }

        @Override
        public String toString() {
            if (mValue == null || mIsHashedValue == null) {
                return String.format("(%s)", keyToString(getKey()));
            }
            return String.format("(%s %s %s)", keyToString(getKey()), operatorToString(EQ), mValue);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            StringAtomicFormula that = (StringAtomicFormula) o;
            return getKey() == that.getKey() && Objects.equals(mValue, that.mValue);
        }

        @Override
        public int hashCode() {
            return Objects.hash(getKey(), mValue);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            if (mValue == null || mIsHashedValue == null) {
                throw new IllegalStateException("Cannot write an empty StringAtomicFormula.");
            }
            dest.writeInt(getKey());
            dest.writeStringNoHelper(mValue);
            dest.writeByte((byte) (mIsHashedValue ? 1 : 0));
        }

        public String getValue() {
            return mValue;
        }

        public Boolean getIsHashedValue() {
            return mIsHashedValue;
        }

        private static String getStringMetadataValue(
                AppInstallMetadata appInstallMetadata, int key) {
            switch (key) {
                case AtomicFormula.PACKAGE_NAME:
                    return appInstallMetadata.getPackageName();
                case AtomicFormula.APP_CERTIFICATE:
                    return appInstallMetadata.getAppCertificate();
                case AtomicFormula.INSTALLER_CERTIFICATE:
                    return appInstallMetadata.getInstallerCertificate();
                case AtomicFormula.INSTALLER_NAME:
                    return appInstallMetadata.getInstallerName();
                default:
                    throw new IllegalStateException(
                            "Unexpected key in StringAtomicFormula: " + key);
            }
        }

        private static String hashValue(@Key int key, String value) {
            // Hash the string value unless it is a PACKAGE_NAME or INSTALLER_NAME and the value is
            // less than 33 characters.
            if (value.length() <= 32) {
                if (key == PACKAGE_NAME || key == INSTALLER_NAME) {
                    return value;
                }
            }
            return hash(value);
        }

        private static String hash(String value) {
            try {
                MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
                byte[] hashBytes = messageDigest.digest(value.getBytes(StandardCharsets.UTF_8));
                return IntegrityUtils.getHexDigest(hashBytes);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("SHA-256 algorithm not found", e);
            }
        }
    }

    /** An {@link AtomicFormula} with a key and boolean value. */
    public static final class BooleanAtomicFormula extends AtomicFormula implements Parcelable {
        private final Boolean mValue;

        /**
         * Constructs an empty {@link BooleanAtomicFormula}. This should only be used as a base.
         *
         * <p>An empty formula will always match to false.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with boolean value
         */
        public BooleanAtomicFormula(@Key int key) {
            super(key);
            checkArgument(
                    key == PRE_INSTALLED,
                    String.format(
                            "Key %s cannot be used with BooleanAtomicFormula", keyToString(key)));
            mValue = null;
        }

        /**
         * Constructs a new {@link BooleanAtomicFormula}.
         *
         * <p>This formula will hold if and only if the corresponding information of an install
         * specified by {@code key} equals {@code value}.
         *
         * @throws IllegalArgumentException if {@code key} cannot be used with boolean value
         */
        public BooleanAtomicFormula(@Key int key, boolean value) {
            super(key);
            checkArgument(
                    key == PRE_INSTALLED,
                    String.format(
                            "Key %s cannot be used with BooleanAtomicFormula", keyToString(key)));
            mValue = value;
        }

        BooleanAtomicFormula(Parcel in) {
            super(in.readInt());
            mValue = in.readByte() != 0;
        }

        @NonNull
        public static final Creator<BooleanAtomicFormula> CREATOR =
                new Creator<BooleanAtomicFormula>() {
                    @Override
                    public BooleanAtomicFormula createFromParcel(Parcel in) {
                        return new BooleanAtomicFormula(in);
                    }

                    @Override
                    public BooleanAtomicFormula[] newArray(int size) {
                        return new BooleanAtomicFormula[size];
                    }
                };

        @Override
        public int getTag() {
            return IntegrityFormula.BOOLEAN_ATOMIC_FORMULA_TAG;
        }

        @Override
        public boolean matches(AppInstallMetadata appInstallMetadata) {
            if (mValue == null) {
                return false;
            }
            return getBooleanMetadataValue(appInstallMetadata, getKey()) == mValue;
        }

        @Override
        public boolean isAppCertificateFormula() {
            return false;
        }

        @Override
        public boolean isInstallerFormula() {
            return false;
        }

        @Override
        public String toString() {
            if (mValue == null) {
                return String.format("(%s)", keyToString(getKey()));
            }
            return String.format("(%s %s %s)", keyToString(getKey()), operatorToString(EQ), mValue);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            BooleanAtomicFormula that = (BooleanAtomicFormula) o;
            return getKey() == that.getKey() && mValue == that.mValue;
        }

        @Override
        public int hashCode() {
            return Objects.hash(getKey(), mValue);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            if (mValue == null) {
                throw new IllegalStateException("Cannot write an empty BooleanAtomicFormula.");
            }
            dest.writeInt(getKey());
            dest.writeByte((byte) (mValue ? 1 : 0));
        }

        public Boolean getValue() {
            return mValue;
        }

        private static boolean getBooleanMetadataValue(
                AppInstallMetadata appInstallMetadata, int key) {
            switch (key) {
                case AtomicFormula.PRE_INSTALLED:
                    return appInstallMetadata.isPreInstalled();
                default:
                    throw new IllegalStateException(
                            "Unexpected key in BooleanAtomicFormula: " + key);
            }
        }
    }

    public int getKey() {
        return mKey;
    }

    static String keyToString(int key) {
        switch (key) {
            case PACKAGE_NAME:
                return "PACKAGE_NAME";
            case APP_CERTIFICATE:
                return "APP_CERTIFICATE";
            case VERSION_CODE:
                return "VERSION_CODE";
            case INSTALLER_NAME:
                return "INSTALLER_NAME";
            case INSTALLER_CERTIFICATE:
                return "INSTALLER_CERTIFICATE";
            case PRE_INSTALLED:
                return "PRE_INSTALLED";
            default:
                throw new IllegalArgumentException("Unknown key " + key);
        }
    }

    static String operatorToString(int op) {
        switch (op) {
            case EQ:
                return "EQ";
            case GT:
                return "GT";
            case GTE:
                return "GTE";
            default:
                throw new IllegalArgumentException("Unknown operator " + op);
        }
    }

    private static boolean isValidKey(int key) {
        return key == PACKAGE_NAME
                || key == APP_CERTIFICATE
                || key == VERSION_CODE
                || key == INSTALLER_NAME
                || key == INSTALLER_CERTIFICATE
                || key == PRE_INSTALLED;
    }
}
