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("algorithm == null");
    102         }
    103         Engine.SpiAndProvider sap = ENGINE.getInstance(algorithm, null);
    104         return new ExemptionMechanism((ExemptionMechanismSpi) sap.spi, sap.provider, algorithm);
    105     }
    106 
    107     /**
    108      * Returns a new {@code ExemptionMechansm} instance that provides the
    109      * specified exemption mechanism algorithm from the specified provider.
    110      *
    111      * @param algorithm
    112      *            the name of the requested exemption mechanism.
    113      * @param provider
    114      *            the name of the provider that is providing the algorithm.
    115      * @return the new {@code ExemptionMechanism} instance.
    116      * @throws NoSuchAlgorithmException
    117      *             if the specified algorithm is not provided by the specified
    118      *             provider.
    119      * @throws NoSuchProviderException
    120      *             if the specified provider is not available.
    121      * @throws NullPointerException
    122      *             if the algorithm parameter is {@code null}.
    123      * @throws IllegalArgumentException
    124      *             if the provider parameter is {@code null}.
    125      */
    126     public static final ExemptionMechanism getInstance(String algorithm,
    127             String provider) throws NoSuchAlgorithmException,
    128             NoSuchProviderException {
    129         if (provider == null) {
    130             throw new IllegalArgumentException("provider == null");
    131         }
    132         Provider impProvider = Security.getProvider(provider);
    133         if (impProvider == null) {
    134             throw new NoSuchProviderException(provider);
    135         }
    136         if (algorithm == null) {
    137             throw new NullPointerException("algorithm == null");
    138         }
    139         return getInstance(algorithm, impProvider);
    140     }
    141 
    142     /**
    143      * Returns a new {@code ExemptionMechanism} instance that provides the
    144      * specified exemption mechanism algorithm from the specified provider.
    145      *
    146      * @param algorithm
    147      *            the name of the requested exemption mechanism.
    148      * @param provider
    149      *            the provider that is providing the algorithm.
    150      * @return the new {@code ExemptionMechanism} instance.
    151      * @throws NoSuchAlgorithmException
    152      *             if the specified algorithm is not provided by the specified
    153      *             provider.
    154      * @throws NullPointerException
    155      *             if the algorithm parameter is {@code null}.
    156      * @throws IllegalArgumentException
    157      *             if the provider parameter is {@code null}.
    158      */
    159     public static final ExemptionMechanism getInstance(String algorithm,
    160             Provider provider) throws NoSuchAlgorithmException {
    161         if (algorithm == null) {
    162             throw new NullPointerException("algorithm == null");
    163         }
    164         if (provider == null) {
    165             throw new IllegalArgumentException("provider == null");
    166         }
    167         Object spi = ENGINE.getInstance(algorithm, provider, null);
    168         return new ExemptionMechanism((ExemptionMechanismSpi) spi, provider, algorithm);
    169     }
    170 
    171     /**
    172      * Returns the provider of this {@code ExemptionMechanism} instance.
    173      *
    174      * @return the provider of this {@code ExemptionMechanism} instance.
    175      */
    176     public final Provider getProvider() {
    177         return provider;
    178     }
    179 
    180     /**
    181      * Returns whether the result blob for this {@code ExemptionMechanism}
    182      * instance has been generated successfully and that the specified key is
    183      * the same as the one that was used to initialize and generate.
    184      *
    185      * @param key
    186      *            the key to verify.
    187      * @return whether the result blob for this {@code ExemptionMechanism}
    188      *         instance has been generated successfully.
    189      * @throws ExemptionMechanismException
    190      *             if an error occurs while determining whether the result blob
    191      *             has been generated successfully.
    192      */
    193     public final boolean isCryptoAllowed(Key key)
    194             throws ExemptionMechanismException {
    195 
    196         if (generated
    197                 && (initKey.equals(key) || Arrays.equals(initKey.getEncoded(),
    198                         key.getEncoded()))) {
    199             return true;
    200         }
    201         return false;
    202     }
    203 
    204     /**
    205      * Returns the size in bytes for the output buffer needed to hold the output
    206      * of the next {@link #genExemptionBlob} call, given the specified {@code
    207      * inputLen} (in bytes).
    208      *
    209      * @param inputLen
    210      *            the specified input length (in bytes).
    211      * @return the size in bytes for the output buffer.
    212      * @throws IllegalStateException
    213      *             if this {@code ExemptionMechanism} instance is not
    214      *             initialized.
    215      */
    216     public final int getOutputSize(int inputLen) throws IllegalStateException {
    217         if (!isInit) {
    218             throw new IllegalStateException("ExemptionMechanism is not initialized");
    219         }
    220         return spiImpl.engineGetOutputSize(inputLen);
    221     }
    222 
    223     /**
    224      * Initializes this {@code ExemptionMechanism} instance with the
    225      * specified key.
    226      *
    227      * @param key
    228      *            the key to initialize this instance with.
    229      * @throws InvalidKeyException
    230      *             if the key cannot be used to initialize this mechanism.
    231      * @throws ExemptionMechanismException
    232      *             if error(s) occur during initialization.
    233      */
    234     public final void init(Key key) throws InvalidKeyException,
    235             ExemptionMechanismException {
    236         generated = false;
    237         spiImpl.engineInit(key);
    238         initKey = key;
    239         isInit = true;
    240     }
    241 
    242     /**
    243      * Initializes this {@code ExemptionMechanism} instance with the
    244      * specified key and algorithm parameters.
    245      *
    246      * @param key
    247      *            the key to initialize this instance with.
    248      * @param param
    249      *            the parameters for this exemption mechanism algorithm.
    250      * @throws InvalidKeyException
    251      *             if the key cannot be used to initialize this mechanism.
    252      * @throws InvalidAlgorithmParameterException
    253      *             if the parameters cannot be used to initialize this
    254      *             mechanism.
    255      * @throws ExemptionMechanismException
    256      *             if error(s) occur during initialization.
    257      */
    258     public final void init(Key key, AlgorithmParameters param)
    259             throws InvalidKeyException, InvalidAlgorithmParameterException,
    260             ExemptionMechanismException {
    261         generated = false;
    262         spiImpl.engineInit(key, param);
    263         initKey = key;
    264         isInit = true;
    265     }
    266 
    267     /**
    268      * Initializes this {@code ExemptionMechanism} instance with the
    269      * specified key and algorithm parameters.
    270      *
    271      * @param key
    272      *            the key to initialize this instance with.
    273      * @param param
    274      *            the parameters for this exemption mechanism algorithm.
    275      * @throws InvalidKeyException
    276      *             if the key cannot be used to initialize this mechanism.
    277      * @throws InvalidAlgorithmParameterException
    278      *             the the parameters cannot be used to initialize this
    279      *             mechanism.
    280      * @throws ExemptionMechanismException
    281      *             if error(s) occur during initialization.
    282      */
    283     public final void init(Key key, AlgorithmParameterSpec param)
    284             throws InvalidKeyException, InvalidAlgorithmParameterException,
    285             ExemptionMechanismException {
    286         generated = false;
    287         spiImpl.engineInit(key, param);
    288         initKey = key;
    289         isInit = true;
    290     }
    291 
    292     /**
    293      * Generates the result key blob for this exemption mechanism.
    294      *
    295      * @return the result key blob for this exemption mechanism.
    296      * @throws IllegalStateException
    297      *             if this {@code ExemptionMechanism} instance is not
    298      *             initialized.
    299      * @throws ExemptionMechanismException
    300      *             if error(s) occur during generation.
    301      */
    302     public final byte[] genExemptionBlob() throws IllegalStateException,
    303             ExemptionMechanismException {
    304         if (!isInit) {
    305             throw new IllegalStateException("ExemptionMechanism is not initialized");
    306         }
    307         generated = false;
    308         byte[] result = spiImpl.engineGenExemptionBlob();
    309         generated = true;
    310         return result;
    311     }
    312 
    313     /**
    314      * Generates the result key blob for this exemption mechanism and stores it
    315      * into the {@code output} buffer.
    316      *
    317      * @param output
    318      *            the output buffer for the result key blob.
    319      * @return the number of bytes written to the {@code output} buffer.
    320      * @throws IllegalStateException
    321      *             if this {@code ExemptionMechanism} instance is not
    322      *             initialized.
    323      * @throws ShortBufferException
    324      *             if the provided buffer is too small for the result key blob.
    325      * @throws ExemptionMechanismException
    326      *             if error(s) occur during generation.
    327      */
    328     public final int genExemptionBlob(byte[] output)
    329             throws IllegalStateException, ShortBufferException,
    330             ExemptionMechanismException {
    331         return genExemptionBlob(output, 0);
    332     }
    333 
    334     /**
    335      * Generates the result key blob for this exemption mechanism and stores it
    336      * into the {@code output} buffer at offset {@code outputOffset}.
    337      *
    338      * @param output
    339      *            the output buffer for the result key blob.
    340      * @param outputOffset
    341      *            the offset in the output buffer to start.
    342      * @return the number of bytes written to the {@code output} buffer.
    343      * @throws IllegalStateException
    344      *             if this {@code ExemptionMechanism} instance is not
    345      *             initialized.
    346      * @throws ShortBufferException
    347      *             if the provided buffer is too small for the result key blob.
    348      * @throws ExemptionMechanismException
    349      *             if error(s) occur during generation.
    350      */
    351     public final int genExemptionBlob(byte[] output, int outputOffset)
    352             throws IllegalStateException, ShortBufferException,
    353             ExemptionMechanismException {
    354         if (!isInit) {
    355             throw new IllegalStateException("ExemptionMechanism is not initialized");
    356         }
    357         generated = false;
    358         int len = spiImpl.engineGenExemptionBlob(output, outputOffset);
    359         generated = true;
    360         return len;
    361     }
    362 
    363     /**
    364      * Override to clear any key state in the instance.
    365      */
    366     @Override protected void finalize() {
    367         try {
    368             super.finalize();
    369         } catch (Throwable t) {
    370             // for consistency with the RI, we must override Object.finalize() to
    371             // remove the throws clause.
    372             throw new AssertionError(t);
    373         }
    374     }
    375 }
    376