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.Key;
     25 import java.security.NoSuchAlgorithmException;
     26 import java.security.SecureRandom;
     27 import java.security.spec.AlgorithmParameterSpec;
     28 
     29 /**
     30  * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
     31  * cryptographic ciphers.
     32  * <p>
     33  * Implementers of cryptographic ciphers must implement all the abstract methods
     34  * for every cipher they implement. {@code CipherSpi} instances are created
     35  * along with ciphers when the {@link Cipher#getInstance} method is called. A
     36  * {@code Cipher} is referenced by a <i>transformation</i>, which is a string
     37  * that describes the operation (or set of operations), always consisting of the
     38  * cipher's name and optionally followed by a mode and a padding, in the form:
     39  * <ul>
     40  * <li>"algorithm"</li>or
     41  * <li>"algorithm/mode/padding"</li>
     42  * </ul>
     43  * The following behavior should be implemented for obtaining {@code Cipher}
     44  * instances.
     45  * <p>
     46  * When one of the {@link Cipher#getInstance} factory methods is called with a
     47  * <i>transformation</i> that is only an <i>algorithm</i>, check if the provider
     48  * defines a {@code CipherSpi} for "algorithm", if so: return it, otherwise
     49  * throw a {@link NoSuchAlgorithmException}.
     50  * <p>
     51  * The following rules apply when a <i>transformation</i> is of the form
     52  * "algorithm/mode/padding":
     53  * <ul>
     54  * 1. The Provider has a {@code CipherSpi} subclass registered for
     55  * "algorithm/mode/padding": return it, otherwise go to step 2.
     56  * </ul>
     57  * <ul>
     58  * 2. The Provider has a {@code CipherSpi} subclass registered for
     59  * "algorithm/mode": instantiate it, call
     60  * {@link CipherSpi#engineSetPadding(String) engineSetPadding(String)} for the
     61  * padding name and return it, otherwise go to step 3.
     62  * </ul>
     63  * <ul>
     64  * 3. The Provider has a {@code CipherSpi} subclass registered for
     65  * "algorithm//padding": instantiate it, call
     66  * {@link CipherSpi#engineSetMode(String) engineSetMode(String)} for the mode
     67  * name and return it, otherwise go to step 4.
     68  * </ul>
     69  * <ul>
     70  * 4. The Provider has a {@code CipherSpi} subclass registered for "algorithm":
     71  * instantiate it, call {@link CipherSpi#engineSetMode(String)
     72  * engineSetMode(String)} for the mode name , call
     73  * {@link CipherSpi#engineSetPadding(String) engineSetPadding(String)} for the
     74  * padding name and return it, otherwise throw a
     75  * {@link NoSuchAlgorithmException}.
     76  * </ul>
     77  *
     78  * @see Cipher
     79  */
     80 public abstract class CipherSpi {
     81 
     82     /**
     83      * Creates a new {@code CipherSpi} instance.
     84      */
     85     public CipherSpi() {
     86     }
     87 
     88     /**
     89      * Sets the mode for this cipher.
     90      *
     91      * @param mode
     92      *            the name of the cipher mode.
     93      * @throws NoSuchAlgorithmException
     94      *             if the specified cipher mode is not supported by this
     95      *             provider.
     96      */
     97     protected abstract void engineSetMode(String mode)
     98             throws NoSuchAlgorithmException;
     99 
    100     /**
    101      * Sets the padding method for this cipher.
    102      *
    103      * @param padding
    104      *            the name of the padding method.
    105      * @throws NoSuchPaddingException
    106      *             if the specified padding method is not supported by this
    107      *             cipher.
    108      */
    109     protected abstract void engineSetPadding(String padding)
    110             throws NoSuchPaddingException;
    111 
    112     /**
    113      * Returns the block size of this cipher (in bytes)
    114      *
    115      * @return the block size of this cipher, or zero if this cipher is not a
    116      *         block cipher.
    117      */
    118     protected abstract int engineGetBlockSize();
    119 
    120     /**
    121      * Returns the size for a buffer (in bytes), that the next call to {@code
    122      * update} of {@code doFinal} would return, taking into account any buffered
    123      * data from previous {@code update} calls and padding.
    124      * <p>
    125      * The actual output length of the next call to {@code update} or {@code
    126      * doFinal} may be smaller than the length returned by this method.
    127      *
    128      * @param inputLen
    129      *            the length of the input (in bytes).
    130      * @return the size for a buffer (in bytes).
    131      */
    132     protected abstract int engineGetOutputSize(int inputLen);
    133 
    134     /**
    135      * Returns the Initialization Vector (IV) that was used to initialize this
    136      * cipher or {@code null} if none was used.
    137      *
    138      * @return the Initialization Vector (IV), or {@code null} if none was used.
    139      */
    140     protected abstract byte[] engineGetIV();
    141 
    142     /**
    143      * Returns the parameters that where used to create this cipher instance.
    144      * <p>
    145      * These may be a the same parameters that were used to create this cipher
    146      * instance, or may be a combination of default and random parameters,
    147      * depending on the underlying cipher implementation.
    148      *
    149      * @return the parameters that where used to create this cipher instance, or
    150      *         {@code null} if this cipher instance does not have any parameters
    151      *         at all.
    152      */
    153     protected abstract AlgorithmParameters engineGetParameters();
    154 
    155     /**
    156      * Initializes this cipher instance with the specified key and a source of
    157      * randomness.
    158      * <p>
    159      * The cipher will be initialized for the specified operation (one of:
    160      * encryption, decryption, key wrapping or key unwrapping) depending on
    161      * {@code opmode}.
    162      * <p>
    163      * If this cipher instance needs any algorithm parameters or random values
    164      * that the specified key cannot provide, the underlying implementation of
    165      * this cipher is supposed to generate the required parameters (using its
    166      * provider or random values). Random values will be generated using {@code
    167      * random};
    168      * <p>
    169      * When a cipher instance is initialized by a call to any of the {@code
    170      * init} methods, the state of the instance is overridden, means it is
    171      * equivalent to creating a new instance and calling it {@code init} method.
    172      *
    173      * @param opmode
    174      *            the operation this cipher instance should be initialized for
    175      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    176      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    177      * @param key
    178      *            the input key for the operation.
    179      * @param random
    180      *            the source of randomness to use.
    181      * @throws InvalidKeyException
    182      *             if the specified key cannot be used to initialize this cipher
    183      *             instance.
    184      */
    185     protected abstract void engineInit(int opmode, Key key, SecureRandom random)
    186             throws InvalidKeyException;
    187 
    188     /**
    189      * Initializes this cipher instance with the specified key, algorithm
    190      * parameters and a source of randomness.
    191      * <p>
    192      * The cipher will be initialized for the specified operation (one of:
    193      * encryption, decryption, key wrapping or key unwrapping) depending on
    194      * {@code opmode}.
    195      * <p>
    196      * If this cipher instance needs any algorithm parameters and {@code params}
    197      * is {@code null}, the underlying implementation of this cipher is supposed
    198      * to generate the required parameters (using its provider or random
    199      * values). Random values are generated using {@code random}.
    200      * <p>
    201      * When a cipher instance is initialized by a call to any of the {@code
    202      * init} methods, the state of the instance is overridden, means it is
    203      * equivalent to creating a new instance and calling it {@code init} method.
    204      *
    205      * @param opmode
    206      *            the operation this cipher instance should be initialized for
    207      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    208      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    209      * @param key
    210      *            the input key for the operation.
    211      * @param params
    212      *            the algorithm parameters.
    213      * @param random
    214      *            the source of randomness to use.
    215      * @throws InvalidKeyException
    216      *             if the specified key cannot be used to initialize this cipher
    217      *             instance.
    218      * @throws InvalidAlgorithmParameterException
    219      *             it the specified parameters are inappropriate for this
    220      *             cipher.
    221      */
    222     protected abstract void engineInit(int opmode, Key key,
    223             AlgorithmParameterSpec params, SecureRandom random)
    224             throws InvalidKeyException, InvalidAlgorithmParameterException;
    225 
    226     /**
    227      * Initializes this cipher instance with the specified key, algorithm
    228      * parameters and a source of randomness.
    229      * <p>
    230      * The cipher will be initialized for the specified operation (one of:
    231      * encryption, decryption, key wrapping or key unwrapping) depending on
    232      * {@code opmode}.
    233      * <p>
    234      * If this cipher instance needs any algorithm parameters and {@code params}
    235      * is {@code null}, the underlying implementation of this cipher is supposed
    236      * to generate the required parameters (using its provider or random
    237      * values). Random values are generated using {@code random}.
    238      * <p>
    239      * When a cipher instance is initialized by a call to any of the {@code
    240      * init} methods, the state of the instance is overridden, means it is
    241      * equivalent to creating a new instance and calling it {@code init} method.
    242      *
    243      * @param opmode
    244      *            the operation this cipher instance should be initialized for
    245      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
    246      *            WRAP_MODE} or {@code UNWRAP_MODE}).
    247      * @param key
    248      *            the input key for the operation.
    249      * @param params
    250      *            the algorithm parameters.
    251      * @param random
    252      *            the source of randomness to use.
    253      * @throws InvalidKeyException
    254      *             if the specified key cannot be used to initialize this cipher
    255      *             instance.
    256      * @throws InvalidAlgorithmParameterException
    257      *             if the specified parameters are inappropriate for this
    258      *             cipher.
    259      */
    260     protected abstract void engineInit(int opmode, Key key,
    261             AlgorithmParameters params, SecureRandom random)
    262             throws InvalidKeyException, InvalidAlgorithmParameterException;
    263 
    264     /**
    265      * Continues a multi-part transformation (encryption or decryption). The
    266      * transformed bytes are returned.
    267      *
    268      * @param input
    269      *            the input bytes to transform.
    270      * @param inputOffset
    271      *            the offset in the input to start.
    272      * @param inputLen
    273      *            the length of the input to transform.
    274      * @return the transformed bytes in a new buffer, or {@code null} if the
    275      *         input has zero length.
    276      * @throws IllegalStateException
    277      *             if this cipher instance is not initialized for encryption or
    278      *             decryption.
    279      * @throws IllegalArgumentException
    280      *             if the input is null, or if {@code inputOffset} and {@code
    281      *             inputLen} do not specify a valid chunk in the input buffer.
    282      */
    283     protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
    284             int inputLen);
    285 
    286     /**
    287      * Continues a multi-part transformation (encryption or decryption). The
    288      * transformed bytes are stored in the {@code output} buffer.
    289      * <p>
    290      * If the size of the {@code output} buffer is too small to hold the result,
    291      * a {@code ShortBufferException} is thrown. Use
    292      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
    293      * output buffer.
    294      *
    295      * @param input
    296      *            the input bytes to transform.
    297      * @param inputOffset
    298      *            the offset in the input to start.
    299      * @param inputLen
    300      *            the length of the input to transform.
    301      * @param output
    302      *            the output buffer.
    303      * @param outputOffset
    304      *            the offset in the output buffer.
    305      * @return the number of bytes placed in output.
    306      * @throws ShortBufferException
    307      *             if the size of the {@code output} buffer is too small.
    308      */
    309     protected abstract int engineUpdate(byte[] input, int inputOffset,
    310             int inputLen, byte[] output, int outputOffset)
    311             throws ShortBufferException;
    312 
    313     /**
    314      * Continues a multi-part transformation (encryption or decryption). The
    315      * {@code input.remaining()} bytes starting at {@code input.position()} are
    316      * transformed and stored in the {@code output} buffer.
    317      * <p>
    318      * If the {@code output.remaining()} is too small to hold the transformed
    319      * bytes a {@code ShortBufferException} is thrown. Use
    320      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
    321      * output buffer.
    322      *
    323      * @param input
    324      *            the input buffer to transform.
    325      * @param output
    326      *            the output buffer to store the result within.
    327      * @return the number of bytes stored in the output buffer.
    328      * @throws ShortBufferException
    329      *             if the size of the {@code output} buffer is too small.
    330      */
    331     protected int engineUpdate(ByteBuffer input, ByteBuffer output)
    332             throws ShortBufferException {
    333         if (input == null) {
    334             throw new NullPointerException("input == null");
    335         }
    336         if (output == null) {
    337             throw new NullPointerException("output == null");
    338         }
    339         int position = input.position();
    340         int limit = input.limit();
    341         if ((limit - position) <= 0) {
    342             return 0;
    343         }
    344         byte[] bInput;
    345         byte[] bOutput;
    346         if (input.hasArray()) {
    347             bInput = input.array();
    348             int offset = input.arrayOffset();
    349             bOutput = engineUpdate(bInput, offset + position, limit - position);
    350             input.position(limit);
    351         } else {
    352             bInput = new byte[limit - position];
    353             input.get(bInput);
    354             bOutput = engineUpdate(bInput, 0, limit - position);
    355         }
    356         if (bOutput == null) {
    357             return 0;
    358         }
    359         if (output.remaining() < bOutput.length) {
    360             throw new ShortBufferException("output buffer too small");
    361         }
    362         try {
    363             output.put(bOutput);
    364         } catch (java.nio.BufferOverflowException e) {
    365             throw new ShortBufferException("output buffer too small");
    366         }
    367         return bOutput.length;
    368     }
    369 
    370     /**
    371      * Finishes a multi-part transformation (encryption or decryption).
    372      * <p>
    373      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
    374      * inputOffset}, and any bytes that have been buffered in previous {@code
    375      * update} calls.
    376      *
    377      * @param input
    378      *            the input buffer.
    379      * @param inputOffset
    380      *            the offset in the input buffer.
    381      * @param inputLen
    382      *            the length of the input.
    383      * @return the final bytes from the transformation.
    384      * @throws IllegalBlockSizeException
    385      *             if the size of the resulting bytes is not a multiple of the
    386      *             cipher block size.
    387      * @throws BadPaddingException
    388      *             if the padding of the data does not match the padding scheme.
    389      */
    390     protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
    391             int inputLen) throws IllegalBlockSizeException, BadPaddingException;
    392 
    393     /**
    394      * Finishes a multi-part transformation (encryption or decryption).
    395      * <p>
    396      * Processes the {@code inputLen} bytes in {@code input} buffer at
    397      * {@code inputOffset}, and any bytes that have been buffered in previous
    398      * {@code update} calls.
    399      *
    400      * @param input
    401      *            the input buffer.
    402      * @param inputOffset
    403      *            the offset in the input buffer.
    404      * @param inputLen
    405      *            the length of the input.
    406      * @param output
    407      *            the output buffer for the transformed bytes.
    408      * @param outputOffset
    409      *            the offset in the output buffer.
    410      * @return the number of bytes placed in the output buffer.
    411      * @throws ShortBufferException
    412      *             if the size of the {@code output} buffer is too small.
    413      * @throws IllegalBlockSizeException
    414      *             if the size of the resulting bytes is not a multiple of the
    415      *             cipher block size.
    416      * @throws BadPaddingException
    417      *             if the padding of the data does not match the padding scheme.
    418      */
    419     protected abstract int engineDoFinal(byte[] input, int inputOffset,
    420             int inputLen, byte[] output, int outputOffset)
    421             throws ShortBufferException, IllegalBlockSizeException,
    422             BadPaddingException;
    423 
    424     /**
    425      * Finishes a multi-part transformation (encryption or decryption).
    426      * <p>
    427      * Processes the {@code input.remaining()} bytes in {@code input} buffer at
    428      * {@code input.position()}, and any bytes that have been buffered in
    429      * previous {@code update} calls. The transformed bytes are placed into
    430      * {@code output} buffer.
    431      *
    432      * @param input
    433      *            the input buffer.
    434      * @param output
    435      *            the output buffer.
    436      * @return the number of bytes placed into the output buffer.
    437      * @throws ShortBufferException
    438      *             if the size of the {@code output} buffer is too small.
    439      * @throws IllegalBlockSizeException
    440      *             if the size of the resulting bytes is not a multiple of the
    441      *             cipher block size.
    442      * @throws BadPaddingException
    443      *             if the padding of the data does not match the padding scheme.
    444      * @throws IllegalArgumentException
    445      *             if the input buffer and the output buffer are the same
    446      *             object.
    447      * @throws IllegalStateException
    448      *             if this cipher instance is not initialized for encryption or
    449      *             decryption.
    450      */
    451     protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
    452             throws ShortBufferException, IllegalBlockSizeException,
    453             BadPaddingException {
    454         if (input == null) {
    455             throw new NullPointerException("input == null");
    456         }
    457         if (output == null) {
    458             throw new NullPointerException("output == null");
    459         }
    460         int position = input.position();
    461         int limit = input.limit();
    462 
    463         if ((limit - position) <= 0) {
    464             return 0;
    465         }
    466         byte[] bInput;
    467         byte[] bOutput;
    468 
    469         if (input.hasArray()) {
    470             bInput = input.array();
    471             int offset = input.arrayOffset();
    472             bOutput = engineDoFinal(bInput, offset + position, limit - position);
    473             input.position(limit);
    474         } else {
    475             bInput = new byte[limit - position];
    476             input.get(bInput);
    477             bOutput = engineDoFinal(bInput, 0, limit - position);
    478         }
    479         if (output.remaining() < bOutput.length) {
    480             throw new ShortBufferException("output buffer too small");
    481         }
    482         try {
    483             output.put(bOutput);
    484         } catch (java.nio.BufferOverflowException e) {
    485             throw new ShortBufferException("output buffer too small");
    486         }
    487         return bOutput.length;
    488     }
    489 
    490     /**
    491      * Wraps a key using this cipher instance. This method has been added to
    492      * this class (for backwards compatibility, it cannot be abstract). If this
    493      * method is not overridden, it throws an {@code
    494      * UnsupportedOperationException}.
    495      *
    496      * @param key
    497      *            the key to wrap.
    498      * @return the wrapped key
    499      * @throws IllegalBlockSizeException
    500      *             if the size of the resulting bytes is not a multiple of the
    501      *             cipher block size.
    502      * @throws InvalidKeyException
    503      *             if this cipher instance cannot wrap this key.
    504      */
    505     protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException {
    506         throw new UnsupportedOperationException();
    507     }
    508 
    509     /**
    510      * Unwraps a key using this cipher instance.
    511      * <p>
    512      * This method has been added to this class (for backwards compatibility, it
    513      * cannot be abstract). If this method is not overridden, it throws an
    514      * {@code UnsupportedOperationException}.
    515      *
    516      * @param wrappedKey
    517      *            the wrapped key to unwrap.
    518      * @param wrappedKeyAlgorithm
    519      *            the algorithm for the wrapped key.
    520      * @param wrappedKeyType
    521      *            the type of the wrapped key (one of: {@code SECRET_KEY},
    522      *            {@code PRIVATE_KEY} or {@code PUBLIC_KEY})
    523      * @return the unwrapped key.
    524      * @throws InvalidKeyException
    525      *             if the {@code wrappedKey} cannot be unwrapped to a key of
    526      *             type {@code wrappedKeyType} for the {@code
    527      *             wrappedKeyAlgorithm}.
    528      * @throws NoSuchAlgorithmException
    529      *             if no provider can be found that can create a key of type
    530      *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
    531      */
    532     protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
    533             int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
    534         throw new UnsupportedOperationException();
    535     }
    536 
    537     /**
    538      * Returns the size of a specified key object in bits. This method has been
    539      * added to this class (for backwards compatibility, it cannot be abstract).
    540      * If this method is not overridden, it throws an {@code
    541      * UnsupportedOperationException}.
    542      *
    543      * @param key
    544      *            the key to get the size for.
    545      * @return the size of a specified key object in bits.
    546      * @throws InvalidKeyException
    547      *             if the size of the key cannot be determined by this
    548      *             implementation.
    549      */
    550     protected int engineGetKeySize(Key key) throws InvalidKeyException {
    551         throw new UnsupportedOperationException();
    552     }
    553 }
    554