/*
 * Copyright (C) 2012 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.security.keystore;

import android.security.Credentials;
import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.KeyStoreParameter;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.security.keystore.SecureKeyImportUnavailableException;
import android.security.keystore.WrappedKeyEntry;
import android.util.Log;

import libcore.util.EmptyArray;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStore.Entry;
import java.security.KeyStore.LoadStoreParameter;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStore.SecretKeyEntry;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.crypto.SecretKey;

/**
 * A java.security.KeyStore interface for the Android KeyStore. An instance of
 * it can be created via the {@link java.security.KeyStore#getInstance(String)
 * KeyStore.getInstance("AndroidKeyStore")} interface. This returns a
 * java.security.KeyStore backed by this "AndroidKeyStore" implementation.
 * <p>
 * This is built on top of Android's keystore daemon. The convention of alias
 * use is:
 * <p>
 * PrivateKeyEntry will have a Credentials.USER_PRIVATE_KEY as the private key,
 * Credentials.USER_CERTIFICATE as the first certificate in the chain (the one
 * that corresponds to the private key), and then a Credentials.CA_CERTIFICATE
 * entry which will have the rest of the chain concatenated in BER format.
 * <p>
 * TrustedCertificateEntry will just have a Credentials.CA_CERTIFICATE entry
 * with a single certificate.
 *
 * @hide
 */
public class AndroidKeyStoreSpi extends KeyStoreSpi {
    public static final String NAME = "AndroidKeyStore";

    private KeyStore mKeyStore;
    private int mUid = KeyStore.UID_SELF;

