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.nio.ByteBuffer;
     21 import java.security.AlgorithmParameters;
     22 import java.security.InvalidAlgorithmParameterException;
     23 import java.security.InvalidKeyException;
     24 import java.security.InvalidParameterException;
     25 import java.security.Key;
     26 import java.security.NoSuchAlgorithmException;
     27 import java.security.NoSuchProviderException;
     28 import java.security.Provider;
     29 import java.security.SecureRandom;
     30 import java.security.Security;
     31 import java.security.cert.Certificate;
     32 import java.security.cert.X509Certificate;
     33 import java.security.spec.AlgorithmParameterSpec;
     34 import java.util.Set;
     35 import org.apache.harmony.crypto.internal.NullCipherSpi;
     36 import org.apache.harmony.security.fortress.Engine;
     37 
     38 /**
     39  * This class provides access to implementations of cryptographic ciphers for
     40  * encryption and decryption. Cipher classes can not be instantiated directly,
     41  * one has to call the Cipher's {@code getInstance} method with the name of a
     42  * requested transformation, optionally with a provider. A transformation
     43  * specifies an operation (or a set of operations) as a string in the form:
     44  * <ul>
     45  * <li><i>"algorithm/mode/padding"</i></li> or
     46  * <li><i>"algorithm"</i></li>
     47  * </ul>
     48  * <i>algorithm</i> is the name of a cryptographic algorithm, <i>mode</i> is the
     49  * name of a feedback mode and <i>padding</i> is the name of a padding scheme.
     50  * If <i>mode</i> and/or <i>padding</i> values are omitted, provider specific
     51  * default values will be used.
     52  * <p>
     53  * A valid transformation would be:
     54  * <ul>
     55  * {@code Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");}
     56  * </ul>
     57  * When a block cipher is requested in in stream cipher mode, the number of bits
     58  * to be processed at a time can be optionally specified by appending it to the
     59  * mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a
     60  * provider specific default value is used.
     61  */
     62 public class Cipher {
     63 
     64     /**
     65      * Constant for decryption operation mode.
     66      */
     67     public static final int DECRYPT_MODE = 2;
     68 
     69     /**
     70      * Constant for encryption operation mode.
     71      */
     72     public static final int ENCRYPT_MODE = 1;
     73 
     74     /**
     75      * Constant indicating that the key to be unwrapped is a private key.
     76      */
     77     public static final int PRIVATE_KEY = 2;
     78 
     79     /**
     80      * Constant indicating that the key to be unwrapped is a public key.
     81      */
     82     public static final int PUBLIC_KEY = 1;
     83 
     84     /**
     85      * Constant indicating that the key to be unwrapped is a secret key.
     86      */
     87     public static final int SECRET_KEY = 3;
     88 
     89     /**
     90      * Constant for key unwrapping operation mode.
     91      */
     92     public static final int UNWRAP_MODE = 4;
     93 
     94     /**
     95      * Constant for key wrapping operation mode.
     96      */
     97     public static final int WRAP_MODE = 3;
     98 
     99     private int mode;
    100 
    101     /**
    102      * The service name.
    103      */
    104     private static final String SERVICE = "Cipher";
    105 
    106     /**
    107      * Used to access common engine functionality.
    108      */
    109     private static final Engine ENGINE = new Engine(SERVICE);
    110 
    111     /**
    112      * The provider.
    113      */
    114     private Provider provider;
    115 
    116     /**
    117      * The SPI implementation.
    118      */
    119     private CipherSpi spiImpl;
    120 
    121     /**
    122      * The transformation.
    123      */
    124     private String transformation;
    125 
    126     private static SecureRandom secureRandom;
    127 
    128     /**
    129      * Creates a new Cipher instance.
    130      *
    131      * @param cipherSpi
    132      *            the implementation delegate of the cipher.
    133      * @param provider
    134      *            the provider of the implementation of this cipher.
    135      * @param transformation
    136      *            the name of the transformation that this cipher performs.
    137      * @throws NullPointerException
    138      *             if either cipherSpi is {@code null} or provider is {@code
    139      *             null} and {@code cipherSpi} is a {@code NullCipherSpi}.
    140      */
    141     protected Cipher(CipherSpi cipherSpi, Provider provider,
    142             String transformation) {
    143         if (cipherSpi == null) {
    144             throw new NullPointerException("cipherSpi == null");
    145         }
    146         if (!(cipherSpi instanceof NullCipherSpi) && provider == null) {
    147             throw new NullPointerException("provider == null");
    148         }
    149         this.provider = provider;
    150         this.transformation = transformation;
    151         this.spiImpl = cipherSpi;
    152     }
    153 
    154     /**
    155      * Creates a new Cipher for the specified transformation. The installed
    156      * providers are searched in order for an implementation of the specified
    157      * transformation. The first found provider providing the transformation is
    158      * used to create the cipher. If no provider is found an exception is
    159      * thrown.
    160      *
    161      * @param transformation
    162      *            the name of the transformation to create a cipher for.
    163      * @return a cipher for the requested transformation.
    164      * @throws NoSuchAlgorithmException
    165      *             if no installed provider can provide the
    166      *             <i>transformation</i>, or it is {@code null}, empty or in an
    167      *             invalid format.
    168      * @throws NoSuchPaddingException
    169      *             if no installed provider can provide the padding scheme in
    170      *             the <i>transformation</i>.
    171      */
    172     public static final Cipher getInstance(String transformation)
    173             throws NoSuchAlgorithmException, NoSuchPaddingException {
    174         return getCipher(transformation, null);
    175     }
    176 
    177     /**
    178      * Creates a new cipher for the specified transformation provided by the
    179      * specified provider.
    180      *
    181      * @param transformation
    182      *            the name of the transformation to create a cipher for.
    183      * @param provider
    184      *            the name of the provider to ask for the transformation.
    185      * @return a cipher for the requested transformation.
    186      * @throws NoSuchAlgorithmException
    187      *             if the specified provider can not provide the
    188      *             <i>transformation</i>, or it is {@code null}, empty or in an
    189      *             invalid format.
    190      * @throws NoSuchProviderException
    191      *             if no provider with the specified name can be found.
    192      * @throws NoSuchPaddingException
    193      *             if the requested padding scheme in the <i>transformation</i>
    194      *             is not available.
    195      * @throws IllegalArgumentException
    196      *             if the specified provider is {@code null}.
    197      */
    198     public static final Cipher getInstance(String transformation,
    199             String provider) throws NoSuchAlgorithmException,
    200             NoSuchProviderException, NoSuchPaddingException {
    201 
    202         if (provider == null) {
    203             throw new IllegalArgumentException("provider == null");
    204         }
    205 
    206         Provider p = Security.getProvider(provider);
    207         if (p == null) {
    208             throw new NoSuchProviderException("Provider not available: " + provider);
    209         }
    210         return getInstance(transformation, p);
    211     }
    212 
    213     /**
    214      * Creates a new cipher for the specified transformation.
    215      *
    216      * @param transformation
    217      *            the name of the transformation to create a cipher for.
    218      * @param provider
    219      *            the provider to ask for the transformation.
    220      * @return a cipher for the requested transformation.
    221      * @throws NoSuchAlgorithmException
    222      *             if the specified provider can not provide the
    223      *             <i>transformation</i>, or it is {@code null}, empty or in an
    224      *             invalid format.
    225      * @throws NoSuchPaddingException
    226      *             if the requested padding scheme in the <i>transformation</i>
    227      *             is not available.
    228      * @throws IllegalArgumentException
    229      *             if the provider is {@code null}.
    230      */
    231     public static final Cipher getInstance(String transformation,
    232             Provider provider) throws NoSuchAlgorithmException,
    233             NoSuchPaddingException {
    234         if (provider == null) {
    235             throw new IllegalArgumentException("provider == null");
    236         }
    237         Cipher c = getCipher(transformation, provider);
    238         return c;
    239     }
    240 
    241     private static NoSuchAlgorithmException invalidTransformation(String transformation)
    242             throws NoSuchAlgorithmException {
    243         throw new NoSuchAlgorithmException("Invalid transformation: " + transformation);
    244     }
    245 
    246     /**
    247      * Find appropriate Cipher according the specification rules
    248      *
    249      * @param transformation
    250      * @param provider
    251      * @return
    252      * @throws NoSuchAlgorithmException
    253      * @throws NoSuchPaddingException
    254      */
    255     private static synchronized Cipher getCipher(String transformation, Provider provider)
    256             throws NoSuchAlgorithmException, NoSuchPaddingException {
    257 
    258         if (transformation == null || transformation.isEmpty()) {
    259             throw invalidTransformation(transformation);
    260         }
    261 
    262         String[] transf = checkTransformation(transformation);
    263 
    264         boolean needSetPadding = false;
    265         boolean needSetMode = false;
    266         Object engineSpi = null;
    267         Provider engineProvider = provider;
    268         if (transf[1] == null && transf[2] == null) { // "algorithm"
    269             if (provider == null) {
    270                 Engine.SpiAndProvider sap = ENGINE.getInstance(transf[0], null);
    271                 engineSpi = sap.spi;
    272                 engineProvider = sap.provider;
    273             } else {
    274                 engineSpi = ENGINE.getInstance(transf[0], provider, null);
    275             }
    276         } else {
    277             String[] searchOrder = {
    278                 transf[0] + "/" + transf[1] + "/" + transf[2], // "algorithm/mode/padding"
    279                 transf[0] + "/" + transf[1], // "algorithm/mode"
    280                 transf[0] + "//" + transf[2], // "algorithm//padding"
    281                 transf[0] // "algorithm"
    282             };
    283             int i;
    284             for (i = 0; i < searchOrder.length; i++) {
    285                 try {
    286                     if (provider == null) {
    287                         Engine.SpiAndProvider sap = ENGINE.getInstance(searchOrder[i], null);
    288                         engineSpi = sap.spi;
    289                         engineProvider = sap.provider;
    290                     } else {
    291                         engineSpi = ENGINE.getInstance(searchOrder[i], provider, null);
    292                     }
    293                     break;
    294                 } catch (NoSuchAlgorithmException e) {
    295                     if (i == searchOrder.length-1) {
    296                         throw new NoSuchAlgorithmException(transformation, e);
    297                     }
    298                 }
    299             }
    300             switch (i) {
    301                 case 1: // "algorithm/mode"
    302                     needSetPadding = true;
    303                     break;
    304                 case 2: // "algorithm//padding"
    305                     needSetMode = true;
    306                     break;
    307                 case 3: // "algorithm"
    308                     needSetPadding = true;
    309                     needSetMode = true;
    310             }
    311         }
    312         if (engineSpi == null || engineProvider == null) {
    313             throw new NoSuchAlgorithmException(transformation);
    314         }
    315         if (!(engineSpi instanceof CipherSpi)) {
    316             throw new NoSuchAlgorithmException(engineSpi.getClass().getName());
    317         }
    318         CipherSpi cspi = (CipherSpi) engineSpi;
    319         Cipher c = new Cipher(cspi, engineProvider, transformation);
    320         if (needSetMode) {
    321             c.spiImpl.engineSetMode(transf[1]);
    322         }
    323         if (needSetPadding) {
    324             c.spiImpl.engineSetPadding(transf[2]);
    325         }
    326         return c;
    327     }
    328 
    329     private static String[] checkTransformation(String transformation) throws NoSuchAlgorithmException {
    330         // ignore an extra prefix / characters such as in
    331         // "/DES/CBC/PKCS5Paddin" http://b/3387688
    332         if (transformation.startsWith("/")) {
    333             transformation = transformation.substring(1);
    334         }
    335         // 'transformation' should be of the form "algorithm/mode/padding".
    336         String[] pieces = transformation.split("/");
    337         if (pieces.length > 3) {
    338             throw invalidTransformation(transformation);
    339         }
    340         // Empty or missing pieces are represented by null.
    341         String[] result = new String[3];
    342         for (int i = 0; i < pieces.length; ++i) {
    343             String piece = pieces[i].trim();
    344             if (!piece.isEmpty()) {
    345                 result[i] = piece;
    346             }
    347         }
    348         // You MUST specify an algorithm.
    349         if (result[0] == null) {
    350             throw invalidTransformation(transformation);
    351         }
    352         if (!(result[1] == null && result[2] == null) && (result[1] == null || result[2] == null)) {
    353             throw invalidTransformation(transformation);
    354         }
    355         return result;
    356     }
    357 
    358     /**
    359      * Returns the provider of this cipher instance.
    360      *
    361      * @return the provider of this cipher instance.
    362      */
    363     public final Provider getProvider() {
    364         return provider;
    365     }
    366 
    367     /**
    368      * Returns the name of the algorithm of this cipher instance.
    369      * <p>
    370      * This is the name of the <i>transformation</i> argument used in the
    371      * {@code getInstance} call creating this object.
    372      *
    373      * @return the name of the algorithm of this cipher instance.
    374      */
    375     public final String getAlgorithm() {
    376         return transformation;
    377     }
    378 
    379     /**
    380      * Returns this ciphers block size (in bytes).
    381      *
    382      * @return this ciphers block size.
    383      */
    384     public final int getBlockSize() {
    385         return spiImpl.engineGetBlockSize();
    386     }
    387 
    388     /**
    389      * Returns the length in bytes an output buffer needs to be when this cipher
    390      * is updated with {@code inputLen} bytes.
    391      *
    392      * @param inputLen
    393      *            the number of bytes of the input.
    394      * @return the output buffer length for the input length.
    395      * @throws IllegalStateException
    396      *             if this cipher instance is in an invalid state.
    397      */
    398     public final int getOutputSize(int inputLen) {
    399         if (mode == 0) {
    400             throw new IllegalStateException("Cipher has not yet been initialized");
    401         }
    402         return spiImpl.engineGetOutputSize(inputLen);
    403     }
    404 
    405     /**
    406      * Returns the <i>initialization vector</i> for this cipher instance.
    407      *
    408      * @return the <i>initialization vector</i> for this cipher instance.
    409      */
    410     public final byte[] getIV() {
    411         return spiImpl.engineGetIV();
    412     }
    413 
    414     /**
    415      * Returns the parameters that where used to create this cipher instance.
    416      * <p>
    417      * These may be a the same parameters that were used to create this cipher
    418      * instance, or may be a combination of default and random parameters,
    419      * depending on the underlying cipher implementation.
    420      *
    421      * @return the parameters that where used to create this cipher instance, or
    422      *         {@code null} if this cipher instance does not have any
    423      *         parameters.
    424      */
    425     public final AlgorithmParameters getParameters() {
    426         return spiImpl.engineGetParameters();
    427     }
    428 
    429     /**
    430      * Returns the exemption mechanism associated with this cipher.
    431      *
    432      * @return currently {@code null}
    433      */
    434     public final ExemptionMechanism getExemptionMechanism() {
    435         //FIXME implement getExemptionMechanism
    436 
    437         //        try {
    438         //            return ExemptionMechanism.getInstance(transformation, provider);
    439         //        } catch (NoSuchAlgorithmException e) {
    440         return null;
    441         //        }
    442 
    443     }
    444 
    445     /**
    446      * Initializes this cipher instance with the specified key.
    447      * <p>
    448      * The cipher is initialized for the specified operational mode (one of:
    449      * encryption, decryption, key wrapping or key unwrapping) depending on
    450      * {@code opmode}.
    451      * <p>
    452      * If this cipher instance needs any algorithm parameters or random values
    453      * that the specified key can not provide, the underlying implementation of
    454      * this cipher is supposed to generate the required parameters (using its
    455      * provider or random values).
    456      * <p>
    457      * When a cipher instance is initialized by a call to any of the {@code
    458      * init} methods, the state of the instance is overridden, meaning that it
    459      * is equivalent to creating a new instance and calling its {@code init}
    460      * method.
    461      *
    462      * @param opmode
    463      *            the operation this cipher instance should be initialized for
    464      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    465      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    466      * @param key
    467      *            the input key for the operation.
    468      * @throws InvalidKeyException
    469      *             if the specified key can not be used to initialize this
    470      *             cipher instance.
    471      */
    472     public final void init(int opmode, Key key) throws InvalidKeyException {
    473         if (secureRandom == null) {
    474             // In theory it might be thread-unsafe but in the given case it's OK
    475             // since it does not matter which SecureRandom instance is passed
    476             // to the init()
    477             secureRandom = new SecureRandom();
    478         }
    479         init(opmode, key, secureRandom);
    480     }
    481 
    482     /**
    483      * Initializes this cipher instance with the specified key and a source of
    484      * randomness.
    485      * <p>
    486      * The cipher is initialized for the specified operational mode (one of:
    487      * encryption, decryption, key wrapping or key unwrapping) depending on
    488      * {@code opmode}.
    489      * <p>
    490      * If this cipher instance needs any algorithm parameters or random values
    491      * that the specified key can not provide, the underlying implementation of
    492      * this cipher is supposed to generate the required parameters (using its
    493      * provider or random values). Random values are generated using {@code
    494      * random};
    495      * <p>
    496      * When a cipher instance is initialized by a call to any of the {@code
    497      * init} methods, the state of the instance is overridden, means it is
    498      * equivalent to creating a new instance and calling it {@code init} method.
    499      *
    500      * @param opmode
    501      *            the operation this cipher instance should be initialized for
    502      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    503      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    504      * @param key
    505      *            the input key for the operation.
    506      * @param random
    507      *            the source of randomness to use.
    508      * @throws InvalidKeyException
    509      *             if the specified key can not be used to initialize this
    510      *             cipher instance.
    511      * @throws InvalidParameterException
    512      *             if the specified opmode is invalid.
    513      */
    514     public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
    515         checkMode(opmode);
    516         //        FIXME InvalidKeyException
    517         //        if keysize exceeds the maximum allowable keysize
    518         //        (jurisdiction policy files)
    519         spiImpl.engineInit(opmode, key, random);
    520         mode = opmode;
    521     }
    522 
    523     private void checkMode(int mode) {
    524         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE
    525             && mode != UNWRAP_MODE && mode != WRAP_MODE) {
    526             throw new InvalidParameterException("Invalid mode: " + mode);
    527         }
    528     }
    529 
    530     /**
    531      * Initializes this cipher instance with the specified key and algorithm
    532      * parameters.
    533      * <p>
    534      * The cipher is initialized for the specified operational mode (one of:
    535      * encryption, decryption, key wrapping or key unwrapping).
    536      * <p>
    537      * If this cipher instance needs any algorithm parameters and {@code params}
    538      * is {@code null}, the underlying implementation of this cipher is supposed
    539      * to generate the required parameters (using its provider or random
    540      * values).
    541      * <p>
    542      * When a cipher instance is initialized by a call to any of the {@code
    543      * init} methods, the state of the instance is overridden, means it is
    544      * equivalent to creating a new instance and calling it {@code init} method.
    545      *
    546      * @param opmode
    547      *            the operation this cipher instance should be initialized for
    548      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    549      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    550      * @param key
    551      *            the input key for the operation.
    552      * @param params
    553      *            the algorithm parameters.
    554      * @throws InvalidKeyException
    555      *             if the specified key can not be used to initialize this
    556      *             cipher instance.
    557      * @throws InvalidAlgorithmParameterException
    558      *             it the specified parameters are inappropriate for this
    559      *             cipher.
    560      */
    561     public final void init(int opmode, Key key, AlgorithmParameterSpec params)
    562             throws InvalidKeyException, InvalidAlgorithmParameterException {
    563         if (secureRandom == null) {
    564             secureRandom = new SecureRandom();
    565         }
    566         init(opmode, key, params, secureRandom);
    567     }
    568 
    569     /**
    570      * Initializes this cipher instance with the specified key, algorithm
    571      * parameters and a source of randomness.
    572      * <p>
    573      * The cipher is initialized for the specified operational mode (one of:
    574      * encryption, decryption, key wrapping or key unwrapping) depending on
    575      * {@code opmode}.
    576      * <p>
    577      * If this cipher instance needs any algorithm parameters and {@code params}
    578      * is {@code null}, the underlying implementation of this cipher is supposed
    579      * to generate the required parameters (using its provider or random
    580      * values). Random values are generated using {@code random};
    581      * <p>
    582      * When a cipher instance is initialized by a call to any of the {@code
    583      * init} methods, the state of the instance is overridden, meaning that it
    584      * is equivalent to creating a new instance and calling it {@code init}
    585      * method.
    586      *
    587      * @param opmode
    588      *            the operation this cipher instance should be initialized for
    589      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    590      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    591      * @param key
    592      *            the input key for the operation.
    593      * @param params
    594      *            the algorithm parameters.
    595      * @param random
    596      *            the source of randomness to use.
    597      * @throws InvalidKeyException
    598      *             if the specified key can not be used to initialize this
    599      *             cipher instance.
    600      * @throws InvalidAlgorithmParameterException
    601      *             it the specified parameters are inappropriate for this
    602      *             cipher.
    603      * @throws InvalidParameterException
    604      *             if the specified {@code opmode} is invalid.
    605      */
    606     public final void init(int opmode, Key key, AlgorithmParameterSpec params,
    607             SecureRandom random) throws InvalidKeyException,
    608             InvalidAlgorithmParameterException {
    609         checkMode(opmode);
    610         //        FIXME InvalidKeyException
    611         //        if keysize exceeds the maximum allowable keysize
    612         //        (jurisdiction policy files)
    613         //        FIXME InvalidAlgorithmParameterException
    614         //        cryptographic strength exceed the legal limits
    615         //        (jurisdiction policy files)
    616         spiImpl.engineInit(opmode, key, params, random);
    617         mode = opmode;
    618     }
    619 
    620     /**
    621      * Initializes this cipher instance with the specified key and algorithm
    622      * parameters.
    623      * <p>
    624      * The cipher is initialized for the specified operation (one of:
    625      * encryption, decryption, key wrapping or key unwrapping) depending on
    626      * {@code opmode}.
    627      * <p>
    628      * If this cipher instance needs any algorithm parameters and {@code params}
    629      * is {@code null}, the underlying implementation of this cipher is supposed
    630      * to generate the required parameters (using its provider or random
    631      * values).
    632      * <p>
    633      * When a cipher instance is initialized by a call to any of the {@code
    634      * init} methods, the state of the instance is overridden, meaning that it
    635      * is equivalent to creating a new instance and calling it {@code init}
    636      * method.
    637      *
    638      * @param opmode
    639      *            the operation this cipher instance should be initialized for
    640      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    641      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    642      * @param key
    643      *            the input key for the operation.
    644      * @param params
    645      *            the algorithm parameters.
    646      * @throws InvalidKeyException
    647      *             if the specified key can not be used to initialize this
    648      *             cipher instance.
    649      * @throws InvalidAlgorithmParameterException
    650      *             it the specified parameters are inappropriate for this
    651      *             cipher.
    652      */
    653     public final void init(int opmode, Key key, AlgorithmParameters params)
    654             throws InvalidKeyException, InvalidAlgorithmParameterException {
    655         if (secureRandom == null) {
    656             secureRandom = new SecureRandom();
    657         }
    658         init(opmode, key, params, secureRandom);
    659     }
    660 
    661     /**
    662      * Initializes this cipher instance with the specified key, algorithm
    663      * parameters and a source of randomness.
    664      * <p>
    665      * The cipher will be initialized for the specified operation (one of:
    666      * encryption, decryption, key wrapping or key unwrapping) depending on
    667      * {@code opmode}.
    668      * <p>
    669      * If this cipher instance needs any algorithm parameters and {@code params}
    670      * is {@code null}, the underlying implementation of this cipher is supposed
    671      * to generate the required parameters (using its provider or random
    672      * values). Random values are generated using {@code random}.
    673      * <p>
    674      * When a cipher instance is initialized by a call to any of the {@code
    675      * init} methods, the state of the instance is overridden, means it is
    676      * equivalent to creating a new instance and calling it {@code init} method.
    677      *
    678      * @param opmode
    679      *            the operation this cipher instance should be initialized for
    680      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    681      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    682      * @param key
    683      *            the input key for the operation.
    684      * @param params
    685      *            the algorithm parameters.
    686      * @param random
    687      *            the source of randomness to use.
    688      * @throws InvalidKeyException
    689      *             if the specified key can not be used to initialize this
    690      *             cipher instance.
    691      * @throws InvalidAlgorithmParameterException
    692      *             if the specified parameters are inappropriate for this
    693      *             cipher.
    694      * @throws InvalidParameterException
    695      *             if the specified {@code opmode} is invalid.
    696      */
    697     public final void init(int opmode, Key key, AlgorithmParameters params,
    698             SecureRandom random) throws InvalidKeyException,
    699             InvalidAlgorithmParameterException {
    700         checkMode(opmode);
    701         //        FIXME InvalidKeyException
    702         //        if keysize exceeds the maximum allowable keysize
    703         //        (jurisdiction policy files)
    704         //        FIXME InvalidAlgorithmParameterException
    705         //        cryptographic strength exceed the legal limits
    706         //        (jurisdiction policy files)
    707         spiImpl.engineInit(opmode, key, params, random);
    708         mode = opmode;
    709     }
    710 
    711     /**
    712      * Initializes this cipher instance with the public key from the specified
    713      * certificate.
    714      * <p>
    715      * The cipher will be initialized for the specified operation (one of:
    716      * encryption, decryption, key wrapping or key unwrapping) depending on
    717      * {@code opmode}.
    718      * <p>
    719      * It the type of the certificate is X.509 and the certificate has a <i>key
    720      * usage</i> extension field marked as critical, the specified {@code
    721      * opmode} has the be enabled for this key, otherwise an {@code
    722      * InvalidKeyException} is thrown.
    723      * <p>
    724      * If this cipher instance needs any algorithm parameters that the key in
    725      * the certificate can not provide, the underlying implementation of this
    726      * cipher is supposed to generate the required parameters (using its
    727      * provider or random values).
    728      * <p>
    729      * When a cipher instance is initialized by a call to any of the {@code
    730      * init} methods, the state of the instance is overridden, means it is
    731      * equivalent to creating a new instance and calling it {@code init} method.
    732      *
    733      * @param opmode
    734      *            the operation this cipher instance should be initialized for
    735      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    736      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    737      * @param certificate
    738      *            the certificate.
    739      * @throws InvalidKeyException
    740      *             if the public key in the certificate can not be used to
    741      *             initialize this cipher instance.
    742      */
    743     public final void init(int opmode, Certificate certificate)
    744             throws InvalidKeyException {
    745         if (secureRandom == null) {
    746             secureRandom = new SecureRandom();
    747         }
    748         init(opmode, certificate, secureRandom);
    749     }
    750 
    751     /**
    752      * Initializes this cipher instance with the public key from the specified
    753      * certificate and a source of randomness.
    754      * <p>
    755      * The cipher will be initialized for the specified operation (one of:
    756      * encryption, decryption, key wrapping or key unwrapping) depending on
    757      * {@code opmode}.
    758      * <p>
    759      * It the type of the certificate is X.509 and the certificate has a <i>key
    760      * usage</i> extension field marked as critical, the specified {@code
    761      * opmode} has the be enabled for this key, otherwise an {@code
    762      * InvalidKeyException} is thrown.
    763      * <p>
    764      * If this cipher instance needs any algorithm parameters that the key in
    765      * the certificate can not provide, the underlying implementation of this
    766      * cipher is supposed to generate the required parameters (using its
    767      * provider or random values). Random values are generated using {@code
    768      * random}.
    769      * <p>
    770      * When a cipher instance is initialized by a call to any of the {@code
    771      * init} methods, the state of the instance is overridden, means it is
    772      * equivalent to creating a new instance and calling it {@code init} method.
    773      *
    774      * @param opmode
    775      *            the operation this cipher instance should be initialized for
    776      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    777      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    778      * @param certificate
    779      *            the certificate.
    780      * @param random
    781      *            the source of randomness to be used.
    782      * @throws InvalidKeyException
    783      *             if the public key in the certificate can not be used to
    784      *             initialize this cipher instance.
    785      */
    786     public final void init(int opmode, Certificate certificate,
    787             SecureRandom random) throws InvalidKeyException {
    788         checkMode(opmode);
    789         if (certificate instanceof X509Certificate) {
    790             Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
    791             boolean critical = false;
    792             if (ce != null && !ce.isEmpty()) {
    793                 for (String oid : ce) {
    794                     if (oid.equals("2.5.29.15")) { // KeyUsage OID = 2.5.29.15
    795                         critical = true;
    796                         break;
    797                     }
    798                 }
    799                 if (critical) {
    800                     boolean[] keyUsage = ((X509Certificate) certificate).getKeyUsage();
    801                     // As specified in RFC 3280:
    802                     //   Internet X.509 Public Key Infrastructure
    803                     //   Certificate and Certificate Revocation List (CRL) Profile.
    804                     // Section 4.2.1.3  Key Usage
    805                     // http://www.ietf.org/rfc/rfc3280.txt
    806                     //
    807                     // KeyUsage ::= BIT STRING {digitalSignature (0),
    808                     //                          nonRepudiation   (1),
    809                     //                          keyEncipherment  (2),
    810                     //                          dataEncipherment (3),
    811                     //                          keyAgreement     (4),
    812                     //                          keyCertSign      (5),
    813                     //                          cRLSign          (6),
    814                     //                          encipherOnly     (7),
    815                     //                          decipherOnly     (8) }
    816                     if (keyUsage != null) {
    817                         if (opmode == ENCRYPT_MODE && !keyUsage[3]) {
    818                             throw new InvalidKeyException("The public key in the certificate "
    819                                                           + "cannot be used for ENCRYPT_MODE");
    820                         } else if (opmode == WRAP_MODE && !keyUsage[2]) {
    821                             throw new InvalidKeyException("The public key in the certificate "
    822                                                           + "cannot be used for WRAP_MODE");
    823                         }
    824                     }
    825                 }
    826             }
    827         }
    828         //        FIXME InvalidKeyException
    829         //        if keysize exceeds the maximum allowable keysize
    830         //        (jurisdiction policy files)
    831         spiImpl.engineInit(opmode, certificate.getPublicKey(), random);
    832         mode = opmode;
    833     }
    834 
    835     /**
    836      * Continues a multi-part transformation (encryption or decryption). The
    837      * transformed bytes are returned.
    838      *
    839      * @param input
    840      *            the input bytes to transform.
    841      * @return the transformed bytes in a new buffer, or {@code null} if the
    842      *         input has zero length.
    843      * @throws IllegalStateException
    844      *             if this cipher instance is not initialized for encryption or
    845      *             decryption.
    846      * @throws IllegalArgumentException
    847      *             if the input is {@code null}.
    848      */
    849     public final byte[] update(byte[] input) {
    850         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
    851             throw new IllegalStateException();
    852         }
    853         if (input == null) {
    854             throw new IllegalArgumentException("input == null");
    855         }
    856         if (input.length == 0) {
    857             return null;
    858         }
    859         return spiImpl.engineUpdate(input, 0, input.length);
    860     }
    861 
    862     /**
    863      * Continues a multi-part transformation (encryption or decryption). The
    864      * transformed bytes are returned.
    865      *
    866      * @param input
    867      *            the input bytes to transform.
    868      * @param inputOffset
    869      *            the offset in the input to start.
    870      * @param inputLen
    871      *            the length of the input to transform.
    872      * @return the transformed bytes in a new buffer, or {@code null} if the
    873      *         input has zero length.
    874      * @throws IllegalStateException
    875      *             if this cipher instance is not initialized for encryption or
    876      *             decryption.
    877      * @throws IllegalArgumentException
    878      *             if the input is {@code null}, or if {@code inputOffset} and
    879      *             {@code inputLen} do not specify a valid chunk in the input
    880      *             buffer.
    881      */
    882     public final byte[] update(byte[] input, int inputOffset, int inputLen) {
    883         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
    884             throw new IllegalStateException();
    885         }
    886         if (input == null) {
    887             throw new IllegalArgumentException("input == null");
    888         }
    889         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
    890         if (input.length == 0) {
    891             return null;
    892         }
    893         return spiImpl.engineUpdate(input, inputOffset, inputLen);
    894     }
    895 
    896     private static void checkInputOffsetAndCount(int inputArrayLength,
    897                                                  int inputOffset,
    898                                                  int inputLen) {
    899         if ((inputOffset | inputLen) < 0
    900                 || inputOffset > inputArrayLength
    901                 || inputArrayLength - inputOffset < inputLen) {
    902             throw new IllegalArgumentException("input.length=" + inputArrayLength
    903                                                + "; inputOffset=" + inputOffset
    904                                                + "; inputLen=" + inputLen);
    905         }
    906     }
    907 
    908     /**
    909      * Continues a multi-part transformation (encryption or decryption). The
    910      * transformed bytes are stored in the {@code output} buffer.
    911      * <p>
    912      * If the size of the {@code output} buffer is too small to hold the result,
    913      * a {@code ShortBufferException} is thrown. Use
    914      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
    915      * output buffer.
    916      *
    917      * @param input
    918      *            the input bytes to transform.
    919      * @param inputOffset
    920      *            the offset in the input to start.
    921      * @param inputLen
    922      *            the length of the input to transform.
    923      * @param output
    924      *            the output buffer.
    925      * @return the number of bytes placed in output.
    926      * @throws ShortBufferException
    927      *             if the size of the {@code output} buffer is too small.
    928      * @throws IllegalStateException
    929      *             if this cipher instance is not initialized for encryption or
    930      *             decryption.
    931      * @throws IllegalArgumentException
    932      *             if the input is {@code null}, the output is {@code null}, or
    933      *             if {@code inputOffset} and {@code inputLen} do not specify a
    934      *             valid chunk in the input buffer.
    935      */
    936     public final int update(byte[] input, int inputOffset, int inputLen,
    937             byte[] output) throws ShortBufferException {
    938         return update(input, inputOffset, inputLen, output, 0);
    939     }
    940 
    941     /**
    942      * Continues a multi-part transformation (encryption or decryption). The
    943      * transformed bytes are stored in the {@code output} buffer.
    944      * <p>
    945      * If the size of the {@code output} buffer is too small to hold the result,
    946      * a {@code ShortBufferException} is thrown. Use
    947      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
    948      * output buffer.
    949      *
    950      * @param input
    951      *            the input bytes to transform.
    952      * @param inputOffset
    953      *            the offset in the input to start.
    954      * @param inputLen
    955      *            the length of the input to transform.
    956      * @param output
    957      *            the output buffer.
    958      * @param outputOffset
    959      *            the offset in the output buffer.
    960      * @return the number of bytes placed in output.
    961      * @throws ShortBufferException
    962      *             if the size of the {@code output} buffer is too small.
    963      * @throws IllegalStateException
    964      *             if this cipher instance is not initialized for encryption or
    965      *             decryption.
    966      * @throws IllegalArgumentException
    967      *             if the input is {@code null}, the output is {@code null}, or
    968      *             if {@code inputOffset} and {@code inputLen} do not specify a
    969      *             valid chunk in the input buffer.
    970      */
    971     public final int update(byte[] input, int inputOffset, int inputLen,
    972             byte[] output, int outputOffset) throws ShortBufferException {
    973         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
    974             throw new IllegalStateException();
    975         }
    976         if (input == null) {
    977             throw new IllegalArgumentException("input == null");
    978         }
    979         if (output == null) {
    980             throw new IllegalArgumentException("output == null");
    981         }
    982         if (outputOffset < 0) {
    983             throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
    984         }
    985         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
    986         if (input.length == 0) {
    987             return 0;
    988         }
    989         return spiImpl.engineUpdate(input, inputOffset, inputLen, output,
    990                 outputOffset);
    991     }
    992 
    993     /**
    994      * Continues a multi-part transformation (encryption or decryption). The
    995      * {@code input.remaining()} bytes starting at {@code input.position()} are
    996      * transformed and stored in the {@code output} buffer.
    997      * <p>
    998      * If the {@code output.remaining()} is too small to hold the transformed
    999      * bytes a {@code ShortBufferException} is thrown. Use
   1000      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
   1001      * output buffer.
   1002      *
   1003      * @param input
   1004      *            the input buffer to transform.
   1005      * @param output
   1006      *            the output buffer to store the result within.
   1007      * @return the number of bytes stored in the output buffer.
   1008      * @throws ShortBufferException
   1009      *             if the size of the {@code output} buffer is too small.
   1010      * @throws IllegalStateException
   1011      *             if this cipher instance is not initialized for encryption or
   1012      *             decryption.
   1013      * @throws IllegalArgumentException
   1014      *             if the input buffer and the output buffer are the identical
   1015      *             object.
   1016      */
   1017     public final int update(ByteBuffer input, ByteBuffer output)
   1018             throws ShortBufferException {
   1019         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1020             throw new IllegalStateException();
   1021         }
   1022         if (input == output) {
   1023             throw new IllegalArgumentException("input == output");
   1024         }
   1025         return spiImpl.engineUpdate(input, output);
   1026     }
   1027 
   1028     /**
   1029      * Finishes a multi-part transformation (encryption or decryption).
   1030      * <p>
   1031      * Processes any bytes that may have been buffered in previous {@code
   1032      * update} calls.
   1033      *
   1034      * @return the final bytes from the transformation.
   1035      * @throws IllegalBlockSizeException
   1036      *             if the size of the resulting bytes is not a multiple of the
   1037      *             cipher block size.
   1038      * @throws BadPaddingException
   1039      *             if the padding of the data does not match the padding scheme.
   1040      * @throws IllegalStateException
   1041      *             if this cipher instance is not initialized for encryption or
   1042      *             decryption.
   1043      */
   1044     public final byte[] doFinal() throws IllegalBlockSizeException,
   1045             BadPaddingException {
   1046         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1047             throw new IllegalStateException();
   1048         }
   1049         return spiImpl.engineDoFinal(null, 0, 0);
   1050     }
   1051 
   1052     /**
   1053      * Finishes a multi-part transformation (encryption or decryption).
   1054      * <p>
   1055      * Processes any bytes that may have been buffered in previous {@code
   1056      * update} calls.
   1057      * <p>
   1058      * The final transformed bytes are stored in the {@code output} buffer.
   1059      *
   1060      * @param output
   1061      *            the output buffer.
   1062      * @param outputOffset
   1063      *            the offset in the output buffer.
   1064      * @return the number of bytes placed in the output buffer.
   1065      * @throws IllegalBlockSizeException
   1066      *             if the size of the resulting bytes is not a multiple of the
   1067      *             cipher block size.
   1068      * @throws ShortBufferException
   1069      *             if the size of the {@code output} buffer is too small.
   1070      * @throws BadPaddingException
   1071      *             if the padding of the data does not match the padding scheme.
   1072      * @throws IllegalStateException
   1073      *             if this cipher instance is not initialized for encryption or
   1074      *             decryption.
   1075      */
   1076     public final int doFinal(byte[] output, int outputOffset)
   1077             throws IllegalBlockSizeException, ShortBufferException,
   1078             BadPaddingException {
   1079         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1080             throw new IllegalStateException();
   1081         }
   1082         if (outputOffset < 0) {
   1083             throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
   1084         }
   1085         return spiImpl.engineDoFinal(null, 0, 0, output, outputOffset);
   1086     }
   1087 
   1088     /**
   1089      * Finishes a multi-part transformation (encryption or decryption).
   1090      * <p>
   1091      * Processes the bytes in {@code input} buffer, and any bytes that have been
   1092      * buffered in previous {@code update} calls.
   1093      *
   1094      * @param input
   1095      *            the input buffer.
   1096      * @return the final bytes from the transformation.
   1097      * @throws IllegalBlockSizeException
   1098      *             if the size of the resulting bytes is not a multiple of the
   1099      *             cipher block size.
   1100      * @throws BadPaddingException
   1101      *             if the padding of the data does not match the padding scheme.
   1102      * @throws IllegalStateException
   1103      *             if this cipher instance is not initialized for encryption or
   1104      *             decryption.
   1105      */
   1106     public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
   1107             BadPaddingException {
   1108         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1109             throw new IllegalStateException();
   1110         }
   1111         return spiImpl.engineDoFinal(input, 0, input.length);
   1112     }
   1113 
   1114     /**
   1115      * Finishes a multi-part transformation (encryption or decryption).
   1116      * <p>
   1117      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
   1118      * inputOffset}, and any bytes that have been buffered in previous {@code
   1119      * update} calls.
   1120      *
   1121      * @param input
   1122      *            the input buffer.
   1123      * @param inputOffset
   1124      *            the offset in the input buffer.
   1125      * @param inputLen
   1126      *            the length of the input
   1127      * @return the final bytes from the transformation.
   1128      * @throws IllegalBlockSizeException
   1129      *             if the size of the resulting bytes is not a multiple of the
   1130      *             cipher block size.
   1131      * @throws BadPaddingException
   1132      *             if the padding of the data does not match the padding scheme.
   1133      * @throws IllegalStateException
   1134      *             if this cipher instance is not initialized for encryption or
   1135      *             decryption.
   1136      * @throws IllegalArgumentException
   1137      *             if {@code inputOffset} and {@code inputLen} do not specify an
   1138      *             valid chunk in the input buffer.
   1139      */
   1140     public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
   1141             throws IllegalBlockSizeException, BadPaddingException {
   1142         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1143             throw new IllegalStateException();
   1144         }
   1145         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
   1146         return spiImpl.engineDoFinal(input, inputOffset, inputLen);
   1147     }
   1148 
   1149     /**
   1150      * Finishes a multi-part transformation (encryption or decryption).
   1151      * <p>
   1152      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
   1153      * inputOffset}, and any bytes that have been buffered in previous {@code
   1154      * update} calls.
   1155      *
   1156      * @param input
   1157      *            the input buffer.
   1158      * @param inputOffset
   1159      *            the offset in the input buffer.
   1160      * @param inputLen
   1161      *            the length of the input.
   1162      * @param output
   1163      *            the output buffer for the transformed bytes.
   1164      * @return the number of bytes placed in the output buffer.
   1165      * @throws ShortBufferException
   1166      *             if the size of the {@code output} buffer is too small.
   1167      * @throws IllegalBlockSizeException
   1168      *             if the size of the resulting bytes is not a multiple of the
   1169      *             cipher block size.
   1170      * @throws BadPaddingException
   1171      *             if the padding of the data does not match the padding scheme.
   1172      * @throws IllegalStateException
   1173      *             if this cipher instance is not initialized for encryption or
   1174      *             decryption.
   1175      * @throws IllegalArgumentException
   1176      *             if {@code inputOffset} and {@code inputLen} do not specify an
   1177      *             valid chunk in the input buffer.
   1178      */
   1179     public final int doFinal(byte[] input, int inputOffset, int inputLen,
   1180             byte[] output) throws ShortBufferException,
   1181             IllegalBlockSizeException, BadPaddingException {
   1182         return doFinal(input, inputOffset, inputLen, output, 0);
   1183     }
   1184 
   1185     /**
   1186      * Finishes a multi-part transformation (encryption or decryption).
   1187      * <p>
   1188      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
   1189      * inputOffset}, and any bytes that have been buffered in previous {@code
   1190      * update} calls.
   1191      *
   1192      * @param input
   1193      *            the input buffer.
   1194      * @param inputOffset
   1195      *            the offset in the input buffer.
   1196      * @param inputLen
   1197      *            the length of the input.
   1198      * @param output
   1199      *            the output buffer for the transformed bytes.
   1200      * @param outputOffset
   1201      *            the offset in the output buffer.
   1202      * @return the number of bytes placed in the output buffer.
   1203      * @throws ShortBufferException
   1204      *             if the size of the {@code output} buffer is too small.
   1205      * @throws IllegalBlockSizeException
   1206      *             if the size of the resulting bytes is not a multiple of the
   1207      *             cipher block size.
   1208      * @throws BadPaddingException
   1209      *             if the padding of the data does not match the padding scheme.
   1210      * @throws IllegalStateException
   1211      *             if this cipher instance is not initialized for encryption or
   1212      *             decryption.
   1213      * @throws IllegalArgumentException
   1214      *             if {@code inputOffset} and {@code inputLen} do not specify an
   1215      *             valid chunk in the input buffer.
   1216      */
   1217     public final int doFinal(byte[] input, int inputOffset, int inputLen,
   1218             byte[] output, int outputOffset) throws ShortBufferException,
   1219             IllegalBlockSizeException, BadPaddingException {
   1220         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1221             throw new IllegalStateException();
   1222         }
   1223         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
   1224         return spiImpl.engineDoFinal(input, inputOffset, inputLen, output,
   1225                 outputOffset);
   1226     }
   1227 
   1228     /**
   1229      * Finishes a multi-part transformation (encryption or decryption).
   1230      * <p>
   1231      * Processes the {@code input.remaining()} bytes in {@code input} buffer at
   1232      * {@code input.position()}, and any bytes that have been buffered in
   1233      * previous {@code update} calls. The transformed bytes are placed into
   1234      * {@code output} buffer.
   1235      *
   1236      * @param input
   1237      *            the input buffer.
   1238      * @param output
   1239      *            the output buffer.
   1240      * @return the number of bytes placed into the output buffer.
   1241      * @throws ShortBufferException
   1242      *             if the size of the {@code output} buffer is too small.
   1243      * @throws IllegalBlockSizeException
   1244      *             if the size of the resulting bytes is not a multiple of the
   1245      *             cipher block size.
   1246      * @throws BadPaddingException
   1247      *             if the padding of the data does not match the padding scheme.
   1248      * @throws IllegalArgumentException
   1249      *             if the input buffer and the output buffer are the same
   1250      *             object.
   1251      * @throws IllegalStateException
   1252      *             if this cipher instance is not initialized for encryption or
   1253      *             decryption.
   1254      */
   1255     public final int doFinal(ByteBuffer input, ByteBuffer output)
   1256             throws ShortBufferException, IllegalBlockSizeException,
   1257             BadPaddingException {
   1258         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
   1259             throw new IllegalStateException();
   1260         }
   1261         if (input == output) {
   1262             throw new IllegalArgumentException("input == output");
   1263         }
   1264         return spiImpl.engineDoFinal(input, output);
   1265     }
   1266 
   1267     /**
   1268      * Wraps a key using this cipher instance.
   1269      *
   1270      * @param key
   1271      *            the key to wrap.
   1272      * @return the wrapped key.
   1273      * @throws IllegalBlockSizeException
   1274      *             if the size of the resulting bytes is not a multiple of the
   1275      *             cipher block size.
   1276      * @throws InvalidKeyException
   1277      *             if this cipher instance can not wrap this key.
   1278      * @throws IllegalStateException
   1279      *             if this cipher instance is not initialized for wrapping.
   1280      */
   1281     public final byte[] wrap(Key key) throws IllegalBlockSizeException,
   1282             InvalidKeyException {
   1283         if (mode != WRAP_MODE) {
   1284             throw new IllegalStateException();
   1285         }
   1286         return spiImpl.engineWrap(key);
   1287     }
   1288 
   1289     /**
   1290      * Unwraps a key using this cipher instance.
   1291      *
   1292      * @param wrappedKey
   1293      *            the wrapped key to unwrap.
   1294      * @param wrappedKeyAlgorithm
   1295      *            the algorithm for the wrapped key.
   1296      * @param wrappedKeyType
   1297      *            the type of the wrapped key (one of: {@code SECRET_KEY
   1298      *            <code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY})
   1299      * @return the unwrapped key
   1300      * @throws InvalidKeyException
   1301      *             if the {@code wrappedKey} can not be unwrapped to a key of
   1302      *             type {@code wrappedKeyType} for the {@code
   1303      *             wrappedKeyAlgorithm}.
   1304      * @throws NoSuchAlgorithmException
   1305      *             if no provider can be found that can create a key of type
   1306      *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
   1307      * @throws IllegalStateException
   1308      *             if this cipher instance is not initialized for unwrapping.
   1309      */
   1310     public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
   1311             int wrappedKeyType) throws InvalidKeyException,
   1312             NoSuchAlgorithmException {
   1313         if (mode != UNWRAP_MODE) {
   1314             throw new IllegalStateException();
   1315         }
   1316         return spiImpl.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
   1317                 wrappedKeyType);
   1318     }
   1319 
   1320     /**
   1321      * Returns the maximum key length for the specified transformation.
   1322      *
   1323      * @param transformation
   1324      *            the transformation name.
   1325      * @return the maximum key length, currently {@code Integer.MAX_VALUE}.
   1326      * @throws NoSuchAlgorithmException
   1327      *             if no provider for the specified {@code transformation} can
   1328      *             be found.
   1329      * @throws NullPointerException
   1330      *             if {@code transformation} is {@code null}.
   1331      */
   1332     public static final int getMaxAllowedKeyLength(String transformation)
   1333             throws NoSuchAlgorithmException {
   1334         if (transformation == null) {
   1335             throw new NullPointerException("transformation == null");
   1336         }
   1337         checkTransformation(transformation);
   1338         //FIXME jurisdiction policy files
   1339         return Integer.MAX_VALUE;
   1340     }
   1341 
   1342     /**
   1343      * Returns the maximum cipher parameter value for the specified
   1344      * transformation. If there is no maximum limit, {@code null} is returned.
   1345      *
   1346      * @param transformation
   1347      *            the transformation name.
   1348      * @return a parameter spec holding the maximum value or {@code null}.
   1349      *         Currently {@code null}.
   1350      * @throws NoSuchAlgorithmException
   1351      *             if no provider for the specified {@code transformation} can
   1352      *             be found.
   1353      * @throws NullPointerException
   1354      *             if {@code transformation} is {@code null}.
   1355      */
   1356     public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
   1357             String transformation) throws NoSuchAlgorithmException {
   1358         if (transformation == null) {
   1359             throw new NullPointerException("transformation == null");
   1360         }
   1361         checkTransformation(transformation);
   1362         //FIXME jurisdiction policy files
   1363         return null;
   1364     }
   1365 }
   1366