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      * Continues a multi-part transformation (encryption or decryption) with
    372      * Authenticated Additional Data (AAD). AAD may only be added after the
    373      * {@code Cipher} is initialized and before any data is passed to the
    374      * instance.
    375      * <p>
    376      * This is only usable with cipher modes that support Authenticated
    377      * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
    378      *
    379      * @param input bytes of AAD to use with the cipher
    380      * @param inputOffset offset within bytes of additional data to add to cipher
    381      * @param inputLen length of bytes of additional data to add to cipher
    382      * @throws IllegalStateException
    383      *             if this cipher instance is not initialized for encryption or
    384      *             decryption.
    385      * @throws IllegalArgumentException
    386      *             if {@code input} is {@code null}, or if {@code inputOffset} and
    387      *             {@code inputLen} do not specify a valid chunk in the input
    388      *             buffer.
    389      * @throws UnsupportedOperationException if the cipher does not support AEAD
    390      * @since 1.7
    391      */
    392     protected void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
    393         throw new UnsupportedOperationException(
    394                 "This cipher does not support Authenticated Encryption with Additional Data");
    395     }
    396 
    397     /**
    398      * Continues a multi-part transformation (encryption or decryption). The
    399      * {@code input.remaining()} bytes starting at {@code input.position()} are
    400      * used for the Additional Authenticated Data (AAD). AAD may only be added
    401      * after the {@code Cipher} is initialized and before any data is passed to
    402      * the instance.
    403      * <p>
    404      * This is only usable with cipher modes that support Authenticated
    405      * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
    406      *
    407      * @param input the input buffer to transform.
    408      * @since 1.7
    409      */
    410     protected void engineUpdateAAD(ByteBuffer input) {
    411         if (input == null) {
    412             throw new NullPointerException("input == null");
    413         }
    414         int position = input.position();
    415         int limit = input.limit();
    416         if ((limit - position) <= 0) {
    417             return;
    418         }
    419         byte[] bInput;
    420         if (input.hasArray()) {
    421             bInput = input.array();
    422             int offset = input.arrayOffset();
    423             engineUpdateAAD(bInput, offset + position, limit - position);
    424             input.position(limit);
    425         } else {
    426             int len = limit - position;
    427             bInput = new byte[len];
    428             input.get(bInput);
    429             engineUpdateAAD(bInput, 0, len);
    430         }
    431     }
    432 
    433     /**
    434      * Finishes a multi-part transformation (encryption or decryption).
    435      * <p>
    436      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
    437      * inputOffset}, and any bytes that have been buffered in previous {@code
    438      * update} calls.
    439      *
    440      * @param input
    441      *            the input buffer.
    442      * @param inputOffset
    443      *            the offset in the input buffer.
    444      * @param inputLen
    445      *            the length of the input.
    446      * @return the final bytes from the transformation.
    447      * @throws IllegalBlockSizeException
    448      *             if the size of the resulting bytes is not a multiple of the
    449      *             cipher block size.
    450      * @throws BadPaddingException
    451      *             if the padding of the data does not match the padding scheme.
    452      */
    453     protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
    454             int inputLen) throws IllegalBlockSizeException, BadPaddingException;
    455 
    456     /**
    457      * Finishes a multi-part transformation (encryption or decryption).
    458      * <p>
    459      * Processes the {@code inputLen} bytes in {@code input} buffer at
    460      * {@code inputOffset}, and any bytes that have been buffered in previous
    461      * {@code update} calls.
    462      *
    463      * @param input
    464      *            the input buffer.
    465      * @param inputOffset
    466      *            the offset in the input buffer.
    467      * @param inputLen
    468      *            the length of the input.
    469      * @param output
    470      *            the output buffer for the transformed bytes.
    471      * @param outputOffset
    472      *            the offset in the output buffer.
    473      * @return the number of bytes placed in the output buffer.
    474      * @throws ShortBufferException
    475      *             if the size of the {@code output} buffer is too small.
    476      * @throws IllegalBlockSizeException
    477      *             if the size of the resulting bytes is not a multiple of the
    478      *             cipher block size.
    479      * @throws BadPaddingException
    480      *             if the padding of the data does not match the padding scheme.
    481      */
    482     protected abstract int engineDoFinal(byte[] input, int inputOffset,
    483             int inputLen, byte[] output, int outputOffset)
    484             throws ShortBufferException, IllegalBlockSizeException,
    485             BadPaddingException;
    486 
    487     /**
    488      * Finishes a multi-part transformation (encryption or decryption).
    489      * <p>
    490      * Processes the {@code input.remaining()} bytes in {@code input} buffer at
    491      * {@code input.position()}, and any bytes that have been buffered in
    492      * previous {@code update} calls. The transformed bytes are placed into
    493      * {@code output} buffer.
    494      *
    495      * @param input
    496      *            the input buffer.
    497      * @param output
    498      *            the output buffer.
    499      * @return the number of bytes placed into the output buffer.
    500      * @throws ShortBufferException
    501      *             if the size of the {@code output} buffer is too small.
    502      * @throws IllegalBlockSizeException
    503      *             if the size of the resulting bytes is not a multiple of the
    504      *             cipher block size.
    505      * @throws BadPaddingException
    506      *             if the padding of the data does not match the padding scheme.
    507      * @throws IllegalArgumentException
    508      *             if the input buffer and the output buffer are the same
    509      *             object.
    510      * @throws IllegalStateException
    511      *             if this cipher instance is not initialized for encryption or
    512      *             decryption.
    513      */
    514     protected int engineDoFinal(ByteBuffer input, ByteBuffer output)
    515             throws ShortBufferException, IllegalBlockSizeException,
    516             BadPaddingException {
    517         if (input == null) {
    518             throw new NullPointerException("input == null");
    519         }
    520         if (output == null) {
    521             throw new NullPointerException("output == null");
    522         }
    523         int position = input.position();
    524         int limit = input.limit();
    525 
    526         if ((limit - position) <= 0) {
    527             return 0;
    528         }
    529         byte[] bInput;
    530         byte[] bOutput;
    531 
    532         if (input.hasArray()) {
    533             bInput = input.array();
    534             int offset = input.arrayOffset();
    535             bOutput = engineDoFinal(bInput, offset + position, limit - position);
    536             input.position(limit);
    537         } else {
    538             bInput = new byte[limit - position];
    539             input.get(bInput);
    540             bOutput = engineDoFinal(bInput, 0, limit - position);
    541         }
    542         if (output.remaining() < bOutput.length) {
    543             throw new ShortBufferException("output buffer too small");
    544         }
    545         try {
    546             output.put(bOutput);
    547         } catch (java.nio.BufferOverflowException e) {
    548             throw new ShortBufferException("output buffer too small");
    549         }
    550         return bOutput.length;
    551     }
    552 
    553     /**
    554      * Wraps a key using this cipher instance. This method has been added to
    555      * this class (for backwards compatibility, it cannot be abstract). If this
    556      * method is not overridden, it throws an {@code
    557      * UnsupportedOperationException}.
    558      *
    559      * @param key
    560      *            the key to wrap.
    561      * @return the wrapped key
    562      * @throws IllegalBlockSizeException
    563      *             if the size of the resulting bytes is not a multiple of the
    564      *             cipher block size.
    565      * @throws InvalidKeyException
    566      *             if this cipher instance cannot wrap this key.
    567      */
    568     protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException {
    569         throw new UnsupportedOperationException();
    570     }
    571 
    572     /**
    573      * Unwraps a key using this cipher instance.
    574      * <p>
    575      * This method has been added to this class (for backwards compatibility, it
    576      * cannot be abstract). If this method is not overridden, it throws an
    577      * {@code UnsupportedOperationException}.
    578      *
    579      * @param wrappedKey
    580      *            the wrapped key to unwrap.
    581      * @param wrappedKeyAlgorithm
    582      *            the algorithm for the wrapped key.
    583      * @param wrappedKeyType
    584      *            the type of the wrapped key (one of: {@code SECRET_KEY},
    585      *            {@code PRIVATE_KEY} or {@code PUBLIC_KEY})
    586      * @return the unwrapped key.
    587      * @throws InvalidKeyException
    588      *             if the {@code wrappedKey} cannot be unwrapped to a key of
    589      *             type {@code wrappedKeyType} for the {@code
    590      *             wrappedKeyAlgorithm}.
    591      * @throws NoSuchAlgorithmException
    592      *             if no provider can be found that can create a key of type
    593      *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
    594      */
    595     protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
    596             int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
    597         throw new UnsupportedOperationException();
    598     }
    599 
    600     /**
    601      * Returns the size of a specified key object in bits. This method has been
    602      * added to this class (for backwards compatibility, it cannot be abstract).
    603      * If this method is not overridden, it throws an {@code
    604      * UnsupportedOperationException}.
    605      *
    606      * @param key
    607      *            the key to get the size for.
    608      * @return the size of a specified key object in bits.
    609      * @throws InvalidKeyException
    610      *             if the size of the key cannot be determined by this
    611      *             implementation.
    612      */
    613     protected int engineGetKeySize(Key key) throws InvalidKeyException {
    614         throw new UnsupportedOperationException();
    615     }
    616 }
    617