/* KeyAgreement.java -- Engine for key agreement methods.
   Copyright (C) 2004  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.crypto;

import gnu.java.security.Engine;

import java.lang.reflect.InvocationTargetException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;

/**
 * Key agreement is a method in which two or more parties may agree on a
 * secret key for symmetric cryptography or message authentication
 * without transmitting any secrets in the clear. Key agreement
 * algorithms typically use a public/private <i>key pair</i>, and the
 * public key (along with some additional information) is sent across
 * untrusted networks.
 *
 * <p>The most common form of key agreement used today is the
 * <i>Diffie-Hellman key exchange algorithm</i>, described in <a
 * href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/">PKCS #3 -
 * Diffie Hellman Key Agreement Standard</a>.
 *
 * @author Casey Marshall (csm@gnu.org)
 * @since 1.4
 * @see KeyGenerator
 * @see SecretKey
 */
public class KeyAgreement
{

  // Fields.
  // ------------------------------------------------------------------------

  private static final String SERVICE = "KeyAgreement";

  /** The underlying key agreement implementation. */
  private KeyAgreementSpi kaSpi;

  /** The provider of this implementation. */
  private Provider provider;

  /** The name of this instance's algorithm. */
  private String algorithm;

  /** Singnals whether or not this instance has been initialized. */
  private boolean virgin;

  // Constructor.
  // ------------------------------------------------------------------------

  protected KeyAgreement(KeyAgreementSpi kaSpi, Provider provider,
                         String algorithm)
  {
    this.kaSpi = kaSpi;
    this.provider = provider;
    this.algorithm = algorithm;
    virgin = true;
  }

  // Class methods.
  // ------------------------------------------------------------------------

  /**
   * Get an implementation of an algorithm from the first provider that
   * implements it.
   *
   * @param algorithm The name of the algorithm to get.
   * @return The proper KeyAgreement instacne, if found.
   * @throws java.security.NoSuchAlgorithmException If the specified
   *         algorithm is not implemented by any installed provider.
   */
  public static final KeyAgreement getInstance(String algorithm)
    throws NoSuchAlgorithmException
  {
    Provider[] provs = Security.getProviders();
    String msg = algorithm;
    for (int i = 0; i < provs.length; i++)
      {
        try
          {
            return getInstance(algorithm, provs[i]);
          }
        catch (NoSuchAlgorithmException nsae)
          {
            msg = nsae.getMessage();
          }
      }
    throw new NoSuchAlgorithmException(msg);
  }

  /**
   * Get an implementation of an algorithm from a named provider.
   *
   * @param algorithm The name of the algorithm to get.
   * @param provider  The name of the provider from which to get the
   *        implementation.
   * @return The proper KeyAgreement instance, if found.
   * @throws java.security.NoSuchAlgorithmException If the named provider
   *         does not implement the algorithm.
   * @throws java.security.NoSuchProviderException If the named provider
   *         does not exist.
   */
  public static final KeyAgreement getInstance(String algorithm,
                                               String provider)
    throws NoSuchAlgorithmException, NoSuchProviderException
  {
    Provider p = Security.getProvider(provider);
    if (p == null)
      {
        throw new NoSuchProviderException(provider);
      }
    return getInstance(algorithm, p);
  }

  /**
   * Get an implementation of an algorithm from a specific provider.
   *
   * @param algorithm The name of the algorithm to get.
   * @param provider  The provider from which to get the implementation.
   * @return The proper KeyAgreement instance, if found.
   * @throws java.security.NoSuchAlgorithmException If this provider
   *         does not implement the algorithm.
   */
  public static final KeyAgreement getInstance(String algorithm,
                                               Provider provider)
    throws NoSuchAlgorithmException
  {
    try
      {
        return new KeyAgreement((KeyAgreementSpi)
          Engine.getInstance(SERVICE, algorithm, provider),
          provider, algorithm);
      }
    catch (InvocationTargetException ite)
      {
        if (ite.getCause() == null)
          throw new NoSuchAlgorithmException(algorithm);
        if (ite.getCause() instanceof NoSuchAlgorithmException)
          throw (NoSuchAlgorithmException) ite.getCause();
        throw new NoSuchAlgorithmException(algorithm);
      }
    catch (ClassCastException cce)
      {
        throw new NoSuchAlgorithmException(algorithm);
      }
  }

  // Instance methods.
  // ------------------------------------------------------------------------

  /**
   * Do a phase in the key agreement. The number of times this method is
   * called depends upon the algorithm and the number of parties
   * involved, but must be called at least once with the
   * <code>lastPhase</code> flag set to <code>true</code>.
   *
   * @param key       The key for this phase.
   * @param lastPhase Should be <code>true</code> if this will be the
   *        last phase before generating the shared secret.
   * @return The intermediate result, or <code>null</code> if there is
   *         no intermediate result.
   * @throws java.lang.IllegalStateException If this instance has not
   *         been initialized.
   * @throws java.security.InvalidKeyException If the key is
   *         inappropriate for this algorithm.
   */
  public final Key doPhase(Key key, boolean lastPhase)
    throws IllegalStateException, InvalidKeyException
  {
    if (virgin)
      {
        throw new IllegalStateException("not initialized");
      }
    return kaSpi.engineDoPhase(key, lastPhase);
  }

