diff options
Diffstat (limited to 'luni/src/main/java/javax/crypto/CipherSpi.java')
-rw-r--r-- | luni/src/main/java/javax/crypto/CipherSpi.java | 557 |
1 files changed, 557 insertions, 0 deletions
diff --git a/luni/src/main/java/javax/crypto/CipherSpi.java b/luni/src/main/java/javax/crypto/CipherSpi.java new file mode 100644 index 0000000..50fdd49 --- /dev/null +++ b/luni/src/main/java/javax/crypto/CipherSpi.java @@ -0,0 +1,557 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package javax.crypto; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.nio.ByteBuffer; + +import org.apache.harmony.crypto.internal.nls.Messages; + +/** + * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for + * cryptographic ciphers. + * <p> + * Implementers of cryptographic ciphers must implement all the abstract methods + * for every cipher they implement. {@code CipherSpi} instances are created + * along with ciphers when the {@link Cipher#getInstance} method is called. A + * {@code Cipher} is referenced by a <i>transformation</i>, which is a string + * that describes the operation (or set of operations), always consisting of the + * cipher's name and optionally followed by a mode and a padding, in the form: + * <ul> + * <li>"algorithm"</li>or + * <li>"algorithm/mode/padding"</li> + * </ul> + * The following behavior should be implemented for obtaining {@code Cipher} + * instances. + * <p> + * When one of the {@link Cipher#getInstance} factory methods is called with a + * <i>transformation</i> that is only an <i>algorithm</i>, check if the provider + * defines a {@code CipherSpi} for "algorithm", if so: return it, otherwise + * throw a {@link NoSuchAlgorithmException}. + * <p> + * The following rules apply when a <i>transformation</i> is of the form + * "algorithm/mode/padding": + * <ul> + * 1. The Provider has a {@code CipherSpi} subclass registered for + * "algorithm/mode/padding": return it, otherwise go to step 2. + * </ul> + * <ul> + * 2. The Provider has a {@code CipherSpi} subclass registered for + * "algorithm/mode": instantiate it, call + * {@link CipherSpi#engineSetPadding(String) engineSetPadding(String)} for the + * padding name and return it, otherwise go to step 3. + * </ul> + * <ul> + * 3. The Provider has a {@code CipherSpi} subclass registered for + * "algorithm//padding": instantiate it, call + * {@link CipherSpi#engineSetMode(String) engineSetMode(String)} for the mode + * name and return it, otherwise go to step 4. + * </ul> + * <ul> + * 4. The Provider has a {@code CipherSpi} subclass registered for "algorithm": + * instantiate it, call {@link CipherSpi#engineSetMode(String) + * engineSetMode(String)} for the mode name , call + * {@link CipherSpi#engineSetPadding(String) engineSetPadding(String)} for the + * padding name and return it, otherwise throw a + * {@link NoSuchAlgorithmException}. + * </ul> + * + * @see Cipher + */ +public abstract class CipherSpi { + + /** + * Creates a new {@code CipherSpi} instance. + */ + public CipherSpi() { + } + + /** + * Sets the mode for this cipher. + * + * @param mode + * the name of the cipher mode. + * @throws NoSuchAlgorithmException + * if the specified cipher mode is not supported by this + * provider. + */ + protected abstract void engineSetMode(String mode) + throws NoSuchAlgorithmException; + + /** + * Sets the padding method for this cipher. + * + * @param padding + * the name of the padding method. + * @throws NoSuchPaddingException + * if the specified padding method is not supported by this + * cipher. + */ + protected abstract void engineSetPadding(String padding) + throws NoSuchPaddingException; + + /** + * Returns the block size of this cipher (in bytes) + * + * @return the block size of this cipher, or zero if this cipher is not a + * block cipher. + */ + protected abstract int engineGetBlockSize(); + + /** + * Returns the size for a buffer (in bytes), that the next call to {@code + * update} of {@code doFinal} would return, taking into account any buffered + * data from previous {@code update} calls and padding. + * <p> + * The actual output length of the next call to {@code update} or {@code + * doFinal} may be smaller than the length returned by this method. + * + * @param inputLen + * the length of the input (in bytes). + * @return the size for a buffer (in bytes). + */ + protected abstract int engineGetOutputSize(int inputLen); + + /** + * Returns the Initialization Vector (IV) that was used to initialize this + * cipher or {@code null} if none was used. + * + * @return the Initialization Vector (IV), or {@code null} if none was used. + */ + protected abstract byte[] engineGetIV(); + + /** + * Returns the parameters that where used to create this cipher instance. + * <p> + * These may be a the same parameters that were used to create this cipher + * instance, or may be a combination of default and random parameters, + * depending on the underlying cipher implementation. + * + * @return the parameters that where used to create this cipher instance, or + * {@code null} if this cipher instance does not have any parameters + * at all. + */ + protected abstract AlgorithmParameters engineGetParameters(); + + /** + * Initializes this cipher instance with the specified key and a source of + * randomness. + * <p> + * The cipher will be initialized for the specified operation (one of: + * encryption, decryption, key wrapping or key unwrapping) depending on + * {@code opmode}. + * <p> + * If this cipher instance needs any algorithm parameters or random values + * that the specified key cannot provide, the underlying implementation of + * this cipher is supposed to generate the required parameters (using its + * provider or random values). Random values will be generated using {@code + * random}; + * <p> + * When a cipher instance is initialized by a call to any of the {@code + * init} methods, the state of the instance is overridden, means it is + * equivalent to creating a new instance and calling it {@code init} method. + * + * @param opmode + * the operation this cipher instance should be initialized for + * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code + * WRAP_MODE} or {@code UNWRAP_MODE}). + * @param key + * the input key for the operation. + * @param random + * the source of randomness to use. + * @throws InvalidKeyException + * if the specified key cannot be used to initialize this cipher + * instance. + */ + protected abstract void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException; + + /** + * Initializes this cipher instance with the specified key, algorithm + * parameters and a source of randomness. + * <p> + * The cipher will be initialized for the specified operation (one of: + * encryption, decryption, key wrapping or key unwrapping) depending on + * {@code opmode}. + * <p> + * If this cipher instance needs any algorithm parameters and {@code params} + * is {@code null}, the underlying implementation of this cipher is supposed + * to generate the required parameters (using its provider or random + * values). Random values are generated using {@code random}. + * <p> + * When a cipher instance is initialized by a call to any of the {@code + * init} methods, the state of the instance is overridden, means it is + * equivalent to creating a new instance and calling it {@code init} method. + * + * @param opmode + * the operation this cipher instance should be initialized for + * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code + * WRAP_MODE} or {@code UNWRAP_MODE}). + * @param key + * the input key for the operation. + * @param params + * the algorithm parameters. + * @param random + * the source of randomness to use. + * @throws InvalidKeyException + * if the specified key cannot be used to initialize this cipher + * instance. + * @throws InvalidAlgorithmParameterException + * it the specified parameters are inappropriate for this + * cipher. + */ + protected abstract void engineInit(int opmode, Key key, + AlgorithmParameterSpec params, SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + /** + * Initializes this cipher instance with the specified key, algorithm + * parameters and a source of randomness. + * <p> + * The cipher will be initialized for the specified operation (one of: + * encryption, decryption, key wrapping or key unwrapping) depending on + * {@code opmode}. + * <p> + * If this cipher instance needs any algorithm parameters and {@code params} + * is {@code null}, the underlying implementation of this cipher is supposed + * to generate the required parameters (using its provider or random + * values). Random values are generated using {@code random}. + * <p> + * When a cipher instance is initialized by a call to any of the {@code + * init} methods, the state of the instance is overridden, means it is + * equivalent to creating a new instance and calling it {@code init} method. + * + * @param opmode + * the operation this cipher instance should be initialized for + * (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code + * WRAP_MODE} or {@code UNWRAP_MODE}). + * @param key + * the input key for the operation. + * @param params + * the algorithm parameters. + * @param random + * the source of randomness to use. + * @throws InvalidKeyException + * if the specified key cannot be used to initialize this cipher + * instance. + * @throws InvalidAlgorithmParameterException + * if the specified parameters are inappropriate for this + * cipher. + */ + protected abstract void engineInit(int opmode, Key key, + AlgorithmParameters params, SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException; + + /** + * Continues a multi-part transformation (encryption or decryption). The + * transformed bytes are returned. + * + * @param input + * the input bytes to transform. + * @param inputOffset + * the offset in the input to start. + * @param inputLen + * the length of the input to transform. + * @return the transformed bytes in a new buffer, or {@code null} if the + * input has zero length. + * @throws IllegalStateException + * if this cipher instance is not initialized for encryption or + * decryption. + * @throws IllegalArgumentException + * if the input is null, or if {@code inputOffset} and {@code + * inputLen} do not specify a valid chunk in the input buffer. + */ + protected abstract byte[] engineUpdate(byte[] input, int inputOffset, + int inputLen); + + /** + * Continues a multi-part transformation (encryption or decryption). The + * transformed bytes are stored in the {@code output} buffer. + * <p> + * If the size of the {@code output} buffer is too small to hold the result, + * a {@code ShortBufferException} is thrown. Use + * {@link Cipher#getOutputSize getOutputSize} to check for the size of the + * output buffer. + * + * @param input + * the input bytes to transform. + * @param inputOffset + * the offset in the input to start. + * @param inputLen + * the length of the input to transform. + * @param output + * the output buffer. + * @param outputOffset + * the offset in the output buffer. + * @return the number of bytes placed in output. + * @throws ShortBufferException + * if the size of the {@code output} buffer is too small. + */ + protected abstract int engineUpdate(byte[] input, int inputOffset, + int inputLen, byte[] output, int outputOffset) + throws ShortBufferException; + + /** + * Continues a multi-part transformation (encryption or decryption). The + * {@code input.remaining()} bytes starting at {@code input.position()} are + * transformed and stored in the {@code output} buffer. + * <p> + * If the {@code output.remaining()} is too small to hold the transformed + * bytes a {@code ShortBufferException} is thrown. Use + * {@link Cipher#getOutputSize getOutputSize} to check for the size of the + * output buffer. + * + * @param input + * the input buffer to transform. + * @param output + * the output buffer to store the result within. + * @return the number of bytes stored in the output buffer. + * @throws ShortBufferException + * if the size of the {@code output} buffer is too small. + */ + protected int engineUpdate(ByteBuffer input, ByteBuffer output) + throws ShortBufferException { + if (input == null) { + throw new NullPointerException(Messages.getString("crypto.0C")); //$NON-NLS-1$ + } + if (output == null) { + throw new NullPointerException(Messages.getString("crypto.0D")); //$NON-NLS-1$ + } + int position = input.position(); + int limit = input.limit(); + if ((limit - position) <= 0) { + return 0; + } + byte[] bInput; + byte[] bOutput; + if (input.hasArray()) { + bInput = input.array(); + int offset = input.arrayOffset(); + bOutput = engineUpdate(bInput, offset + position, limit - position); + input.position(limit); + } else { + bInput = new byte[limit - position]; + input.get(bInput); + bOutput = engineUpdate(bInput, 0, limit - position); + } + if (output.remaining() < bOutput.length) { + throw new ShortBufferException(Messages.getString("crypto.0E")); //$NON-NLS-1$ + } + try { + output.put(bOutput); + } catch (java.nio.BufferOverflowException e) { + throw new ShortBufferException(Messages.getString("crypto.0F", e)); //$NON-NLS-1$ + } + return bOutput.length; + } + + /** + * Finishes a multi-part transformation (encryption or decryption). + * <p> + * Processes the {@code inputLen} bytes in {@code input} buffer at {@code + * inputOffset}, and any bytes that have been buffered in previous {@code + * update} calls. + * + * @param input + * the input buffer. + * @param inputOffset + * the offset in the input buffer. + * @param inputLen + * the length of the input. + * @return the final bytes from the transformation. + * @throws IllegalBlockSizeException + * if the size of the resulting bytes is not a multiple of the + * cipher block size. + * @throws BadPaddingException + * if the padding of the data does not match the padding scheme. + */ + protected abstract byte[] engineDoFinal(byte[] input, int inputOffset, + int inputLen) throws IllegalBlockSizeException, BadPaddingException; + + /** + * Finishes a multi-part transformation (encryption or decryption). + * <p> + * Processes the {@code inputLen} bytes in {@code input} buffer at + * {@code inputOffset}, and any bytes that have been buffered in previous + * {@code update} calls. + * + * @param input + * the input buffer. + * @param inputOffset + * the offset in the input buffer. + * @param inputLen + * the length of the input. + * @param output + * the output buffer for the transformed bytes. + * @param outputOffset + * the offset in the output buffer. + * @return the number of bytes placed in the output buffer. + * @throws ShortBufferException + * if the size of the {@code output} buffer is too small. + * @throws IllegalBlockSizeException + * if the size of the resulting bytes is not a multiple of the + * cipher block size. + * @throws BadPaddingException + * if the padding of the data does not match the padding scheme. + */ + protected abstract int engineDoFinal(byte[] input, int inputOffset, + int inputLen, byte[] output, int outputOffset) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException; + + /** + * Finishes a multi-part transformation (encryption or decryption). + * <p> + * Processes the {@code input.remaining()} bytes in {@code input} buffer at + * {@code input.position()}, and any bytes that have been buffered in + * previous {@code update} calls. The transformed bytes are placed into + * {@code output} buffer. + * + * @param input + * the input buffer. + * @param output + * the output buffer. + * @return the number of bytes placed into the output buffer. + * @throws ShortBufferException + * if the size of the {@code output} buffer is too small. + * @throws IllegalBlockSizeException + * if the size of the resulting bytes is not a multiple of the + * cipher block size. + * @throws BadPaddingException + * if the padding of the data does not match the padding scheme. + * @throws IllegalArgumentException + * if the input buffer and the output buffer are the same + * object. + * @throws IllegalStateException + * if this cipher instance is not initialized for encryption or + * decryption. + */ + protected int engineDoFinal(ByteBuffer input, ByteBuffer output) + throws ShortBufferException, IllegalBlockSizeException, + BadPaddingException { + if (input == null) { + throw new NullPointerException(Messages.getString("crypto.0C")); //$NON-NLS-1$ + } + if (output == null) { + throw new NullPointerException(Messages.getString("crypto.0D")); //$NON-NLS-1$ + } + int position = input.position(); + int limit = input.limit(); + + if ((limit - position) <= 0) { + return 0; + } + byte[] bInput; + byte[] bOutput; + + if (input.hasArray()) { + bInput = input.array(); + int offset = input.arrayOffset(); + bOutput = engineDoFinal(bInput, offset + position, limit - position); + input.position(limit); + } else { + bInput = new byte[limit - position]; + input.get(bInput); + bOutput = engineDoFinal(bInput, 0, limit - position); + } + if (output.remaining() < bOutput.length) { + throw new ShortBufferException(Messages.getString("crypto.0E")); //$NON-NLS-1$ + } + try { + output.put(bOutput); + } catch (java.nio.BufferOverflowException e) { + throw new ShortBufferException(Messages.getString("crypto.0F", e)); //$NON-NLS-1$ + } + return bOutput.length; + } + + /** + * Wraps a key using this cipher instance. This method has been added to + * this class (for backwards compatibility, it cannot be abstract). If this + * method is not overridden, it throws an {@code + * UnsupportedOperationException}. + * + * @param key + * the key to wrap. + * @return the wrapped key + * @throws IllegalBlockSizeException + * if the size of the resulting bytes is not a multiple of the + * cipher block size. + * @throws InvalidKeyException + * if this cipher instance cannot wrap this key. + */ + protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, + InvalidKeyException { + throw new UnsupportedOperationException( + Messages.getString("crypto.10")); //$NON-NLS-1$ + } + + /** + * Unwraps a key using this cipher instance. + * <p> + * This method has been added to this class (for backwards compatibility, it + * cannot be abstract). If this method is not overridden, it throws an + * {@code UnsupportedOperationException}. + * + * @param wrappedKey + * the wrapped key to unwrap. + * @param wrappedKeyAlgorithm + * the algorithm for the wrapped key. + * @param wrappedKeyType + * the type of the wrapped key (one of: {@code SECRET_KEY}, + * {@code PRIVATE_KEY} or {@code PUBLIC_KEY}) + * @return the unwrapped key. + * @throws InvalidKeyException + * if the {@code wrappedKey} cannot be unwrapped to a key of + * type {@code wrappedKeyType} for the {@code + * wrappedKeyAlgorithm}. + * @throws NoSuchAlgorithmException + * if no provider can be found that can create a key of type + * {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}. + */ + protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, + int wrappedKeyType) throws InvalidKeyException, + NoSuchAlgorithmException { + throw new UnsupportedOperationException( + Messages.getString("crypto.11")); //$NON-NLS-1$ + } + + /** + * Returns the size of a specified key object in bits. This method has been + * added to this class (for backwards compatibility, it cannot be abstract). + * If this method is not overridden, it throws an {@code + * UnsupportedOperationException}. + * + * @param key + * the key to get the size for. + * @return the size of a specified key object in bits. + * @throws InvalidKeyException + * if the size of the key cannot be determined by this + * implementation. + */ + protected int engineGetKeySize(Key key) throws InvalidKeyException { + throw new UnsupportedOperationException( + Messages.getString("crypto.12")); //$NON-NLS-1$ + } +}
\ No newline at end of file |