Home | History | Annotate | Download | only in crypto
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package javax.crypto;
     19 
     20 import java.security.AlgorithmParameters;
     21 import java.security.InvalidAlgorithmParameterException;
     22 import java.security.InvalidKeyException;
     23 import java.security.Key;
     24 import java.security.NoSuchAlgorithmException;
     25 import java.security.NoSuchProviderException;
     26 import java.security.Provider;
     27 import java.security.Security;
     28 import java.security.spec.AlgorithmParameterSpec;
     29 import java.util.Arrays;
     30 import org.apache.harmony.security.fortress.Engine;
     31 
     32 /**
     33  * This class implements the functionality of an exemption mechanism such as
     34  * <i>key recovery</i>, <i>key weakening</i>, or <i>key escrow</i>.
     35  */
     36 public class ExemptionMechanism {
     37 
     38     // Used to access common engine functionality
     39     private static final Engine engine = new Engine("ExemptionMechanism");
     40 
     41     // Store used provider
     42     private final Provider provider;
     43 
     44     // Store used spi implementation
     45     private final ExemptionMechanismSpi spiImpl;
     46 
     47     // Store mechanism name
     48     private final String mechanism;
     49 
     50     // Store state (initialized or not)
     51     private boolean isInit;
     52 
     53     // Store initKey value
     54     private Key initKey;
     55 
     56     // Indicates if blob generated successfully
     57     private boolean generated;
     58 
     59     /**
     60      * Creates a {@code ExemptionMechanism} instance.
     61      *
     62      * @param exmechSpi
     63      *            the implementation delegate.
     64      * @param provider
     65      *            the associated provider.
     66      * @param mechanism
     67      *            the name of the mechanism.
     68      */
     69     protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi,
     70             Provider provider, String mechanism) {
     71         this.mechanism = mechanism;
     72         this.spiImpl = exmechSpi;
     73         this.provider = provider;
     74         isInit = false;
     75     }
     76 
     77     /**
     78      * Returns the name of this {@code ExemptionMechanism}.
     79      *
     80      * @return the name of this {@code ExemptionMechanism}.
     81      */
     82     public final String getName() {
     83         return mechanism;
     84     }
     85 
     86     /**
     87      * Returns a new {@code ExemptionMechanism} instance that provides the
     88      * specified exemption mechanism algorithm.
     89      *
     90      * @param algorithm
     91      *            the name of the requested exemption mechanism.
     92      * @return the new {@code ExemptionMechanism} instance.
     93      * @throws NoSuchAlgorithmException
     94      *             if the specified algorithm is not available by any provider.
     95      * @throws NullPointerException
     96      *             if the algorithm parameter is {@code null}.
     97      */
     98     public static final ExemptionMechanism getInstance(String algorithm)
     99             throws NoSuchAlgorithmException {
    100         if (algorithm == null) {
    101             throw new NullPointerException();
    102         }
    103         synchronized (engine) {
    104             engine.getInstance(algorithm, null);
    105             return new ExemptionMechanism((ExemptionMechanismSpi) engine.spi,
    106                     engine.provider, algorithm);
    107         }
    108     }
    109 
    110     /**
    111      * Returns a new {@code ExemptionMechansm} instance that provides the
    112      * specified exemption mechanism algorithm from the specified provider.
    113      *
    114      * @param algorithm
    115      *            the name of the requested exemption mechanism.
    116      * @param provider
    117      *            the name of the provider that is providing the algorithm.
    118      * @return the new {@code ExemptionMechanism} instance.
    119      * @throws NoSuchAlgorithmException
    120      *             if the specified algorithm is not provided by the specified
    121      *             provider.
    122      * @throws NoSuchProviderException
    123      *             if the specified provider is not available.
    124      * @throws NullPointerException
    125      *             if the algorithm parameter is {@code null}.
    126      * @throws IllegalArgumentException
    127      *             if the provider parameter is {@code null}.
    128      */
    129     public static final ExemptionMechanism getInstance(String algorithm,
    130             String provider) throws NoSuchAlgorithmException,
    131             NoSuchProviderException {
    132         if (provider == null) {
    133             throw new IllegalArgumentException("provider == null");
    134         }
    135         Provider impProvider = Security.getProvider(provider);
    136         if (impProvider == null) {
    137             throw new NoSuchProviderException(provider);
    138         }
    139         if (algorithm == null) {
    140             throw new NullPointerException();
    141         }
    142         return getInstance(algorithm, impProvider);
    143     }
    144 
    145     /**
    146      * Returns a new {@code ExemptionMechanism} instance that provides the
    147      * specified exemption mechanism algorithm from the specified provider.
    148      *
    149      * @param algorithm
    150      *            the name of the requested exemption mechanism.
    151      * @param provider
    152      *            the provider that is providing the algorithm.
    153      * @return the new {@code ExemptionMechanism} instance.
    154      * @throws NoSuchAlgorithmException
    155      *             if the specified algorithm is not provided by the specified
    156      *             provider.
    157      * @throws NullPointerException
    158      *             if the algorithm parameter is {@code null}.
    159      * @throws IllegalArgumentException
    160      *             if the provider parameter is {@code null}.
    161      */
    162     public static final ExemptionMechanism getInstance(String algorithm,
    163             Provider provider) throws NoSuchAlgorithmException {
    164         if (algorithm == null) {
    165             throw new NullPointerException();
    166         }
    167         if (provider == null) {
    168             throw new IllegalArgumentException("provider == null");
    169         }
    170         synchronized (engine) {
    171             engine.getInstance(algorithm, provider, null);
    172             return new ExemptionMechanism((ExemptionMechanismSpi) engine.spi,
    173                     provider, algorithm);
    174         }
    175     }
    176 
    177     /**
    178      * Returns the provider of this {@code ExemptionMechanism} instance.
    179      *
    180      * @return the provider of this {@code ExemptionMechanism} instance.
    181      */
    182     public final Provider getProvider() {
    183         return provider;
    184     }
    185 
    186     /**
    187      * Returns whether the result blob for this {@code ExemptionMechanism}
    188      * instance has been generated successfully and that the specified key is
    189      * the same as the one that was used to initialize and generate.
    190      *
    191      * @param key
    192      *            the key to verify.
    193      * @return whether the result blob for this {@code ExemptionMechanism}
    194      *         instance has been generated successfully.
    195      * @throws ExemptionMechanismException
    196      *             if an error occurs while determining whether the result blob
    197      *             has been generated successfully.
    198      */
    199     public final boolean isCryptoAllowed(Key key)
    200             throws ExemptionMechanismException {
    201 
    202         if (generated
    203                 && (initKey.equals(key) || Arrays.equals(initKey.getEncoded(),
    204                         key.getEncoded()))) {
    205             return true;
    206         }
    207         return false;
    208     }
    209 
    210     /**
    211      * Returns the size in bytes for the output buffer needed to hold the output
    212      * of the next {@link #genExemptionBlob} call, given the specified {@code
    213      * inputLen} (in bytes).
    214      *
    215      * @param inputLen
    216      *            the specified input length (in bytes).
    217      * @return the size in bytes for the output buffer.
    218      * @throws IllegalStateException
    219      *             if this {@code ExemptionMechanism} instance is not
    220      *             initialized.
    221      */
    222     public final int getOutputSize(int inputLen) throws IllegalStateException {
    223         if (!isInit) {
    224             throw new IllegalStateException("ExemptionMechanism is not initialized");
    225         }
    226         return spiImpl.engineGetOutputSize(inputLen);
    227     }
    228 
    229     /**
    230      * Initializes this {@code ExemptionMechanism} instance with the
    231      * specified key.
    232      *
    233      * @param key
    234      *            the key to initialize this instance with.
    235      * @throws InvalidKeyException
    236      *             if the key cannot be used to initialize this mechanism.
    237      * @throws ExemptionMechanismException
    238      *             if error(s) occur during initialization.
    239      */
    240     public final void init(Key key) throws InvalidKeyException,
    241             ExemptionMechanismException {
    242         generated = false;
    243         spiImpl.engineInit(key);
    244         initKey = key;
    245         isInit = true;
    246     }
    247 
    248     /**
    249      * Initializes this {@code ExemptionMechanism} instance with the
    250      * specified key and algorithm parameters.
    251      *
    252      * @param key
    253      *            the key to initialize this instance with.
    254      * @param param
    255      *            the parameters for this exemption mechanism algorithm.
    256      * @throws InvalidKeyException
    257      *             if the key cannot be used to initialize this mechanism.
    258      * @throws InvalidAlgorithmParameterException
    259      *             if the parameters cannot be used to initialize this
    260      *             mechanism.
    261      * @throws ExemptionMechanismException
    262      *             if error(s) occur during initialization.
    263      */
    264     public final void init(Key key, AlgorithmParameters param)
    265             throws InvalidKeyException, InvalidAlgorithmParameterException,
    266             ExemptionMechanismException {
    267         generated = false;
    268         spiImpl.engineInit(key, param);
    269         initKey = key;
    270         isInit = true;
    271     }
    272 
    273     /**
    274      * Initializes this {@code ExemptionMechanism} instance with the
    275      * specified key and algorithm parameters.
    276      *
    277      * @param key
    278      *            the key to initialize this instance with.
    279      * @param param
    280      *            the parameters for this exemption mechanism algorithm.
    281      * @throws InvalidKeyException
    282      *             if the key cannot be used to initialize this mechanism.
    283      * @throws InvalidAlgorithmParameterException
    284      *             the the parameters cannot be used to initialize this
    285      *             mechanism.
    286      * @throws ExemptionMechanismException
    287      *             if error(s) occur during initialization.
    288      */
    289     public final void init(Key key, AlgorithmParameterSpec param)
    290             throws InvalidKeyException, InvalidAlgorithmParameterException,
    291             ExemptionMechanismException {
    292         generated = false;
    293         spiImpl.engineInit(key, param);
    294         initKey = key;
    295         isInit = true;
    296     }
    297 
    298     /**
    299      * Generates the result key blob for this exemption mechanism.
    300      *
    301      * @return the result key blob for this exemption mechanism.
    302      * @throws IllegalStateException
    303      *             if this {@code ExemptionMechanism} instance is not
    304      *             initialized.
    305      * @throws ExemptionMechanismException
    306      *             if error(s) occur during generation.
    307      */
    308     public final byte[] genExemptionBlob() throws IllegalStateException,
    309             ExemptionMechanismException {
    310         if (!isInit) {
    311             throw new IllegalStateException("ExemptionMechanism is not initialized");
    312         }
    313         generated = false;
    314         byte[] result = spiImpl.engineGenExemptionBlob();
    315         generated = true;
    316         return result;
    317     }
    318 
    319     /**
    320      * Generates the result key blob for this exemption mechanism and stores it
    321      * into the {@code output} buffer.
    322      *
    323      * @param output
    324      *            the output buffer for the result key blob.
    325      * @return the number of bytes written to the {@code output} buffer.
    326      * @throws IllegalStateException
    327      *             if this {@code ExemptionMechanism} instance is not
    328      *             initialized.
    329      * @throws ShortBufferException
    330      *             if the provided buffer is too small for the result key blob.
    331      * @throws ExemptionMechanismException
    332      *             if error(s) occur during generation.
    333      */
    334     public final int genExemptionBlob(byte[] output)
    335             throws IllegalStateException, ShortBufferException,
    336             ExemptionMechanismException {
    337         return genExemptionBlob(output, 0);
    338     }
    339 
    340     /**
    341      * Generates the result key blob for this exemption mechanism and stores it
    342      * into the {@code output} buffer at offset {@code outputOffset}.
    343      *
    344      * @param output
    345      *            the output buffer for the result key blob.
    346      * @param outputOffset
    347      *            the offset in the output buffer to start.
    348      * @return the number of bytes written to the {@code output} buffer.
    349      * @throws IllegalStateException
    350      *             if this {@code ExemptionMechanism} instance is not
    351      *             initialized.
    352      * @throws ShortBufferException
    353      *             if the provided buffer is too small for the result key blob.
    354      * @throws ExemptionMechanismException
    355      *             if error(s) occur during generation.
    356      */
    357     public final int genExemptionBlob(byte[] output, int outputOffset)
    358             throws IllegalStateException, ShortBufferException,
    359             ExemptionMechanismException {
    360         if (!isInit) {
    361             throw new IllegalStateException("ExemptionMechanism is not initialized");
    362         }
    363         generated = false;
    364         int len = spiImpl.engineGenExemptionBlob(output, outputOffset);
    365         generated = true;
    366         return len;
    367     }
    368 
    369     /**
    370      * Override to clear any key state in the instance.
    371      */
    372     @Override protected void finalize() {
    373         try {
    374             super.finalize();
    375         } catch (Throwable t) {
    376             throw new AssertionError(t);
    377         }
    378     }
    379 }
    380