  /**
   * Generate the shared secret in a new byte array.
   *
   * @return The shared secret.
   * @throws java.lang.IllegalStateException If this instnace has not
   *         been initialized, or if not enough calls to
   *         <code>doPhase</code> have been made.
   */
  public final byte[] generateSecret() throws IllegalStateException
  {
    if (virgin)
      {
        throw new IllegalStateException("not initialized");
      }
    return kaSpi.engineGenerateSecret();
  }

  /**
   * Generate the shared secret and store it into the supplied array.
   *
   * @param sharedSecret The array in which to store the secret.
   * @param offset       The index in <code>sharedSecret</code> to start
   *                     storing data.
   * @return The length of the shared secret, in bytes.
   * @throws java.lang.IllegalStateException If this instnace has not
   *         been initialized, or if not enough calls to
   *         <code>doPhase</code> have been made.
   * @throws javax.crypto.ShortBufferException If the supplied array is
   *         not large enough to store the result.
   */
  public final int generateSecret(byte[] sharedSecret, int offset)
  throws IllegalStateException, ShortBufferException
  {
    if (virgin)
      {
        throw new IllegalStateException("not initialized");
      }
    return kaSpi.engineGenerateSecret(sharedSecret, offset);
  }

  /**
   * Generate the shared secret and return it as an appropriate {@link
   * SecretKey}.
   *
   * @param algorithm The secret key's algorithm.
   * @return The shared secret as a secret key.
   * @throws java.lang.IllegalStateException If this instnace has not
   *         been initialized, or if not enough calls to
   *         <code>doPhase</code> have been made.
   * @throws java.security.InvalidKeyException If the shared secret
   *         cannot be used to make a {@link SecretKey}.
   * @throws java.security.NoSuchAlgorithmException If the specified
   *         algorithm does not exist.
   */
  public final SecretKey generateSecret(String algorithm)
  throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException
  {
    if (virgin)
      {
        throw new IllegalStateException("not initialized");
      }
    return kaSpi.engineGenerateSecret(algorithm);
  }

  /**
   * Return the name of this key-agreement algorithm.
   *
   * @return The algorithm name.
   */
  public final String getAlgorithm()
  {
    return algorithm;
  }

  /**
   * Return the provider of the underlying implementation.
   *
   * @return The provider.
   */
  public final Provider getProvider()
  {
    return provider;
  }

  /**
   * Initialize this key agreement with a key. This method will use the
   * highest-priority {@link java.security.SecureRandom} as its source
   * of randomness.
   *
   * @param key The key, usually the user's private key.
   * @throws java.security.InvalidKeyException If the supplied key is
   *         not appropriate.
   */
  public final void init(Key key) throws InvalidKeyException
  {
    init(key, new SecureRandom());
  }

  /**
   * Initialize this key agreement with a key and a source of
   * randomness.
   *
   * @param key    The key, usually the user's private key.
   * @param random The source of randomness.
   * @throws java.security.InvalidKeyException If the supplied key is
   *         not appropriate.
   */
  public final void init(Key key, SecureRandom random)
    throws InvalidKeyException
  {
    kaSpi.engineInit(key, random);
    virgin = false; // w00t!
  }

  /**
   * Initialize this key agreement with a key and parameters. This
   * method will use the highest-priority {@link
   * java.security.SecureRandom} as its source of randomness.
   *
   * @param key    The key, usually the user's private key.
   * @param params The algorithm parameters.
   * @throws java.security.InvalidAlgorithmParameterException If the
   *         supplied parameters are not appropriate.
   * @throws java.security.InvalidKeyException If the supplied key is
   *         not appropriate.
   */
  public final void init(Key key, AlgorithmParameterSpec params)
    throws InvalidAlgorithmParameterException, InvalidKeyException
  {
    init(key, params, new SecureRandom());
  }

  /**
   * Initialize this key agreement with a key, parameters, and source of
   * randomness.
   *
   * @param key    The key, usually the user's private key.
   * @param params The algorithm parameters.
   * @param random The source of randomness.
   * @throws java.security.InvalidAlgorithmParameterException If the
   *         supplied parameters are not appropriate.
   * @throws java.security.InvalidKeyException If the supplied key is
   *         not appropriate.
   */
  public final void init(Key key, AlgorithmParameterSpec params,
                         SecureRandom random)
    throws InvalidAlgorithmParameterException, InvalidKeyException
  {
    kaSpi.engineInit(key, params, random);
    virgin = false; // w00t!
  }
}
