// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package com.google.crypto.tink.subtle;

import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.Provider;
import java.security.Security;
import java.security.Signature;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.Mac;

/**
 * A factory that returns JCE engines, using pre-specified j.security.Providers.
 *
 * <p>This class contains a lot of static factories and static functions returning factories: these
 * allow customization and hide the typing complexity in this class. To use this class, import it,
 * and replace your <code>Cipher.getInstance(...)</code> with <code>
 * EngineFactory.CIPHER.getInstance(...)</code>.
 *
 * @since 1.0.0
 */
public final class EngineFactory<T_WRAPPER extends EngineWrapper<T_ENGINE>, T_ENGINE> {
  private static final Logger logger = Logger.getLogger(EngineFactory.class.getName());
  private static final List<Provider> defaultPolicy;
  private static final boolean DEFAULT_LET_FALLBACK = true;

  // Warning: keep this above the initialization of static providers below. or you'll get null
  // pointer errors (due to this policy not being initialized).
  static {
    if (SubtleUtil.isAndroid()) {
      // TODO(thaidn): test this when Android building and testing are supported.
      defaultPolicy =
          toProviderList(
              "GmsCore_OpenSSL" /* Conscrypt in GmsCore, updatable thus preferrable */,
              "AndroidOpenSSL" /* Conscrypt in AOSP, not updatable but still better than BC */);
    } else {
      defaultPolicy = new ArrayList<Provider>();
    }
  }

  public static final EngineFactory<EngineWrapper.TCipher, Cipher> CIPHER =
      new EngineFactory<>(new EngineWrapper.TCipher());

  public static final EngineFactory<EngineWrapper.TCipher, Cipher> getCustomCipherProvider(
      boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TCipher, Cipher>(
        new EngineWrapper.TCipher(), toProviderList(providerNames), letFallbackToDefault);
  }

  public static final EngineFactory<EngineWrapper.TMac, Mac> MAC =
      new EngineFactory<>(new EngineWrapper.TMac());

  public static final EngineFactory<EngineWrapper.TMac, Mac> getCustomMacProvider(
      boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TMac, Mac>(
        new EngineWrapper.TMac(), toProviderList(providerNames), letFallbackToDefault);
  }

  public static final EngineFactory<EngineWrapper.TSignature, Signature> SIGNATURE =
      new EngineFactory<>(new EngineWrapper.TSignature());

  public static final EngineFactory<EngineWrapper.TSignature, Signature> getCustomSignatureProvider(
      boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TSignature, Signature>(
        new EngineWrapper.TSignature(), toProviderList(providerNames), letFallbackToDefault);
  }

  public static final EngineFactory<EngineWrapper.TMessageDigest, MessageDigest> MESSAGE_DIGEST =
      new EngineFactory<>(new EngineWrapper.TMessageDigest());

  public static final EngineFactory<EngineWrapper.TMessageDigest, MessageDigest>
      getCustomMessageDigestProvider(boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TMessageDigest, MessageDigest>(
        new EngineWrapper.TMessageDigest(), toProviderList(providerNames), letFallbackToDefault);
  }

  public static final EngineFactory<EngineWrapper.TKeyAgreement, KeyAgreement> KEY_AGREEMENT =
      new EngineFactory<>(new EngineWrapper.TKeyAgreement());

  public static final EngineFactory<EngineWrapper.TKeyAgreement, KeyAgreement>
      getCustomKeyAgreementProvider(boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TKeyAgreement, KeyAgreement>(
        new EngineWrapper.TKeyAgreement(), toProviderList(providerNames), letFallbackToDefault);
  }

  public static final EngineFactory<EngineWrapper.TKeyPairGenerator, KeyPairGenerator>
      KEY_PAIR_GENERATOR = new EngineFactory<>(new EngineWrapper.TKeyPairGenerator());

  public static final EngineFactory<EngineWrapper.TKeyPairGenerator, KeyPairGenerator>
      getCustomKeyPairGeneratorProvider(boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TKeyPairGenerator, KeyPairGenerator>(
        new EngineWrapper.TKeyPairGenerator(), toProviderList(providerNames), letFallbackToDefault);
  }

  public static final EngineFactory<EngineWrapper.TKeyFactory, KeyFactory> KEY_FACTORY =
      new EngineFactory<>(new EngineWrapper.TKeyFactory());

  public static final EngineFactory<EngineWrapper.TKeyFactory, KeyFactory>
      getCustomKeyFactoryProvider(boolean letFallbackToDefault, String... providerNames) {
    return new EngineFactory<EngineWrapper.TKeyFactory, KeyFactory>(
        new EngineWrapper.TKeyFactory(), toProviderList(providerNames), letFallbackToDefault);
  }

  /** Helper function to get a list of Providers from names. */
  public static List<Provider> toProviderList(String... providerNames) {
    List<Provider> providers = new ArrayList<Provider>();
    for (String s : providerNames) {
      Provider p = Security.getProvider(s);
      if (p != null) {
        providers.add(p);
      } else {
        logger.info(String.format("Provider %s not available", s));
      }
    }
    return providers;
  }

  public EngineFactory(T_WRAPPER instanceBuilder) {
    this.instanceBuilder = instanceBuilder;
    this.policy = defaultPolicy;
    this.letFallback = DEFAULT_LET_FALLBACK;
  }

  public EngineFactory(T_WRAPPER instanceBuilder, List<Provider> policy) {
    this.instanceBuilder = instanceBuilder;
    this.policy = policy;
    this.letFallback = DEFAULT_LET_FALLBACK;
  }

  public EngineFactory(T_WRAPPER instanceBuilder, List<Provider> policy, boolean letFallback) {
    this.instanceBuilder = instanceBuilder;
    this.policy = policy;
    this.letFallback = letFallback;
  }

  public T_ENGINE getInstance(String algorithm) throws GeneralSecurityException {
    for (Provider p : this.policy) {
      if (tryProvider(algorithm, p)) {
        return this.instanceBuilder.getInstance(algorithm, p);
      }
    }
    if (letFallback) {
      return this.instanceBuilder.getInstance(algorithm, null);
    }
    throw new GeneralSecurityException("No good Provider found.");
  }

  private T_WRAPPER instanceBuilder;
  private List<Provider> policy;
  private boolean letFallback;

  private boolean tryProvider(String algorithm, Provider provider) {
    try {
      this.instanceBuilder.getInstance(algorithm, provider);
      return true;
    } catch (Exception e) { // Don't care which one specifically.
      e.printStackTrace();
      return false;
    }
  }
}
