001/* ExemptionMechanism.java -- Generic crypto-weakening mechanism.
002   Copyright (C) 2004  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package javax.crypto;
040
041import gnu.java.security.Engine;
042
043import java.lang.reflect.InvocationTargetException;
044import java.security.AlgorithmParameters;
045import java.security.InvalidAlgorithmParameterException;
046import java.security.InvalidKeyException;
047import java.security.Key;
048import java.security.NoSuchAlgorithmException;
049import java.security.NoSuchProviderException;
050import java.security.Provider;
051import java.security.Security;
052import java.security.spec.AlgorithmParameterSpec;
053
054/**
055 * An exemption mechanism, which will conditionally allow cryptography
056 * where it is not normally allowed, implements things such as <i>key
057 * recovery</i>, <i>key weakening</i>, or <i>key escrow</i>.
058 *
059 * <p><b>Implementation note</b>: this class is present for
060 * API-compatibility only; it is not actually used anywhere in this library
061 * and this library does not, in general, support crypto weakening.
062 *
063 * @author Casey Marshall (csm@gnu.org)
064 * @since 1.4
065 */
066public class ExemptionMechanism
067{
068
069  // Constants and fields.
070  // ------------------------------------------------------------------------
071
072  private static final String SERVICE = "ExemptionMechanism";
073  private ExemptionMechanismSpi emSpi;
074  private Provider provider;
075  private String mechanism;
076  private boolean virgin;
077
078  // Constructor.
079  // ------------------------------------------------------------------------
080
081  protected ExemptionMechanism(ExemptionMechanismSpi emSpi, Provider provider,
082                               String mechanism)
083  {
084    this.emSpi = emSpi;
085    this.provider = provider;
086    this.mechanism = mechanism;
087    virgin = true;
088  }
089
090  /**
091   * Create an instance of <code>ExemptionMechanism</code> for a designated
092   * <code>mechanism</code> from the first Security Provider offering it.
093   *
094   * @param mechanism the name of the exemption mechanism to create.
095   * @return a newly created instance of <code>ExemptionMechanism</code>.
096   * @throws IllegalArgumentException if the provider is null.
097   * @throws NoSuchAlgorithmException if no such exemption mechanism is
098   *           available from any known Security Provider.
099   * @throws IllegalArgumentException if <code>mechanism</code> is
100   *           <code>null</code> or is an empty string.
101   */
102  public static final ExemptionMechanism getInstance(String mechanism)
103      throws NoSuchAlgorithmException
104  {
105    Provider[] p = Security.getProviders();
106    NoSuchAlgorithmException lastException = null;
107    for (int i = 0; i < p.length; i++)
108      try
109        {
110          return getInstance(mechanism, p[i]);
111        }
112      catch (NoSuchAlgorithmException x)
113        {
114          lastException = x;
115        }
116    if (lastException != null)
117      throw lastException;
118    throw new NoSuchAlgorithmException(mechanism);
119  }
120
121  /**
122   * Create an instance of <code>ExemptionMechanism</code> for a designated
123   * <code>mechanism</code> from a named <code>provider</code>.
124   *
125   * @param mechanism the name of the exemption mechanism to create.
126   * @param provider the security provider to provide the exemption
127   *          <code>mechanism</code>.
128   * @return a newly created instance of <code>ExemptionMechanism</code>.
129   * @throws NoSuchAlgorithmException if no such exemption mechanism is
130   *           available from the named <code>provider</code>.
131   * @throws NoSuchProviderException if no Security Provider with the designated
132   *           name is known to the underlying JVM.
133   * @throws IllegalArgumentException if either <code>mechanism</code> or
134   *           <code>provider</code> is <code>null</code>, or if
135   *           <code>mechanism</code> is an empty string.
136   */
137  public static final ExemptionMechanism getInstance(String mechanism,
138                                                     String provider)
139      throws NoSuchAlgorithmException, NoSuchProviderException
140  {
141    if (provider == null)
142      throw new IllegalArgumentException("provider MUST NOT be null");
143    Provider p = Security.getProvider(provider);
144    if (p == null)
145      throw new NoSuchProviderException(provider);
146    return getInstance(mechanism, p);
147  }
148
149  /**
150   * Create an instance of <code>ExemptionMechanism</code> for a designated
151   * <code>mechanism</code> from a designated <code>provider</code>.
152   *
153   * @param mechanism the name of the exemption mechanism to create.
154   * @param provider the security provider to provide the exemption
155   *          <code>mechanism</code>.
156   * @return a newly created instance of <code>ExemptionMechanism</code>.
157   * @throws NoSuchAlgorithmException if an exemption mechanism could not be
158   *           created.
159   * @throws IllegalArgumentException if either <code>mechanism</code> or
160   *           <code>provider</code> is <code>null</code>, or if
161   *           <code>mechanism</code> is an empty string.
162   */
163  public static final ExemptionMechanism getInstance(String mechanism,
164                                                     Provider provider)
165      throws NoSuchAlgorithmException
166  {
167    StringBuilder sb = new StringBuilder("ExemptionMechanism [")
168        .append(mechanism).append("] from provider[")
169        .append(provider).append("] could not be created");
170    Throwable cause;
171    try
172      {
173        Object spi = Engine.getInstance(SERVICE, mechanism, provider);
174        return new ExemptionMechanism((ExemptionMechanismSpi) spi,
175                                      provider,
176                                      mechanism);
177      }
178    catch (InvocationTargetException x)
179      {
180        cause = x.getCause();
181        if (cause instanceof NoSuchAlgorithmException)
182          throw (NoSuchAlgorithmException) cause;
183        if (cause == null)
184          cause = x;
185      }
186    catch (ClassCastException x)
187      {
188        cause = x;
189      }
190    NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
191    x.initCause(cause);
192    throw x;
193  }
194
195  public final byte[] genExemptionBlob()
196    throws IllegalStateException, ExemptionMechanismException
197  {
198    if (virgin)
199      {
200        throw new IllegalStateException("not initialized");
201      }
202    return emSpi.engineGenExemptionBlob();
203  }
204
205  public final int genExemptionBlob(byte[] output)
206    throws IllegalStateException, ExemptionMechanismException,
207           ShortBufferException
208  {
209    return genExemptionBlob(output, 0);
210  }
211
212  public final int genExemptionBlob(byte[] output, int outputOffset)
213    throws IllegalStateException, ExemptionMechanismException,
214           ShortBufferException
215  {
216    if (virgin)
217      {
218        throw new IllegalStateException("not initialized");
219      }
220    return emSpi.engineGenExemptionBlob(output, outputOffset);
221  }
222
223  public final String getName()
224  {
225    return mechanism;
226  }
227
228  public final int getOutputSize(int inputLength) throws IllegalStateException
229  {
230    if (virgin)
231      {
232        throw new IllegalStateException("not initialized");
233      }
234    return emSpi.engineGetOutputSize(inputLength);
235  }
236
237  public final Provider getProvider()
238  {
239    return provider;
240  }
241
242  public final void init(Key key)
243    throws ExemptionMechanismException, InvalidKeyException
244  {
245    emSpi.engineInit(key);
246    virgin = false;
247  }
248
249  public final void init(Key key, AlgorithmParameters params)
250    throws ExemptionMechanismException, InvalidAlgorithmParameterException,
251           InvalidKeyException
252  {
253    emSpi.engineInit(key, params);
254    virgin = false;
255  }
256
257  public final void init(Key key, AlgorithmParameterSpec params)
258    throws ExemptionMechanismException, InvalidAlgorithmParameterException,
259           InvalidKeyException
260  {
261    emSpi.engineInit(key, params);
262    virgin = false;
263  }
264
265  public final boolean isCryptoAllowed(Key key)
266    throws ExemptionMechanismException
267  {
268    return true;
269  }
270
271  protected void finalize()
272  {
273  }
274}