    @Override
    public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
            UnrecoverableKeyException {
        String userKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
        AndroidKeyStoreKey key;
        if (!mKeyStore.contains(userKeyAlias, mUid)) {
            // try legacy prefix for backward compatibility
            userKeyAlias = Credentials.USER_SECRET_KEY + alias;
            if (!mKeyStore.contains(userKeyAlias, mUid)) return null;
        }
        try {
            key = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore,
                                                                             userKeyAlias,
                                                                             mUid);
        } catch (KeyPermanentlyInvalidatedException e) {
            throw new UnrecoverableKeyException(e.getMessage());
        }
        return key;
    }

    @Override
    public Certificate[] engineGetCertificateChain(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        }

        final X509Certificate leaf = (X509Certificate) engineGetCertificate(alias);
        if (leaf == null) {
            return null;
        }

        final Certificate[] caList;

        // Suppress the key not found warning for this call. It seems that this error is exclusively
        // being thrown when there is a self signed certificate chain, so when the keystore service
        // attempts to query for the CA details, it obviously fails to find them and returns a
        // key not found exception. This is WAI, and throwing a stack trace here can be very
        // misleading since the trace is not clear.
        final byte[] caBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias,
                                             mUid,
                                             true /* suppressKeyNotFoundWarning */);
        if (caBytes != null) {
            final Collection<X509Certificate> caChain = toCertificates(caBytes);

            caList = new Certificate[caChain.size() + 1];

            final Iterator<X509Certificate> it = caChain.iterator();
            int i = 1;
            while (it.hasNext()) {
                caList[i++] = it.next();
            }
        } else {
            caList = new Certificate[1];
        }

        caList[0] = leaf;

        return caList;
    }

    @Override
    public Certificate engineGetCertificate(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        }

        byte[] encodedCert = mKeyStore.get(Credentials.USER_CERTIFICATE + alias, mUid);
        if (encodedCert != null) {
            return getCertificateForPrivateKeyEntry(alias, encodedCert);
        }

        encodedCert = mKeyStore.get(Credentials.CA_CERTIFICATE + alias, mUid);
        if (encodedCert != null) {
            return getCertificateForTrustedCertificateEntry(encodedCert);
        }

        // This entry/alias does not contain a certificate.
        return null;
    }

    private Certificate getCertificateForTrustedCertificateEntry(byte[] encodedCert) {
        // For this certificate there shouldn't be a private key in this KeyStore entry. Thus,
        // there's no need to wrap this certificate as opposed to the certificate associated with
        // a private key entry.
        return toCertificate(encodedCert);
    }

    private Certificate getCertificateForPrivateKeyEntry(String alias, byte[] encodedCert) {
        // All crypto algorithms offered by Android Keystore for its private keys must also
        // be offered for the corresponding public keys stored in the Android Keystore. The
        // complication is that the underlying keystore service operates only on full key pairs,
        // rather than just public keys or private keys. As a result, Android Keystore-backed
        // crypto can only be offered for public keys for which keystore contains the
        // corresponding private key. This is not the case for certificate-only entries (e.g.,
        // trusted certificates).
        //
        // getCertificate().getPublicKey() is the only way to obtain the public key
        // corresponding to the private key stored in the KeyStore. Thus, we need to make sure
        // that the returned public key points to the underlying key pair / private key
        // when available.

        X509Certificate cert = toCertificate(encodedCert);
        if (cert == null) {
            // Failed to parse the certificate.
            return null;
        }

        String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
        if (mKeyStore.contains(privateKeyAlias, mUid)) {
            // As expected, keystore contains the private key corresponding to this public key. Wrap
            // the certificate so that its getPublicKey method returns an Android Keystore
            // PublicKey. This key will delegate crypto operations involving this public key to
            // Android Keystore when higher-priority providers do not offer these crypto
            // operations for this key.
            return wrapIntoKeyStoreCertificate(privateKeyAlias, mUid, cert);
        } else {
            // This KeyStore entry/alias is supposed to contain the private key corresponding to
            // the public key in this certificate, but it does not for some reason. It's probably a
            // bug. Let other providers handle crypto operations involving the public key returned
            // by this certificate's getPublicKey.
            return cert;
        }
    }

    /**
     * Wraps the provided cerificate into {@link KeyStoreX509Certificate} so that the public key
     * returned by the certificate contains information about the alias of the private key in
     * keystore. This is needed so that Android Keystore crypto operations using public keys can
     * find out which key alias to use. These operations cannot work without an alias.
     */
    private static KeyStoreX509Certificate wrapIntoKeyStoreCertificate(
            String privateKeyAlias, int uid, X509Certificate certificate) {
        return (certificate != null)
                ? new KeyStoreX509Certificate(privateKeyAlias, uid, certificate) : null;
    }

    private static X509Certificate toCertificate(byte[] bytes) {
        try {
            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            return (X509Certificate) certFactory.generateCertificate(
                    new ByteArrayInputStream(bytes));
        } catch (CertificateException e) {
            Log.w(NAME, "Couldn't parse certificate in keystore", e);
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    private static Collection<X509Certificate> toCertificates(byte[] bytes) {
        try {
            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            return (Collection<X509Certificate>) certFactory.generateCertificates(
                            new ByteArrayInputStream(bytes));
        } catch (CertificateException e) {
            Log.w(NAME, "Couldn't parse certificates in keystore", e);
            return new ArrayList<X509Certificate>();
        }
    }

    private Date getModificationDate(String alias) {
        final long epochMillis = mKeyStore.getmtime(alias, mUid);
        if (epochMillis == -1L) {
            return null;
        }

        return new Date(epochMillis);
    }

    @Override
    public Date engineGetCreationDate(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        }

        Date d = getModificationDate(Credentials.USER_PRIVATE_KEY + alias);
        if (d != null) {
            return d;
        }

        d = getModificationDate(Credentials.USER_SECRET_KEY + alias);
        if (d != null) {
            return d;
        }

        d = getModificationDate(Credentials.USER_CERTIFICATE + alias);
        if (d != null) {
            return d;
        }

        return getModificationDate(Credentials.CA_CERTIFICATE + alias);
    }

    @Override
    public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain)
            throws KeyStoreException {
        if ((password != null) && (password.length > 0)) {
            throw new KeyStoreException("entries cannot be protected with passwords");
        }

        if (key instanceof PrivateKey) {
            setPrivateKeyEntry(alias, (PrivateKey) key, chain, null);
        } else if (key instanceof SecretKey) {
            setSecretKeyEntry(alias, (SecretKey) key, null);
        } else {
            throw new KeyStoreException("Only PrivateKey and SecretKey are supported");
        }
    }

    private static KeyProtection getLegacyKeyProtectionParameter(PrivateKey key)
            throws KeyStoreException {
        String keyAlgorithm = key.getAlgorithm();
        KeyProtection.Builder specBuilder;
        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
            specBuilder =
                    new KeyProtection.Builder(
                            KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
            // Authorized to be used with any digest (including no digest).
            // MD5 was never offered for Android Keystore for ECDSA.
            specBuilder.setDigests(
                    KeyProperties.DIGEST_NONE,
                    KeyProperties.DIGEST_SHA1,
                    KeyProperties.DIGEST_SHA224,
                    KeyProperties.DIGEST_SHA256,
                    KeyProperties.DIGEST_SHA384,
                    KeyProperties.DIGEST_SHA512);
        } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
            specBuilder =
                    new KeyProtection.Builder(
                            KeyProperties.PURPOSE_ENCRYPT
                            | KeyProperties.PURPOSE_DECRYPT
                            | KeyProperties.PURPOSE_SIGN
                            | KeyProperties.PURPOSE_VERIFY);
            // Authorized to be used with any digest (including no digest).
            specBuilder.setDigests(
                    KeyProperties.DIGEST_NONE,
                    KeyProperties.DIGEST_MD5,
                    KeyProperties.DIGEST_SHA1,
                    KeyProperties.DIGEST_SHA224,
                    KeyProperties.DIGEST_SHA256,
                    KeyProperties.DIGEST_SHA384,
                    KeyProperties.DIGEST_SHA512);
            // Authorized to be used with any encryption and signature padding
            // schemes (including no padding).
            specBuilder.setEncryptionPaddings(
                    KeyProperties.ENCRYPTION_PADDING_NONE,
                    KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
                    KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
            specBuilder.setSignaturePaddings(
                    KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
                    KeyProperties.SIGNATURE_PADDING_RSA_PSS);
            // Disable randomized encryption requirement to support encryption
            // padding NONE above.
            specBuilder.setRandomizedEncryptionRequired(false);
        } else {
            throw new KeyStoreException("Unsupported key algorithm: " + keyAlgorithm);
        }
        specBuilder.setUserAuthenticationRequired(false);

        return specBuilder.build();
    }

    private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain,
            java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
        int flags = 0;
        KeyProtection spec;
        if (param == null) {
            spec = getLegacyKeyProtectionParameter(key);
        } else if (param instanceof KeyStoreParameter) {
            spec = getLegacyKeyProtectionParameter(key);
            KeyStoreParameter legacySpec = (KeyStoreParameter) param;
            if (legacySpec.isEncryptionRequired()) {
                flags = KeyStore.FLAG_ENCRYPTED;
            }
        } else if (param instanceof KeyProtection) {
            spec = (KeyProtection) param;
            if (spec.isCriticalToDeviceEncryption()) {
                flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
            }

            if (spec.isStrongBoxBacked()) {
                flags |= KeyStore.FLAG_STRONGBOX;
            }
        } else {
            throw new KeyStoreException(
                    "Unsupported protection parameter class:" + param.getClass().getName()
                    + ". Supported: " + KeyProtection.class.getName() + ", "
                    + KeyStoreParameter.class.getName());
        }

        // Make sure the chain exists since this is a PrivateKey
        if ((chain == null) || (chain.length == 0)) {
            throw new KeyStoreException("Must supply at least one Certificate with PrivateKey");
        }

        // Do chain type checking.
        X509Certificate[] x509chain = new X509Certificate[chain.length];
        for (int i = 0; i < chain.length; i++) {
            if (!"X.509".equals(chain[i].getType())) {
                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
                        + i);
            }

            if (!(chain[i] instanceof X509Certificate)) {
                throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #"
                        + i);
            }

            x509chain[i] = (X509Certificate) chain[i];
        }

        final byte[] userCertBytes;
        try {
            userCertBytes = x509chain[0].getEncoded();
        } catch (CertificateEncodingException e) {
            throw new KeyStoreException("Failed to encode certificate #0", e);
        }

        /*
         * If we have a chain, store it in the CA certificate slot for this
         * alias as concatenated DER-encoded certificates. These can be
         * deserialized by {@link CertificateFactory#generateCertificates}.
         */
        final byte[] chainBytes;
        if (chain.length > 1) {
            /*
             * The chain is passed in as {user_cert, ca_cert_1, ca_cert_2, ...}
             * so we only need the certificates starting at index 1.
             */
            final byte[][] certsBytes = new byte[x509chain.length - 1][];
            int totalCertLength = 0;
            for (int i = 0; i < certsBytes.length; i++) {
                try {
                    certsBytes[i] = x509chain[i + 1].getEncoded();
                    totalCertLength += certsBytes[i].length;
                } catch (CertificateEncodingException e) {
                    throw new KeyStoreException("Failed to encode certificate #" + i, e);
                }
            }

            /*
             * Serialize this into one byte array so we can later call
             * CertificateFactory#generateCertificates to recover them.
             */
            chainBytes = new byte[totalCertLength];
            int outputOffset = 0;
            for (int i = 0; i < certsBytes.length; i++) {
                final int certLength = certsBytes[i].length;
                System.arraycopy(certsBytes[i], 0, chainBytes, outputOffset, certLength);
                outputOffset += certLength;
                certsBytes[i] = null;
            }
        } else {
            chainBytes = null;
        }

        final String pkeyAlias;
        if (key instanceof AndroidKeyStorePrivateKey) {
            pkeyAlias = ((AndroidKeyStoreKey) key).getAlias();
        } else {
            pkeyAlias = null;
        }

        byte[] pkcs8EncodedPrivateKeyBytes;
        KeymasterArguments importArgs;
        final boolean shouldReplacePrivateKey;
        if (pkeyAlias != null && pkeyAlias.startsWith(Credentials.USER_PRIVATE_KEY)) {
            final String keySubalias = pkeyAlias.substring(Credentials.USER_PRIVATE_KEY.length());
            if (!alias.equals(keySubalias)) {
                throw new KeyStoreException("Can only replace keys with same alias: " + alias
                        + " != " + keySubalias);
            }
            shouldReplacePrivateKey = false;
            importArgs = null;
            pkcs8EncodedPrivateKeyBytes = null;
        } else {
            shouldReplacePrivateKey = true;
            // Make sure the PrivateKey format is the one we support.
            final String keyFormat = key.getFormat();
            if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
                throw new KeyStoreException(
                        "Unsupported private key export format: " + keyFormat
                        + ". Only private keys which export their key material in PKCS#8 format are"
                        + " supported.");
            }

            // Make sure we can actually encode the key.
            pkcs8EncodedPrivateKeyBytes = key.getEncoded();
            if (pkcs8EncodedPrivateKeyBytes == null) {
                throw new KeyStoreException("Private key did not export any key material");
            }

            importArgs = new KeymasterArguments();
            try {
                importArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
                        KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
                                key.getAlgorithm()));
                @KeyProperties.PurposeEnum int purposes = spec.getPurposes();
                importArgs.addEnums(KeymasterDefs.KM_TAG_PURPOSE,
                        KeyProperties.Purpose.allToKeymaster(purposes));
                if (spec.isDigestsSpecified()) {
                    importArgs.addEnums(KeymasterDefs.KM_TAG_DIGEST,
                            KeyProperties.Digest.allToKeymaster(spec.getDigests()));
                }

                importArgs.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE,
                        KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()));
                int[] keymasterEncryptionPaddings =
                        KeyProperties.EncryptionPadding.allToKeymaster(
                                spec.getEncryptionPaddings());
                if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
                        && (spec.isRandomizedEncryptionRequired())) {
                    for (int keymasterPadding : keymasterEncryptionPaddings) {
                        if (!KeymasterUtils
                                .isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(
                                        keymasterPadding)) {
                            throw new KeyStoreException(
                                    "Randomized encryption (IND-CPA) required but is violated by"
                                    + " encryption padding mode: "
                                    + KeyProperties.EncryptionPadding.fromKeymaster(
                                            keymasterPadding)
                                    + ". See KeyProtection documentation.");
                        }
                    }
                }
                importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
                importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING,
                        KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
                KeymasterUtils.addUserAuthArgs(importArgs, spec);
                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
                        spec.getKeyValidityStart());
                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
                        spec.getKeyValidityForOriginationEnd());
                importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
                        spec.getKeyValidityForConsumptionEnd());
            } catch (IllegalArgumentException | IllegalStateException e) {
                throw new KeyStoreException(e);
            }
        }


        boolean success = false;
        try {
            // Store the private key, if necessary
            if (shouldReplacePrivateKey) {
                // Delete the stored private key and any related entries before importing the
                // provided key
                Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
                KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
                int errorCode = mKeyStore.importKey(
                        Credentials.USER_PRIVATE_KEY + alias,
                        importArgs,
                        KeymasterDefs.KM_KEY_FORMAT_PKCS8,
                        pkcs8EncodedPrivateKeyBytes,
                        mUid,
                        flags,
                        resultingKeyCharacteristics);
                if (errorCode != KeyStore.NO_ERROR) {
                    throw new KeyStoreException("Failed to store private key",
                            KeyStore.getKeyStoreException(errorCode));
                }
            } else {
                // Keep the stored private key around -- delete all other entry types
                Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
                Credentials.deleteLegacyKeyForAlias(mKeyStore, alias, mUid);
            }

            // Store the leaf certificate
            int errorCode = mKeyStore.insert(Credentials.USER_CERTIFICATE + alias, userCertBytes,
                    mUid, flags);
            if (errorCode != KeyStore.NO_ERROR) {
                throw new KeyStoreException("Failed to store certificate #0",
                        KeyStore.getKeyStoreException(errorCode));
            }

            // Store the certificate chain
            errorCode = mKeyStore.insert(Credentials.CA_CERTIFICATE + alias, chainBytes,
                    mUid, flags);
            if (errorCode != KeyStore.NO_ERROR) {
                throw new KeyStoreException("Failed to store certificate chain",
                        KeyStore.getKeyStoreException(errorCode));
            }
            success = true;
        } finally {
            if (!success) {
                if (shouldReplacePrivateKey) {
                    Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
                } else {
                    Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
                    Credentials.deleteLegacyKeyForAlias(mKeyStore, alias, mUid);
                }
            }
        }
    }

    private void setSecretKeyEntry(String entryAlias, SecretKey key,
            java.security.KeyStore.ProtectionParameter param)
            throws KeyStoreException {
        if ((param != null) && (!(param instanceof KeyProtection))) {
            throw new KeyStoreException(
                    "Unsupported protection parameter class: " + param.getClass().getName()
                    + ". Supported: " + KeyProtection.class.getName());
        }
        KeyProtection params = (KeyProtection) param;

        if (key instanceof AndroidKeyStoreSecretKey) {
            // KeyStore-backed secret key. It cannot be duplicated into another entry and cannot
            // overwrite its own entry.
            String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias();
            if (keyAliasInKeystore == null) {
                throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
            }
            String keyAliasPrefix = Credentials.USER_PRIVATE_KEY;
            if (!keyAliasInKeystore.startsWith(keyAliasPrefix)) {
                // try legacy prefix
                keyAliasPrefix = Credentials.USER_SECRET_KEY;
                if (!keyAliasInKeystore.startsWith(keyAliasPrefix)) {
                    throw new KeyStoreException("KeyStore-backed secret key has invalid alias: "
                            + keyAliasInKeystore);
                }
            }
            String keyEntryAlias =
                    keyAliasInKeystore.substring(keyAliasPrefix.length());
            if (!entryAlias.equals(keyEntryAlias)) {
                throw new KeyStoreException("Can only replace KeyStore-backed keys with same"
                        + " alias: " + entryAlias + " != " + keyEntryAlias);
            }
            // This is the entry where this key is already stored. No need to do anything.
            if (params != null) {
                throw new KeyStoreException("Modifying KeyStore-backed key using protection"
                        + " parameters not supported");
            }
            return;
        }

        if (params == null) {
            throw new KeyStoreException(
                    "Protection parameters must be specified when importing a symmetric key");
        }

        // Not a KeyStore-backed secret key -- import its key material into keystore.
        String keyExportFormat = key.getFormat();
        if (keyExportFormat == null) {
            throw new KeyStoreException(
                    "Only secret keys that export their key material are supported");
        } else if (!"RAW".equals(keyExportFormat)) {
            throw new KeyStoreException(
                    "Unsupported secret key material export format: " + keyExportFormat);
        }
        byte[] keyMaterial = key.getEncoded();
        if (keyMaterial == null) {
            throw new KeyStoreException("Key did not export its key material despite supporting"
                    + " RAW format export");
        }

        KeymasterArguments args = new KeymasterArguments();
        try {
            int keymasterAlgorithm =
                    KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(key.getAlgorithm());
            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);

            int[] keymasterDigests;
            if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
                // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
                // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
                // digest, we don't let import parameters override the digest implied by the key.
                // If the parameters specify digests at all, they must specify only one digest, the
                // only implied by key algorithm.
                int keymasterImpliedDigest =
                        KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
                if (keymasterImpliedDigest == -1) {
                    throw new ProviderException(
                            "HMAC key algorithm digest unknown for key algorithm "
                                    + key.getAlgorithm());
                }
                keymasterDigests = new int[] {keymasterImpliedDigest};
                if (params.isDigestsSpecified()) {
                    // Digest(s) explicitly specified in params -- check that the list consists of
                    // exactly one digest, the one implied by key algorithm.
                    int[] keymasterDigestsFromParams =
                            KeyProperties.Digest.allToKeymaster(params.getDigests());
                    if ((keymasterDigestsFromParams.length != 1)
                            || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
                        throw new KeyStoreException(
                                "Unsupported digests specification: "
                                + Arrays.asList(params.getDigests()) + ". Only "
                                + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest)
                                + " supported for HMAC key algorithm " + key.getAlgorithm());
                    }
                }
            } else {
                // Key algorithm does not imply a digest.
                if (params.isDigestsSpecified()) {
                    keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
                } else {
                    keymasterDigests = EmptyArray.INT;
                }
            }
            args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);

            @KeyProperties.PurposeEnum int purposes = params.getPurposes();
            int[] keymasterBlockModes =
                    KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
            if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
                    && (params.isRandomizedEncryptionRequired())) {
                for (int keymasterBlockMode : keymasterBlockModes) {
                    if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(
                            keymasterBlockMode)) {
                        throw new KeyStoreException(
                                "Randomized encryption (IND-CPA) required but may be violated by"
                                + " block mode: "
                                + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode)
                                + ". See KeyProtection documentation.");
                    }
                }
            }
            args.addEnums(KeymasterDefs.KM_TAG_PURPOSE,
                    KeyProperties.Purpose.allToKeymaster(purposes));
            args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
            if (params.getSignaturePaddings().length > 0) {
                throw new KeyStoreException("Signature paddings not supported for symmetric keys");
            }
            int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(
                    params.getEncryptionPaddings());
            args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
            KeymasterUtils.addUserAuthArgs(args, params);
            KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
                    args,
                    keymasterAlgorithm,
                    keymasterBlockModes,
                    keymasterDigests);
            args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
                    params.getKeyValidityStart());
            args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
                    params.getKeyValidityForOriginationEnd());
            args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME,
                    params.getKeyValidityForConsumptionEnd());

            if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0)
                    && (!params.isRandomizedEncryptionRequired())) {
                // Permit caller-provided IV when encrypting with this key
                args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
            }
        } catch (IllegalArgumentException | IllegalStateException e) {
            throw new KeyStoreException(e);
        }
        int flags = 0;
        if (params.isCriticalToDeviceEncryption()) {
            flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
        }
        if (params.isStrongBoxBacked()) {
            flags |= KeyStore.FLAG_STRONGBOX;
        }

        Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
        String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + entryAlias;
        int errorCode = mKeyStore.importKey(
                keyAliasInKeystore,
                args,
                KeymasterDefs.KM_KEY_FORMAT_RAW,
                keyMaterial,
                mUid,
                flags,
                new KeyCharacteristics());
        if (errorCode != KeyStore.NO_ERROR) {
            throw new KeyStoreException("Failed to import secret key. Keystore error code: "
                + errorCode);
        }
    }

    private void setWrappedKeyEntry(String alias, WrappedKeyEntry entry,
            java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
        if (param != null) {
            throw new KeyStoreException("Protection parameters are specified inside wrapped keys");
        }

        byte[] maskingKey = new byte[32];


        KeymasterArguments args = new KeymasterArguments();
        String[] parts = entry.getTransformation().split("/");

        String algorithm = parts[0];
        if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) {
            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
        } else if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) {
            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
        }

        if (parts.length > 1) {
            String mode = parts[1];
            if (KeyProperties.BLOCK_MODE_ECB.equalsIgnoreCase(mode)) {
                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
            } else if (KeyProperties.BLOCK_MODE_CBC.equalsIgnoreCase(mode)) {
                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CBC);
            } else if (KeyProperties.BLOCK_MODE_CTR.equalsIgnoreCase(mode)) {
                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
            } else if (KeyProperties.BLOCK_MODE_GCM.equalsIgnoreCase(mode)) {
                args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
            }
        }

        if (parts.length > 2) {
            String padding = parts[2];
            if (KeyProperties.ENCRYPTION_PADDING_NONE.equalsIgnoreCase(padding)) {
                // Noop
            } else if (KeyProperties.ENCRYPTION_PADDING_PKCS7.equalsIgnoreCase(padding)) {
                args.addEnums(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_PKCS7);
            } else if (KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(padding)) {
                args.addEnums(KeymasterDefs.KM_TAG_PADDING,
                    KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
            } else if (KeyProperties.ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(padding)) {
                args.addEnums(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
            }
        }

        KeyGenParameterSpec spec = (KeyGenParameterSpec) entry.getAlgorithmParameterSpec();
        if (spec.isDigestsSpecified()) {
            String digest = spec.getDigests()[0];
            if (KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest)) {
                // Noop
            } else if (KeyProperties.DIGEST_MD5.equalsIgnoreCase(digest)) {
                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
            } else if (KeyProperties.DIGEST_SHA1.equalsIgnoreCase(digest)) {
                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
            } else if (KeyProperties.DIGEST_SHA224.equalsIgnoreCase(digest)) {
                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
            } else if (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest)) {
                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
            } else if (KeyProperties.DIGEST_SHA384.equalsIgnoreCase(digest)) {
                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
            } else if (KeyProperties.DIGEST_SHA512.equalsIgnoreCase(digest)) {
                args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
            }
        }

        int errorCode = mKeyStore.importWrappedKey(
            Credentials.USER_PRIVATE_KEY + alias,
            entry.getWrappedKeyBytes(),
            Credentials.USER_PRIVATE_KEY + entry.getWrappingKeyAlias(),
            maskingKey,
            args,
            GateKeeper.getSecureUserId(),
            0, // FIXME fingerprint id?
            mUid,
            new KeyCharacteristics());
        if (errorCode == KeymasterDefs.KM_ERROR_UNIMPLEMENTED) {
          throw new SecureKeyImportUnavailableException("Could not import wrapped key");
        } else if (errorCode != KeyStore.NO_ERROR) {
            throw new KeyStoreException("Failed to import wrapped key. Keystore error code: "
                + errorCode);
        }
    }

    @Override
    public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
            throws KeyStoreException {
        throw new KeyStoreException("Operation not supported because key encoding is unknown");
    }

    @Override
    public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
        if (isKeyEntry(alias)) {
            throw new KeyStoreException("Entry exists and is not a trusted certificate");
        }

        // We can't set something to null.
        if (cert == null) {
            throw new NullPointerException("cert == null");
        }

        final byte[] encoded;
        try {
            encoded = cert.getEncoded();
        } catch (CertificateEncodingException e) {
            throw new KeyStoreException(e);
        }

        if (!mKeyStore.put(Credentials.CA_CERTIFICATE + alias, encoded, mUid, KeyStore.FLAG_NONE)) {
            throw new KeyStoreException("Couldn't insert certificate; is KeyStore initialized?");
        }
    }

    @Override
    public void engineDeleteEntry(String alias) throws KeyStoreException {
        if (!Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid)) {
            throw new KeyStoreException("Failed to delete entry: " + alias);
        }
    }

    private Set<String> getUniqueAliases() {
        final String[] rawAliases = mKeyStore.list("", mUid);
        if (rawAliases == null) {
            return new HashSet<String>();
        }

        final Set<String> aliases = new HashSet<String>(rawAliases.length);
        for (String alias : rawAliases) {
            final int idx = alias.indexOf('_');
            if ((idx == -1) || (alias.length() <= idx)) {
                Log.e(NAME, "invalid alias: " + alias);
                continue;
            }

            aliases.add(new String(alias.substring(idx + 1)));
        }

        return aliases;
    }

    @Override
    public Enumeration<String> engineAliases() {
        return Collections.enumeration(getUniqueAliases());
    }

    @Override
    public boolean engineContainsAlias(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        }

        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias, mUid)
                || mKeyStore.contains(Credentials.USER_SECRET_KEY + alias, mUid)
                || mKeyStore.contains(Credentials.USER_CERTIFICATE + alias, mUid)
                || mKeyStore.contains(Credentials.CA_CERTIFICATE + alias, mUid);
    }

    @Override
    public int engineSize() {
        return getUniqueAliases().size();
    }

    @Override
    public boolean engineIsKeyEntry(String alias) {
        return isKeyEntry(alias);
    }

    private boolean isKeyEntry(String alias) {
        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias, mUid) ||
                mKeyStore.contains(Credentials.USER_SECRET_KEY + alias, mUid);
    }


    private boolean isCertificateEntry(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        }

        return mKeyStore.contains(Credentials.CA_CERTIFICATE + alias, mUid);
    }

    @Override
    public boolean engineIsCertificateEntry(String alias) {
        return !isKeyEntry(alias) && isCertificateEntry(alias);
    }

    @Override
    public String engineGetCertificateAlias(Certificate cert) {
        if (cert == null) {
            return null;
        }
        if (!"X.509".equalsIgnoreCase(cert.getType())) {
            // Only X.509 certificates supported
            return null;
        }
        byte[] targetCertBytes;
        try {
            targetCertBytes = cert.getEncoded();
        } catch (CertificateEncodingException e) {
            return null;
        }
        if (targetCertBytes == null) {
            return null;
        }

        final Set<String> nonCaEntries = new HashSet<String>();

        /*
         * First scan the PrivateKeyEntry types. The KeyStoreSpi documentation
         * says to only compare the first certificate in the chain which is
         * equivalent to the USER_CERTIFICATE prefix for the Android keystore
         * convention.
         */
        final String[] certAliases = mKeyStore.list(Credentials.USER_CERTIFICATE, mUid);
        if (certAliases != null) {
            for (String alias : certAliases) {
                final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias, mUid);
                if (certBytes == null) {
                    continue;
                }

                nonCaEntries.add(alias);

                if (Arrays.equals(certBytes, targetCertBytes)) {
                    return alias;
                }
            }
        }

        /*
         * Look at all the TrustedCertificateEntry types. Skip all the
         * PrivateKeyEntry we looked at above.
         */
        final String[] caAliases = mKeyStore.list(Credentials.CA_CERTIFICATE, mUid);
        if (certAliases != null) {
            for (String alias : caAliases) {
                if (nonCaEntries.contains(alias)) {
                    continue;
                }

                final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias, mUid);
                if (certBytes == null) {
                    continue;
                }

                if (Arrays.equals(certBytes, targetCertBytes)) {
                    return alias;
                }
            }
        }

        return null;
    }

    @Override
    public void engineStore(OutputStream stream, char[] password) throws IOException,
            NoSuchAlgorithmException, CertificateException {
        throw new UnsupportedOperationException("Can not serialize AndroidKeyStore to OutputStream");
    }

    @Override
    public void engineLoad(InputStream stream, char[] password) throws IOException,
            NoSuchAlgorithmException, CertificateException {
        if (stream != null) {
            throw new IllegalArgumentException("InputStream not supported");
        }

        if (password != null) {
            throw new IllegalArgumentException("password not supported");
        }

        // Unfortunate name collision.
        mKeyStore = KeyStore.getInstance();
        mUid = KeyStore.UID_SELF;
    }

    @Override
    public void engineLoad(LoadStoreParameter param) throws IOException,
            NoSuchAlgorithmException, CertificateException {
        int uid = KeyStore.UID_SELF;
        if (param != null) {
            if (param instanceof AndroidKeyStoreLoadStoreParameter) {
                uid = ((AndroidKeyStoreLoadStoreParameter) param).getUid();
            } else {
                throw new IllegalArgumentException(
                        "Unsupported param type: " + param.getClass());
            }
        }
        mKeyStore = KeyStore.getInstance();
        mUid = uid;
    }

    @Override
    public void engineSetEntry(String alias, Entry entry, ProtectionParameter param)
            throws KeyStoreException {
        if (entry == null) {
            throw new KeyStoreException("entry == null");
        }

        Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);

        if (entry instanceof java.security.KeyStore.TrustedCertificateEntry) {
            java.security.KeyStore.TrustedCertificateEntry trE =
                    (java.security.KeyStore.TrustedCertificateEntry) entry;
            engineSetCertificateEntry(alias, trE.getTrustedCertificate());
            return;
        }

        if (entry instanceof PrivateKeyEntry) {
            PrivateKeyEntry prE = (PrivateKeyEntry) entry;
            setPrivateKeyEntry(alias, prE.getPrivateKey(), prE.getCertificateChain(), param);
        } else if (entry instanceof SecretKeyEntry) {
            SecretKeyEntry secE = (SecretKeyEntry) entry;
            setSecretKeyEntry(alias, secE.getSecretKey(), param);
        } else if (entry instanceof WrappedKeyEntry) {
            WrappedKeyEntry wke = (WrappedKeyEntry) entry;
            setWrappedKeyEntry(alias, wke, param);
        } else {
            throw new KeyStoreException(
                    "Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry"
                    + "; was " + entry);
        }
    }

    /**
     * {@link X509Certificate} which returns {@link AndroidKeyStorePublicKey} from
     * {@link #getPublicKey()}. This is so that crypto operations on these public keys contain
     * can find out which keystore private key entry to use. This is needed so that Android Keystore
     * crypto operations using public keys can find out which key alias to use. These operations
     * require an alias.
     */
    static class KeyStoreX509Certificate extends DelegatingX509Certificate {
        private final String mPrivateKeyAlias;
        private final int mPrivateKeyUid;
        KeyStoreX509Certificate(String privateKeyAlias, int privateKeyUid,
                X509Certificate delegate) {
            super(delegate);
            mPrivateKeyAlias = privateKeyAlias;
            mPrivateKeyUid = privateKeyUid;
        }

        @Override
        public PublicKey getPublicKey() {
            PublicKey original = super.getPublicKey();
            return AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(
                    mPrivateKeyAlias, mPrivateKeyUid,
                    original.getAlgorithm(), original.getEncoded());
        }
    }
}
