001    /* ExemptionMechanism.java -- Generic crypto-weakening mechanism.
002       Copyright (C) 2004  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.crypto;
040    
041    import gnu.java.security.Engine;
042    
043    import java.lang.reflect.InvocationTargetException;
044    import java.security.AlgorithmParameters;
045    import java.security.InvalidAlgorithmParameterException;
046    import java.security.InvalidKeyException;
047    import java.security.Key;
048    import java.security.NoSuchAlgorithmException;
049    import java.security.NoSuchProviderException;
050    import java.security.Provider;
051    import java.security.Security;
052    import 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     */
066    public 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    }