diff options
Diffstat (limited to 'libjava/classpath/javax/crypto')
43 files changed, 8006 insertions, 0 deletions
diff --git a/libjava/classpath/javax/crypto/BadPaddingException.java b/libjava/classpath/javax/crypto/BadPaddingException.java new file mode 100644 index 000000000..a1d6dd595 --- /dev/null +++ b/libjava/classpath/javax/crypto/BadPaddingException.java @@ -0,0 +1,79 @@ +/* BadPaddingException -- Signals bad padding bytes on decryption. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.GeneralSecurityException; + +/** + * This exception is thrown during decryption when the decrypted input + * does not have the proper padding bytes that are expected by the padding + * mechanism. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class BadPaddingException extends GeneralSecurityException +{ + + // Constant. + // ------------------------------------------------------------------------ + + /** Serialization constant. */ + private static final long serialVersionUID = -5315033893984728443L; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Creates a new bad padding exception with no detail message. + */ + public BadPaddingException() + { + super(); + } + + /** + * Creates a new bad padding exception with a detail message. + * + * @param message The detail message. + */ + public BadPaddingException(String message) + { + super(message); + } +} diff --git a/libjava/classpath/javax/crypto/Cipher.java b/libjava/classpath/javax/crypto/Cipher.java new file mode 100644 index 000000000..9b7d8f9fe --- /dev/null +++ b/libjava/classpath/javax/crypto/Cipher.java @@ -0,0 +1,1148 @@ +/* Cipher.java -- Interface to a cryptographic cipher. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.Engine; + +import java.nio.ByteBuffer; +import java.nio.ReadOnlyBufferException; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.security.spec.AlgorithmParameterSpec; +import java.util.StringTokenizer; + +/** + * <p>This class implements a cryptographic cipher for transforming + * data.</p> + * + * <p>Ciphers cannot be instantiated directly; rather one of the + * <code>getInstance</code> must be used to instantiate a given + * <i>transformation</i>, optionally with a specific provider.</p> + * + * <p>A transformation is of the form:</p> + * + * <ul> + * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i>, or</li> + * <li><i>algorithm</i> + * </ul> + * + * <p>where <i>algorithm</i> is the base name of a cryptographic cipher + * (such as "AES"), <i>mode</i> is the abbreviated name of a block + * cipher mode (such as "CBC" for cipher block chaining mode), and + * <i>padding</i> is the name of a padding scheme (such as + * "PKCS5Padding"). If only the algorithm name is supplied, then the + * provider-specific default mode and padding will be used.</p> + * + * <p>An example transformation is:</p> + * + * <blockquote><code>Cipher c = + * Cipher.getInstance("AES/CBC/PKCS5Padding");</code></blockquote> + * + * <p>Finally, when requesting a block cipher in stream cipher mode + * (such as <acronym title="Advanced Encryption Standard">AES</acronym> + * in OFB or CFB mode) the number of bits to be processed + * at a time may be specified by appending it to the name of the mode; + * e.g. <code>"AES/OFB8/NoPadding"</code>. If no such number is + * specified a provider-specific default value is used.</p> + * + * @author Casey Marshall (csm@gnu.org) + * @see java.security.KeyGenerator + * @see javax.crypto.SecretKey + */ +public class Cipher +{ + + // Constants and variables. + // ------------------------------------------------------------------------ + + private static final String SERVICE = "Cipher"; + + /** + * The decryption operation mode. + */ + public static final int DECRYPT_MODE = 2; + + /** + * The encryption operation mode. + */ + public static final int ENCRYPT_MODE = 1; + + /** + * Constant for when the key to be unwrapped is a private key. + */ + public static final int PRIVATE_KEY = 2; + + /** + * Constant for when the key to be unwrapped is a public key. + */ + public static final int PUBLIC_KEY = 1; + + /** + * Constant for when the key to be unwrapped is a secret key. + */ + public static final int SECRET_KEY = 3; + + /** + * The key unwrapping operation mode. + */ + public static final int UNWRAP_MODE = 4; + + /** + * The key wrapping operation mode. + */ + public static final int WRAP_MODE = 3; + + /** + * The uninitialized state. This state signals that any of the + * <code>init</code> methods have not been called, and therefore no + * transformations can be done. + */ + private static final int INITIAL_STATE = 0; + + /** The underlying cipher service provider interface. */ + private CipherSpi cipherSpi; + + /** The provider from which this instance came. */ + private Provider provider; + + /** The transformation requested. */ + private String transformation; + + /** Our current state (encrypting, wrapping, etc.) */ + private int state; + + /** + * Creates a new cipher instance for the given transformation. + * <p> + * The installed providers are tried in order for an implementation, and the + * first appropriate instance is returned. If no installed provider can + * provide the implementation, an appropriate exception is thrown. + * + * @param transformation The transformation to create. + * @return An appropriate cipher for this transformation. + * @throws NoSuchAlgorithmException If no installed provider can supply the + * appropriate cipher or mode. + * @throws NoSuchPaddingException If no installed provider can supply the + * appropriate padding. + */ + public static final Cipher getInstance(String transformation) + throws NoSuchAlgorithmException, NoSuchPaddingException + { + Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; + NoSuchPaddingException lastPaddingException = null; + for (int i = 0; i < p.length; i++) + try + { + return getInstance(transformation, p[i]); + } + catch (NoSuchAlgorithmException x) + { + lastException = x; + lastPaddingException = null; + } + catch (NoSuchPaddingException x) + { + lastPaddingException = x; + } + if (lastPaddingException != null) + throw lastPaddingException; + if (lastException != null) + throw lastException; + throw new NoSuchAlgorithmException(transformation); + } + + /** + * Creates a new cipher instance for the given transformation and the named + * provider. + * + * @param transformation The transformation to create. + * @param provider The name of the provider to use. + * @return An appropriate cipher for this transformation. + * @throws NoSuchAlgorithmException If the provider cannot supply the + * appropriate cipher or mode. + * @throws NoSuchProviderException If the named provider is not installed. + * @throws NoSuchPaddingException If the provider cannot supply the + * appropriate padding. + * @throws IllegalArgumentException if either <code>transformation</code> or + * <code>provider</code> is <code>null</code>. + */ + public static final Cipher getInstance(String transformation, String provider) + throws NoSuchAlgorithmException, NoSuchProviderException, + NoSuchPaddingException + { + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + Provider p = Security.getProvider(provider); + if (p == null) + throw new NoSuchProviderException(provider); + return getInstance(transformation, p); + } + + /** + * Creates a new cipher instance for a given transformation from a given + * provider. + * + * @param transformation The transformation to create. + * @param provider The provider to use. + * @return An appropriate cipher for this transformation. + * @throws NoSuchAlgorithmException If the given provider cannot supply the + * appropriate cipher or mode. + * @throws NoSuchPaddingException If the given provider cannot supply the + * appropriate padding scheme. + */ + public static final Cipher getInstance(String transformation, + Provider provider) + throws NoSuchAlgorithmException, NoSuchPaddingException + { + StringBuilder sb = new StringBuilder().append("Cipher transformation [") + .append(transformation).append("] from provider [") + .append(provider).append("] "); + Throwable cause; + Object spi; + CipherSpi result; + if (transformation.indexOf('/') < 0) + { + try + { + spi = Engine.getInstance(SERVICE, transformation, provider); + return new Cipher((CipherSpi) spi, provider, transformation); + } + catch (Exception e) + { + if (e instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) e; + cause = e; + } + } + else + { + StringTokenizer tok = new StringTokenizer(transformation, "/"); + if (tok.countTokens() != 3) + throw new NoSuchAlgorithmException(sb.append("is malformed").toString()); + + String alg = tok.nextToken(); + String mode = tok.nextToken(); + String pad = tok.nextToken(); + try + { + spi = Engine.getInstance(SERVICE, transformation, provider); + return new Cipher((CipherSpi) spi, provider, transformation); + } + catch (Exception e) + { + cause = e; + } + + try + { + spi = Engine.getInstance(SERVICE, alg + '/' + mode, provider); + result = (CipherSpi) spi; + result.engineSetPadding(pad); + return new Cipher(result, provider, transformation); + } + catch (Exception e) + { + if (e instanceof NoSuchPaddingException) + throw (NoSuchPaddingException) e; + cause = e; + } + + try + { + spi = Engine.getInstance(SERVICE, alg + "//" + pad, provider); + result = (CipherSpi) spi; + result.engineSetMode(mode); + return new Cipher(result, provider, transformation); + } + catch (Exception e) + { + cause = e; + } + + try + { + spi = Engine.getInstance(SERVICE, alg, provider); + result = (CipherSpi) spi; + result.engineSetMode(mode); + result.engineSetPadding(pad); + return new Cipher(result, provider, transformation); + } + catch (Exception e) + { + if (e instanceof NoSuchPaddingException) + throw (NoSuchPaddingException) e; + cause = e; + } + } + sb.append("could not be created"); + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; + } + + /** + * Create a cipher. + * + * @param cipherSpi The underlying implementation of the cipher. + * @param provider The provider of this cipher implementation. + * @param transformation The transformation this cipher performs. + */ + protected + Cipher(CipherSpi cipherSpi, Provider provider, String transformation) + { + this.cipherSpi = cipherSpi; + this.provider = provider; + this.transformation = transformation; + state = INITIAL_STATE; + } + + /** + * Get the name that this cipher instance was created with; this is + * equivalent to the "transformation" argument given to any of the + * {@link #getInstance()} methods. + * + * @return The cipher name. + */ + public final String getAlgorithm() + { + return transformation; + } + + /** + * Return the size of blocks, in bytes, that this cipher processes. + * + * @return The block size. + */ + public final int getBlockSize() + { + if (cipherSpi != null) + { + return cipherSpi.engineGetBlockSize(); + } + return 1; + } + + /** + * Return the currently-operating {@link ExemptionMechanism}. + * + * @return null, currently. + */ + public final ExemptionMechanism getExemptionMechanism() + { + return null; + } + + /** + * Return the <i>initialization vector</i> that this instance was + * initialized with. + * + * @return The IV. + */ + public final byte[] getIV() + { + if (cipherSpi != null) + { + return cipherSpi.engineGetIV(); + } + return null; + } + + /** + * Return the {@link java.security.AlgorithmParameters} that this + * instance was initialized with. + * + * @return The parameters. + */ + public final AlgorithmParameters getParameters() + { + if (cipherSpi != null) { + return cipherSpi.engineGetParameters(); + } + return null; + } + + /** + * Return this cipher's provider. + * + * @return The provider. + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Finishes a multi-part transformation, and returns the final + * transformed bytes. + * + * @return The final transformed bytes. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized, or if a <tt>doFinal</tt> call has already + * been made. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input is not a multiple of this cipher's + * block size. + * @throws javax.crypto.BadPaddingException If this instance is + * decrypting and the padding bytes do not match this + * instance's padding scheme. + */ + public final byte[] doFinal() + throws IllegalStateException, IllegalBlockSizeException, BadPaddingException + { + return doFinal(new byte[0], 0, 0); + } + + /** + * Finishes a multi-part transformation or does an entire + * transformation on the input, and returns the transformed bytes. + * + * @param input The final input bytes. + * @return The final transformed bytes. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized, or if a <tt>doFinal</tt> call has already + * been made. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input is not a multiple of this cipher's + * block size. + * @throws javax.crypto.BadPaddingException If this instance is + * decrypting and the padding bytes do not match this + * instance's padding scheme. + */ + public final byte[] doFinal(byte[] input) + throws IllegalStateException, IllegalBlockSizeException, BadPaddingException + { + return doFinal(input, 0, input.length); + } + + /** + * Finishes a multi-part transformation or does an entire + * transformation on the input, and returns the transformed bytes. + * + * @param input The final input bytes. + * @param inputOffset The index in the input bytes to start. + * @param inputLength The number of bytes to read from the input. + * @return The final transformed bytes. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized, or if a <tt>doFinal</tt> call has already + * been made. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input is not a multiple of this cipher's + * block size. + * @throws javax.crypto.BadPaddingException If this instance is + * decrypting and the padding bytes do not match this + * instance's padding scheme. + */ + public final byte[] doFinal(byte[] input, int inputOffset, int inputLength) + throws IllegalStateException, IllegalBlockSizeException, BadPaddingException + { + if (cipherSpi == null) + { + byte[] b = new byte[inputLength]; + System.arraycopy(input, inputOffset, b, 0, inputLength); + return b; + } + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + { + throw new IllegalStateException("neither encrypting nor decrypting"); + } + return cipherSpi.engineDoFinal(input, inputOffset, inputLength); + } + + /** + * Finishes a multi-part transformation and stores the transformed + * bytes into the given array. + * + * @param output The destination for the transformed bytes. + * @param outputOffset The offset in <tt>output</tt> to start storing + * bytes. + * @return The number of bytes placed into the output array. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized, or if a <tt>doFinal</tt> call has already + * been made. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input is not a multiple of this cipher's + * block size. + * @throws javax.crypto.BadPaddingException If this instance is + * decrypting and the padding bytes do not match this + * instance's padding scheme. + * @throws javax.crypto.ShortBufferException If the output array is + * not large enough to hold the transformed bytes. + */ + public final int doFinal(byte[] output, int outputOffset) + throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, + ShortBufferException + { + if (cipherSpi == null) + { + return 0; + } + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + { + throw new IllegalStateException("neither encrypting nor decrypting"); + } + return cipherSpi.engineDoFinal(new byte[0], 0, 0, output, outputOffset); + } + + /** + * Finishes a multi-part transformation or transforms a portion of a + * byte array, and stores the result in the given byte array. + * + * @param input The input bytes. + * @param inputOffset The index in <tt>input</tt> to start. + * @param inputLength The number of bytes to transform. + * @param output The output buffer. + * @param outputOffset The index in <tt>output</tt> to start. + * @return The number of bytes placed into the output array. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized, or if a <tt>doFinal</tt> call has already + * been made. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input is not a multiple of this cipher's + * block size. + * @throws javax.crypto.BadPaddingException If this instance is + * decrypting and the padding bytes do not match this + * instance's padding scheme. + * @throws javax.crypto.ShortBufferException If the output array is + * not large enough to hold the transformed bytes. + */ + public final int doFinal(byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset) + throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, + ShortBufferException + { + if (cipherSpi == null) + { + if (inputLength > output.length - outputOffset) + { + throw new ShortBufferException(); + } + System.arraycopy(input, inputOffset, output, outputOffset, inputLength); + return inputLength; + } + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + { + throw new IllegalStateException("neither encrypting nor decrypting"); + } + return cipherSpi.engineDoFinal(input, inputOffset, inputLength, + output, outputOffset); + } + + public final int doFinal(byte[] input, int inputOffset, int inputLength, + byte[] output) + throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, + ShortBufferException + { + return doFinal(input, inputOffset, inputLength, output, 0); + } + + /** + * Finishes a multi-part transformation with, or completely + * transforms, a byte buffer, and stores the result into the output + * buffer. + * + * @param input The input buffer. + * @param output The output buffer. + * @return The number of bytes stored into the output buffer. + * @throws IllegalArgumentException If the input and output buffers + * are the same object. + * @throws IllegalStateException If this cipher was not initialized + * for encryption or decryption. + * @throws ReadOnlyBufferException If the output buffer is not + * writable. + * @throws IllegalBlockSizeException If this cipher requires a total + * input that is a multiple of its block size to complete this + * transformation. + * @throws ShortBufferException If the output buffer is not large + * enough to hold the transformed bytes. + * @throws BadPaddingException If the cipher is a block cipher with + * a padding scheme, and the decrypted bytes do not end with a + * valid padding. + * @since 1.5 + */ + public final int doFinal (ByteBuffer input, ByteBuffer output) + throws ReadOnlyBufferException, ShortBufferException, + BadPaddingException, IllegalBlockSizeException + { + if (input == output) + throw new IllegalArgumentException + ("input and output buffers cannot be the same"); + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + throw new IllegalStateException + ("not initialized for encrypting or decrypting"); + return cipherSpi.engineDoFinal (input, output); + } + + /** + * Returns the size an output buffer needs to be if this cipher is + * updated with a number of bytes. + * + * @param inputLength The input length. + * @return The output length given this input length. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized, or if a <tt>doFinal</tt> call has already + * been made. + */ + public final int getOutputSize(int inputLength) throws IllegalStateException + { + if (cipherSpi == null) + return inputLength; + return cipherSpi.engineGetOutputSize(inputLength); + } + + /** + * <p>Initialize this cipher with the public key from the given + * certificate.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>As per the Java 1.4 specification, if <code>cert</code> is an + * instance of an {@link java.security.cert.X509Certificate} and its + * <i>key usage</i> extension field is incompatible with + * <code>opmode</code> then an {@link + * java.security.InvalidKeyException} is thrown.</p> + * + * <p>If this cipher requires any random bytes (for example for an + * initilization vector) than the {@link java.security.SecureRandom} + * with the highest priority is used as the source of these bytes.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param certificate The certificate. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the certificate's public key, or if the + * public key cannot be used as described above. + */ + public final void init(int opmode, Certificate certificate) + throws InvalidKeyException + { + init(opmode, certificate, new SecureRandom()); + } + + /** + * <p>Initialize this cipher with the supplied key.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>If this cipher requires any random bytes (for example for an + * initilization vector) than the {@link java.security.SecureRandom} + * with the highest priority is used as the source of these bytes.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param key The key. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the given key. + */ + public final void init(int opmode, Key key) throws InvalidKeyException + { + if (cipherSpi != null) + { + cipherSpi.engineInit(opmode, key, new SecureRandom()); + } + state = opmode; + } + + /** + * <p>Initialize this cipher with the public key from the given + * certificate and the specified source of randomness.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>As per the Java 1.4 specification, if <code>cert</code> is an + * instance of an {@link java.security.cert.X509Certificate} and its + * <i>key usage</i> extension field is incompatible with + * <code>opmode</code> then an {@link + * java.security.InvalidKeyException} is thrown.</p> + * + * <p>If this cipher requires any random bytes (for example for an + * initilization vector) than the {@link java.security.SecureRandom} + * with the highest priority is used as the source of these bytes.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param certificate The certificate. + * @param random The source of randomness. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the certificate's public key, or if the + * public key cannot be used as described above. + */ + public final void + init(int opmode, Certificate certificate, SecureRandom random) + throws InvalidKeyException + { + if (certificate instanceof X509Certificate) + { + boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage(); + if (keyInfo != null) + { + switch (opmode) + { + case DECRYPT_MODE: + if (!keyInfo[3]) + { + throw new InvalidKeyException( + "the certificate's key cannot be used for transforming data"); + } + if (keyInfo[7]) + { + throw new InvalidKeyException( + "the certificate's key can only be used for encryption"); + } + break; + + case ENCRYPT_MODE: + if (!keyInfo[3]) + { + throw new InvalidKeyException( + "the certificate's key cannot be used for transforming data"); + } + if (keyInfo[8]) + { + throw new InvalidKeyException( + "the certificate's key can only be used for decryption"); + } + break; + + case UNWRAP_MODE: + if (!keyInfo[2] || keyInfo[7]) + { + throw new InvalidKeyException( + "the certificate's key cannot be used for key unwrapping"); + } + break; + + case WRAP_MODE: + if (!keyInfo[2] || keyInfo[8]) + { + throw new InvalidKeyException( + "the certificate's key cannot be used for key wrapping"); + } + break; + } + } + } + init(opmode, certificate.getPublicKey(), random); + } + + /** + * <p>Initialize this cipher with the supplied key and source of + * randomness.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param key The key. + * @param random The source of randomness to use. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the given key. + */ + public final void init(int opmode, Key key, SecureRandom random) + throws InvalidKeyException + { + if (cipherSpi != null) + { + cipherSpi.engineInit(opmode, key, random); + } + state = opmode; + } + + /** + * <p>Initialize this cipher with the supplied key and parameters.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>If this cipher requires any random bytes (for example for an + * initilization vector) then the {@link java.security.SecureRandom} + * with the highest priority is used as the source of these bytes.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param key The key. + * @param params The algorithm parameters to initialize this instance + * with. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the given key. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inappropriate for this cipher. + */ + public final void init(int opmode, Key key, AlgorithmParameters params) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + init(opmode, key, params, new SecureRandom()); + } + + /** + * <p>Initialize this cipher with the supplied key and parameters.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>If this cipher requires any random bytes (for example for an + * initilization vector) then the {@link java.security.SecureRandom} + * with the highest priority is used as the source of these bytes.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param key The key. + * @param params The algorithm parameters to initialize this instance + * with. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the given key. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inappropriate for this cipher. + */ + public final void init(int opmode, Key key, AlgorithmParameterSpec params) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + init(opmode, key, params, new SecureRandom()); + } + + /** + * <p>Initialize this cipher with the supplied key, parameters, and + * source of randomness.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param key The key. + * @param params The algorithm parameters to initialize this instance + * with. + * @param random The source of randomness to use. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the given key. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inappropriate for this cipher. + */ + public final void init(int opmode, Key key, AlgorithmParameters params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + if (cipherSpi != null) + { + cipherSpi.engineInit(opmode, key, params, random); + } + state = opmode; + } + + /** + * <p>Initialize this cipher with the supplied key, parameters, and + * source of randomness.</p> + * + * <p>The cipher will be initialized for encryption, decryption, key + * wrapping, or key unwrapping, depending upon whether the + * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link + * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE}, + * respectively.</p> + * + * <p>A call to any of the <code>init</code> methods overrides the + * state of the instance, and is equivalent to creating a new instance + * and calling its <code>init</code> method.</p> + * + * @param opmode The operation mode to use. + * @param key The key. + * @param params The algorithm parameters to initialize this instance + * with. + * @param random The source of randomness to use. + * @throws java.security.InvalidKeyException If the underlying cipher + * instance rejects the given key. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inappropriate for this cipher. + */ + public final void init(int opmode, Key key, AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidKeyException, InvalidAlgorithmParameterException + { + if (cipherSpi != null) + { + cipherSpi.engineInit(opmode, key, params, random); + } + state = opmode; + } + + /** + * Unwrap a previously-wrapped key. + * + * @param wrappedKey The wrapped key. + * @param wrappedKeyAlgorithm The algorithm with which the key was + * wrapped. + * @param wrappedKeyType The type of key (public, private, or + * secret) that this wrapped key respresents. + * @return The unwrapped key. + * @throws java.lang.IllegalStateException If this instance has not be + * initialized for unwrapping. + * @throws java.security.InvalidKeyException If <code>wrappedKey</code> + * is not a wrapped key, if the algorithm cannot unwrap this + * key, or if the unwrapped key's type differs from the + * specified type. + * @throws java.security.NoSuchAlgorithmException If + * <code>wrappedKeyAlgorithm</code> is not a valid algorithm + * name. + */ + public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, + int wrappedKeyType) + throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException + { + if (cipherSpi == null) + { + return null; + } + if (state != UNWRAP_MODE) + { + throw new IllegalStateException("instance is not for unwrapping"); + } + return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, + wrappedKeyType); + } + + /** + * Continue a multi-part transformation on an entire byte array, + * returning the transformed bytes. + * + * @param input The input bytes. + * @return The transformed bytes. + * @throws java.lang.IllegalStateException If this cipher was not + * initialized for encryption or decryption. + */ + public final byte[] update(byte[] input) throws IllegalStateException + { + return update(input, 0, input.length); + } + + /** + * Continue a multi-part transformation on part of a byte array, + * returning the transformed bytes. + * + * @param input The input bytes. + * @param inputOffset The index in the input to start. + * @param inputLength The number of bytes to transform. + * @return The transformed bytes. + * @throws java.lang.IllegalStateException If this cipher was not + * initialized for encryption or decryption. + */ + public final byte[] update(byte[] input, int inputOffset, int inputLength) + throws IllegalStateException + { + if (cipherSpi == null) + { + byte[] b = new byte[inputLength]; + System.arraycopy(input, inputOffset, b, 0, inputLength); + return b; + } + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + { + throw new IllegalStateException( + "cipher is not for encrypting or decrypting"); + } + return cipherSpi.engineUpdate(input, inputOffset, inputLength); + } + + /** + * Continue a multi-part transformation on part of a byte array, + * placing the transformed bytes into the given array. + * + * @param input The input bytes. + * @param inputOffset The index in the input to start. + * @param inputLength The number of bytes to transform. + * @param output The output byte array. + * @return The number of transformed bytes. + * @throws java.lang.IllegalStateException If this cipher was not + * initialized for encryption or decryption. + * @throws javax.security.ShortBufferException If there is not enough + * room in the output array to hold the transformed bytes. + */ + public final int update(byte[] input, int inputOffset, int inputLength, + byte[] output) + throws IllegalStateException, ShortBufferException + { + return update(input, inputOffset, inputLength, output, 0); + } + + /** + * Continue a multi-part transformation on part of a byte array, + * placing the transformed bytes into the given array. + * + * @param input The input bytes. + * @param inputOffset The index in the input to start. + * @param inputLength The number of bytes to transform. + * @param output The output byte array. + * @param outputOffset The index in the output array to start. + * @return The number of transformed bytes. + * @throws java.lang.IllegalStateException If this cipher was not + * initialized for encryption or decryption. + * @throws javax.security.ShortBufferException If there is not enough + * room in the output array to hold the transformed bytes. + */ + public final int update(byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset) + throws IllegalStateException, ShortBufferException + { + if (cipherSpi == null) + { + if (inputLength > output.length - outputOffset) + { + throw new ShortBufferException(); + } + System.arraycopy(input, inputOffset, output, outputOffset, inputLength); + return inputLength; + } + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + { + throw new IllegalStateException( + "cipher is not for encrypting or decrypting"); + } + return cipherSpi.engineUpdate(input, inputOffset, inputLength, + output, outputOffset); + } + + /** + * Continue a multi-part transformation on a byte buffer, storing + * the transformed bytes into another buffer. + * + * @param input The input buffer. + * @param output The output buffer. + * @return The number of bytes stored in <i>output</i>. + * @throws IllegalArgumentException If the two buffers are the same + * object. + * @throws IllegalStateException If this cipher was not initialized + * for encrypting or decrypting. + * @throws ReadOnlyBufferException If the output buffer is not + * writable. + * @throws ShortBufferException If the output buffer does not have + * enough available space for the transformed bytes. + * @since 1.5 + */ + public final int update (ByteBuffer input, ByteBuffer output) + throws ReadOnlyBufferException, ShortBufferException + { + if (input == output) + throw new IllegalArgumentException + ("input and output buffers must be different"); + if (state != ENCRYPT_MODE && state != DECRYPT_MODE) + throw new IllegalStateException + ("not initialized for encryption or decryption"); + return cipherSpi.engineUpdate (input, output); + } + + /** + * Wrap a key. + * + * @param key The key to wrap. + * @return The wrapped key. + * @throws java.lang.IllegalStateException If this instance was not + * initialized for key wrapping. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the key is not a multiple of the block size. + * @throws java.security.InvalidKeyException If this instance cannot + * wrap this key. + */ + public final byte[] wrap(Key key) + throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException + { + if (cipherSpi == null) + { + return null; + } + if (state != WRAP_MODE) + { + throw new IllegalStateException("instance is not for key wrapping"); + } + return cipherSpi.engineWrap(key); + } +} diff --git a/libjava/classpath/javax/crypto/CipherInputStream.java b/libjava/classpath/javax/crypto/CipherInputStream.java new file mode 100644 index 000000000..dff7edcf1 --- /dev/null +++ b/libjava/classpath/javax/crypto/CipherInputStream.java @@ -0,0 +1,368 @@ +/* CipherInputStream.java -- Filters input through a cipher. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.classpath.Configuration; +import gnu.classpath.debug.Component; +import gnu.classpath.debug.SystemLogger; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +import java.util.logging.Logger; + +/** + * This is an {@link java.io.InputStream} that filters its data + * through a {@link Cipher} before returning it. The <code>Cipher</code> + * argument must have been initialized before it is passed to the + * constructor. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class CipherInputStream extends FilterInputStream +{ + + // Constants and variables. + // ------------------------------------------------------------------------ + + private static final Logger logger = SystemLogger.SYSTEM; + + /** + * The underlying {@link Cipher} instance. + */ + private final Cipher cipher; + + /** + * Data that has been transformed but not read. + */ + private byte[] outBuffer; + + /** + * The offset into {@link #outBuffer} where valid data starts. + */ + private int outOffset; + + /** + * We set this when the cipher block size is 1, meaning that we can + * transform any amount of data. + */ + private final boolean isStream; + + /** + * Whether or not we've reached the end of the stream. + */ + private boolean eof; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Creates a new input stream with a source input stream and cipher. + * + * @param in The underlying input stream. + * @param cipher The cipher to filter data through. + */ + public CipherInputStream(InputStream in, Cipher cipher) + { + super (in); + this.cipher = cipher; + isStream = cipher.getBlockSize () == 1; + eof = false; + if (Configuration.DEBUG) + logger.log (Component.CRYPTO, "I am born; cipher: {0}, stream? {1}", + new Object[] { cipher.getAlgorithm (), + Boolean.valueOf (isStream) }); + } + + /** + * Creates a new input stream without a cipher. This constructor is + * <code>protected</code> because this class does not work without an + * underlying cipher. + * + * @param in The underlying input stream. + */ + protected CipherInputStream(InputStream in) + { + this (in, new NullCipher ()); + } + + // Instance methods overriding java.io.FilterInputStream. + // ------------------------------------------------------------------------ + + /** + * Returns the number of bytes available without blocking. The value + * returned is the number of bytes that have been processed by the + * cipher, and which are currently buffered by this class. + * + * @return The number of bytes immediately available. + * @throws java.io.IOException If an I/O exception occurs. + */ + public int available() throws IOException + { + if (isStream) + return super.available(); + if (outBuffer == null || outOffset >= outBuffer.length) + nextBlock (); + return outBuffer.length - outOffset; + } + + /** + * Close this input stream. This method merely calls the {@link + * java.io.InputStream#close()} method of the underlying input stream. + * + * @throws java.io.IOException If an I/O exception occurs. + */ + public synchronized void close() throws IOException + { + super.close(); + } + + /** + * Read a single byte from this input stream; returns -1 on the + * end-of-file. + * + * @return The byte read, or -1 if there are no more bytes. + * @throws java.io.IOExcpetion If an I/O exception occurs. + */ + public synchronized int read() throws IOException + { + if (isStream) + { + byte[] buf = new byte[1]; + int in = super.read(); + if (in == -1) + return -1; + buf[0] = (byte) in; + try + { + cipher.update(buf, 0, 1, buf, 0); + } + catch (ShortBufferException shouldNotHappen) + { + throw new IOException(shouldNotHappen.getMessage()); + } + return buf[0] & 0xFF; + } + + if (outBuffer == null || outOffset == outBuffer.length) + { + if (eof) + return -1; + nextBlock (); + } + return outBuffer [outOffset++] & 0xFF; + } + + /** + * Read bytes into an array, returning the number of bytes read or -1 + * on the end-of-file. + * + * @param buf The byte array to read into. + * @param off The offset in <code>buf</code> to start. + * @param len The maximum number of bytes to read. + * @return The number of bytes read, or -1 on the end-of-file. + * @throws java.io.IOException If an I/O exception occurs. + */ + public synchronized int read(byte[] buf, int off, int len) + throws IOException + { + // CipherInputStream has this wierd implementation where if + // the buffer is null, this call is the same as `skip'. + if (buf == null) + return (int) skip (len); + + if (isStream) + { + len = super.read(buf, off, len); + if (len > 0) + { + try + { + cipher.update(buf, off, len, buf, off); + } + catch (ShortBufferException shouldNotHappen) + { + IOException ioe = new IOException ("Short buffer for stream cipher -- this should not happen"); + ioe.initCause (shouldNotHappen); + throw ioe; + } + } + return len; + } + + int count = 0; + while (count < len) + { + if (outBuffer == null || outOffset >= outBuffer.length) + { + if (eof) + { + if (count == 0) + count = -1; + break; + } + nextBlock(); + } + int l = Math.min (outBuffer.length - outOffset, len - count); + System.arraycopy (outBuffer, outOffset, buf, count+off, l); + count += l; + outOffset += l; + } + return count; + } + + /** + * Read bytes into an array, returning the number of bytes read or -1 + * on the end-of-file. + * + * @param buf The byte arry to read into. + * @return The number of bytes read, or -1 on the end-of-file. + * @throws java.io.IOException If an I/O exception occurs. + */ + public int read(byte[] buf) throws IOException + { + return read(buf, 0, buf.length); + } + + /** + * Skip a number of bytes. This class only supports skipping as many + * bytes as are returned by {@link #available()}, which is the number + * of transformed bytes currently in this class's internal buffer. + * + * @param bytes The number of bytes to skip. + * @return The number of bytes skipped. + */ + public long skip(long bytes) throws IOException + { + if (isStream) + { + return super.skip(bytes); + } + long ret = 0; + if (bytes > 0 && outBuffer != null && outOffset >= outBuffer.length) + { + ret = outBuffer.length - outOffset; + outOffset = outBuffer.length; + } + return ret; + } + + /** + * Returns whether or not this input stream supports the {@link + * #mark(long)} and {@link #reset()} methods; this input stream does + * not, however, and invariably returns <code>false</code>. + * + * @return <code>false</code> + */ + public boolean markSupported() + { + return false; + } + + /** + * Set the mark. This method is unsupported and is empty. + * + * @param mark Is ignored. + */ + public void mark(int mark) + { + } + + /** + * Reset to the mark. This method is unsupported and is empty. + */ + public void reset() throws IOException + { + throw new IOException("reset not supported"); + } + + // Own methods. + // ------------------------------------------------------------------------- + + // FIXME: I don't fully understand how this class is supposed to work. + + private void nextBlock() throws IOException + { + byte[] buf = new byte[cipher.getBlockSize ()]; + if (Configuration.DEBUG) + logger.log (Component.CRYPTO, "getting a new data block"); + + try + { + outBuffer = null; + outOffset = 0; + while (outBuffer == null) + { + int l = in.read (buf); + if (Configuration.DEBUG) + logger.log (Component.CRYPTO, "we read {0} bytes", + Integer.valueOf (l)); + if (l == -1) + { + outBuffer = cipher.doFinal (); + eof = true; + return; + } + + outOffset = 0; + outBuffer = cipher.update (buf, 0, l); + } + } + catch (BadPaddingException bpe) + { + IOException ioe = new IOException ("bad padding"); + ioe.initCause (bpe); + throw ioe; + } + catch (IllegalBlockSizeException ibse) + { + IOException ioe = new IOException ("illegal block size"); + ioe.initCause (ibse); + throw ioe; + } + finally + { + if (Configuration.DEBUG) + logger.log (Component.CRYPTO, + "decrypted {0} bytes for reading", + Integer.valueOf (outBuffer.length)); + } + } +} diff --git a/libjava/classpath/javax/crypto/CipherOutputStream.java b/libjava/classpath/javax/crypto/CipherOutputStream.java new file mode 100644 index 000000000..170feed47 --- /dev/null +++ b/libjava/classpath/javax/crypto/CipherOutputStream.java @@ -0,0 +1,154 @@ +/* CipherOutputStream.java -- Filters output through a cipher. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * A filtered output stream that transforms data written to it with a + * {@link Cipher} before sending it to the underlying output stream. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class CipherOutputStream extends FilterOutputStream +{ + /** The underlying cipher. */ + private Cipher cipher; + + /** + * Create a new cipher output stream. The cipher argument must have already + * been initialized. + * + * @param out The sink for transformed data. + * @param cipher The cipher to transform data with. + */ + public CipherOutputStream(OutputStream out, Cipher cipher) + { + super(out); + this.cipher = (cipher != null) ? cipher : new NullCipher(); + } + + /** + * Create a cipher output stream with no cipher. + * + * @param out The sink for transformed data. + */ + protected CipherOutputStream(OutputStream out) + { + super(out); + } + + /** + * Close this output stream, and the sink output stream. + * <p> + * This method will first invoke the {@link Cipher#doFinal()} method of the + * underlying {@link Cipher}, and writes the output of that method to the + * sink output stream. + * + * @throws IOException If an I/O error occurs, or if an error is caused by + * finalizing the transformation. + */ + public void close() throws IOException + { + try + { + out.write(cipher.doFinal()); + out.flush(); + out.close(); + } + catch (Exception cause) + { + IOException ioex = new IOException(String.valueOf(cause)); + ioex.initCause(cause); + throw ioex; + } + } + + /** + * Flush any pending output. + * + * @throws IOException If an I/O error occurs. + */ + public void flush() throws IOException + { + out.flush(); + } + + /** + * Write a single byte to the output stream. + * + * @param b The next byte. + * @throws IOException If an I/O error occurs, or if the underlying cipher is + * not in the correct state to transform data. + */ + public void write(int b) throws IOException + { + write(new byte[] { (byte) b }, 0, 1); + } + + /** + * Write a byte array to the output stream. + * + * @param buf The next bytes. + * @throws IOException If an I/O error occurs, or if the underlying cipher is + * not in the correct state to transform data. + */ + public void write(byte[] buf) throws IOException + { + write(buf, 0, buf.length); + } + + /** + * Write a portion of a byte array to the output stream. + * + * @param buf The next bytes. + * @param off The offset in the byte array to start. + * @param len The number of bytes to write. + * @throws IOException If an I/O error occurs, or if the underlying cipher is + * not in the correct state to transform data. + */ + public void write(byte[] buf, int off, int len) throws IOException + { + byte[] b = cipher.update(buf, off, len); + if (b != null) + out.write(b); + } +} diff --git a/libjava/classpath/javax/crypto/CipherSpi.java b/libjava/classpath/javax/crypto/CipherSpi.java new file mode 100644 index 000000000..194c1dabf --- /dev/null +++ b/libjava/classpath/javax/crypto/CipherSpi.java @@ -0,0 +1,445 @@ +/* CipherSpi.java -- The cipher service provider interface. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.nio.ByteBuffer; + +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; + +/** + * <p>This class represents the <i>Service Provider Interface</i> + * (<b>SPI</b>) for cryptographic ciphers.</p> + * + * <p>Providers of cryptographic ciphers must subclass this for every + * cipher they implement, implementing the abstract methods as + * appropriate, then provide an entry that points to the subclass in + * their implementation of {@link java.security.Provider}.</p> + * + * <p>CipherSpi objects are instantiated along with {@link Cipher}s when + * the {@link Cipher#getInstance(java.lang.String)} methods are invoked. + * Particular ciphers are referenced by a <i>transformation</i>, which + * is a String consisting of the cipher's name or the ciper's name + * followed by a mode and a padding. Transformations all follow the + * general form:</p> + * + * <ul> + * <li><i>algorithm</i>, or</li> + * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i> + * </ul> + * + * <p>Cipher names in the master {@link java.security.Provider} class + * may be:</p> + * + * <ol> + * <li>The algorithm's name, which uses a pluggable mode and padding: + * <code>Cipher.<i>algorithm</i></code></li> + * <li>The algorithm's name and the mode, which uses pluggable padding: + * <code>Cipher.<i>algorithm</i>/<i>mode</i></code></li> + * <li>The algorithm's name and the padding, which uses a pluggable + * mode: <code>Cipher.<i>algorithm</i>//<i>padding</i></code></li> + * <li>The algorihtm's name, the mode, and the padding: + * <code>Cipher.<i>algorithm</i>/<i>mode</i>/<i>padding</i></code></li> + * </ol> + * + * <p>When any {@link Cipher#getInstance(java.lang.String)} method is + * invoked, the following happens if the transformation is simply + * <i>algorithm</i>:</p> + * + * <ol> + * <li>If the provider defines a <code>CipherSpi</code> implementation + * for "<i>algorithm</i>", return it. Otherwise throw a {@link + * java.security.NoSuchAlgorithmException}.</li> + * </ol> + * + * <p>If the transformation is of the form + * <i>algorithm</i>/<i>mode</i>/<i>padding</i>:</p> + * + * <ol> + * <li>If the provider defines a <code>CipherSpi</code> subclass for + * "<i>algorithm</i>/<i>mode</i>/<i>padding</i>", return it. Otherwise + * go to step 2.</li> + * + * <li>If the provider defines a <code>CipherSpi</code> subclass for + * "<i>algorithm</i>/<i>mode</i>", instatiate it, call {@link + * #engineSetPadding(java.lang.String)} for the padding name, and return + * it. Otherwise go to step 3.</li> + * + * <li>If the provider defines a <code>CipherSpi</code> subclass for + * "<i>algorithm</i>//<i>padding</i>", instatiate it, call {@link + * #engineSetMode(java.lang.String)} for the mode name, and return + * it. Otherwise go to step 4.</li> + * + * <li>If the provider defines a <code>CipherSpi</code> subclass for + * "<i>algorithm</i>", instatiate it, call {@link + * #engineSetMode(java.lang.String)} for the mode name, call {@link + * #engineSetPadding(java.lang.String)} for the padding name, and return + * it. Otherwise throw a {@link java.security.NoSuchAlgorithmException}.</li> + * </ol> + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public abstract class CipherSpi +{ + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new CipherSpi. + */ + public CipherSpi() + { + } + + // Abstract methods to be implemented by providers. + // ------------------------------------------------------------------------ + + /** + * Finishes a multi-part transformation or transforms a portion of a + * byte array, and returns the transformed bytes. + * + * @param input The input bytes. + * @param inputOffset The index in the input at which to start. + * @param inputLength The number of bytes to transform. + * @return The transformed bytes in a new array. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input size is not a multiple of the + * block size. + * @throws javax.crypto.BadPaddingException If this instance is being + * used for decryption and the padding is not appropriate for + * this instance's padding scheme. + */ + protected abstract byte[] + engineDoFinal(byte[] input, int inputOffset, int inputLength) + throws IllegalBlockSizeException, BadPaddingException; + + /** + * Finishes a multi-part transformation or transforms a portion of a + * byte array, and stores the transformed bytes in the supplied array. + * + * @param input The input bytes. + * @param inputOffset The index in the input at which to start. + * @param inputLength The number of bytes to transform. + * @param output The output byte array. + * @param outputOffset The index in the output array at which to start. + * @return The number of transformed bytes stored in the output array. + * @throws javax.crypto.IllegalBlockSizeException If this instance has + * no padding and the input size is not a multiple of the + * block size. + * @throws javax.crypto.BadPaddingException If this instance is being + * used for decryption and the padding is not appropriate for + * this instance's padding scheme. + * @throws javax.crypto.ShortBufferException If there is not enough + * space in the output array for the transformed bytes. + */ + protected abstract int + engineDoFinal(byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset) + throws IllegalBlockSizeException, BadPaddingException, ShortBufferException; + + /** + * @since 1.5 + */ + protected int engineDoFinal (ByteBuffer input, ByteBuffer output) + throws BadPaddingException, IllegalBlockSizeException, + ShortBufferException + { + int total = 0; + byte[] inbuf = new byte[256]; + while (input.hasRemaining ()) + { + int in = Math.min (inbuf.length, input.remaining ()); + input.get (inbuf, 0, in); + byte[] outbuf = new byte[engineGetOutputSize (in)]; + int out = 0; + if (input.hasRemaining ()) // i.e., we have more 'update' calls + out = engineUpdate (inbuf, 0, in, outbuf, 0); + else + out = engineDoFinal (inbuf, 0, in, outbuf, 0); + output.put (outbuf, 0, out); + total += out; + } + return total; + } + + /** + * Returns the block size of the underlying cipher. + * + * @return The block size. + */ + protected abstract int engineGetBlockSize(); + + /** + * Returns the initializaiton vector this cipher was initialized with, + * if any. + * + * @return The IV, or null if this cipher uses no IV or if this + * instance has not been initialized yet. + */ + protected abstract byte[] engineGetIV(); + + /** + * <p>Return the length of the given key in bits.</p> + * + * <p>For compatibility this method is not declared + * <code>abstract</code>, and the default implementation will throw an + * {@link java.lang.UnsupportedOperationException}. Concrete + * subclasses should override this method to return the correct + * value.</p> + * + * @param key The key to get the size for. + * @return The size of the key, in bits. + * @throws java.security.InvalidKeyException If the key's length + * cannot be determined by this implementation. + */ + protected int engineGetKeySize(Key key) throws InvalidKeyException + { + throw new UnsupportedOperationException(); + } + + /** + * <p>Returns the size, in bytes, an output buffer must be for a call + * to {@link #engineUpdate(byte[],int,int,byte[],int)} or {@link + * #engineDoFinal(byte[],int,int,byte[],int)} to succeed.</p> + * + * <p>The actual output length may be smaller than the value returned + * by this method, as it considers the padding length as well. The + * length considered is the argument plus the length of any buffered, + * unprocessed bytes.</p> + * + * @param inputLength The input length, in bytes. + * @return The size an output buffer must be. + */ + protected abstract int engineGetOutputSize(int inputLength); + + /** + * Returns the parameters that this cipher is using. This may be the + * parameters used to initialize this cipher, or it may be parameters + * that have been initialized with random values. + * + * @return This cipher's parameters, or <code>null</code> if this + * cipher does not use parameters. + */ + protected abstract AlgorithmParameters engineGetParameters(); + + /** + * Initializes this cipher with an operation mode, key, and source of + * randomness. If this cipher requires any other initializing data, + * for example an initialization vector, then it should generate it + * from the provided source of randomness. + * + * @param opmode The operation mode, one of {@link + * Cipher#DECRYPT_MODE}, {@link Cipher#ENCRYPT_MODE}, {@link + * Cipher#UNWRAP_MODE}, or {@link Cipher#WRAP_MODE}. + * @param key The key to initialize this cipher with. + * @param random The source of random bytes to use. + * @throws java.security.InvalidKeyException If the given key is not + * acceptable for this implementation. + */ + protected abstract void engineInit(int opmode, Key key, SecureRandom random) + throws InvalidKeyException; + + /** + * Initializes this cipher with an operation mode, key, parameters, + * and source of randomness. If this cipher requires any other + * initializing data, for example an initialization vector, then it should + * generate it from the provided source of randomness. + * + * @param opmode The operation mode, one of {@link + * Cipher#DECRYPT_MODE}, {@link Cipher#ENCRYPT_MODE}, {@link + * Cipher#UNWRAP_MODE}, or {@link Cipher#WRAP_MODE}. + * @param key The key to initialize this cipher with. + * @param params The algorithm parameters to initialize with. + * @param random The source of random bytes to use. + * @throws java.security.InvalidAlgorithmParameterException If the + * given parameters are not appropriate for this + * implementation. + * @throws java.security.InvalidKeyException If the given key is not + * acceptable for this implementation. + */ + protected abstract void + engineInit(int opmode, Key key, AlgorithmParameters params, + SecureRandom random) + throws InvalidAlgorithmParameterException, InvalidKeyException; + + /** + * Initializes this cipher with an operation mode, key, parameters, + * and source of randomness. If this cipher requires any other + * initializing data, for example an initialization vector, then it should + * generate it from the provided source of randomness. + * + * @param opmode The operation mode, one of {@link + * Cipher#DECRYPT_MODE}, {@link Cipher#ENCRYPT_MODE}, {@link + * Cipher#UNWRAP_MODE}, or {@link Cipher#WRAP_MODE}. + * @param key The key to initialize this cipher with. + * @param params The algorithm parameters to initialize with. + * @param random The source of random bytes to use. + * @throws java.security.InvalidAlgorithmParameterException If the + * given parameters are not appropriate for this + * implementation. + * @throws java.security.InvalidKeyException If the given key is not + * acceptable for this implementation. + */ + protected abstract void + engineInit(int opmode, Key key, AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException, InvalidKeyException; + + /** + * Set the mode in which this cipher is to run. + * + * @param mode The name of the mode to use. + * @throws java.security.NoSuchAlgorithmException If the mode is + * not supported by this cipher's provider. + */ + protected abstract void engineSetMode(String mode) + throws NoSuchAlgorithmException; + + /** + * Set the method with which the input is to be padded. + * + * @param padding The name of the padding to use. + * @throws javax.crypto.NoSuchPaddingException If the padding is not + * supported by this cipher's provider. + */ + protected abstract void engineSetPadding(String padding) + throws NoSuchPaddingException; + + /** + * <p>Unwraps a previously-wrapped key.</p> + * + * <p>For compatibility this method is not declared + * <code>abstract</code>, and the default implementation will throw an + * {@link java.lang.UnsupportedOperationException}.</p> + * + * @param wrappedKey The wrapped key. + * @param wrappedKeyAlgorithm The name of the algorithm used to wrap + * this key. + * @param wrappedKeyType The type of wrapped key; one of + * {@link Cipher#PRIVATE_KEY}, + * {@link Cipher#PUBLIC_KEY}, or + * {@link Cipher#SECRET_KEY}. + * @return The unwrapped key. + * @throws java.security.InvalidKeyException If the key cannot be + * unwrapped, or if <code>wrappedKeyType</code> is an + * inappropriate type for the unwrapped key. + * @throws java.security.NoSuchAlgorithmException If the + * <code>wrappedKeyAlgorithm</code> is unknown. + */ + protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, + int wrappedKeyType) + throws InvalidKeyException, NoSuchAlgorithmException + { + throw new UnsupportedOperationException(); + } + + /** + * Continue with a multi-part transformation, returning a new array of + * the transformed bytes. + * + * @param input The next input bytes. + * @param inputOffset The index in the input array from which to start. + * @param inputLength The number of bytes to input. + * @return The transformed bytes. + */ + protected abstract byte[] + engineUpdate(byte[] input, int inputOffset, int inputLength); + + /** + * Continue with a multi-part transformation, storing the transformed + * bytes into the specified array. + * + * @param input The next input bytes. + * @param inputOffset The index in the input from which to start. + * @param inputLength The number of bytes to input. + * @param output The output buffer. + * @param outputOffset The index in the output array from which to start. + * @return The transformed bytes. + * @throws javax.crypto.ShortBufferException If there is not enough + * space in the output array to store the transformed bytes. + */ + protected abstract int + engineUpdate(byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset) + throws ShortBufferException; + + /** + * @since 1.5 + */ + protected int engineUpdate (ByteBuffer input, ByteBuffer output) + throws ShortBufferException + { + int total = 0; + byte[] inbuf = new byte[256]; + while (input.hasRemaining ()) + { + int in = Math.min (inbuf.length, input.remaining ()); + input.get (inbuf, 0, in); + byte[] outbuf = new byte[engineGetOutputSize (in)]; + int out = engineUpdate (inbuf, 0, in, outbuf, 0); + output.put (outbuf, 0, out); + total += out; + } + return total; + } + + /** + * <p>Wrap a key.</p> + * + * <p>For compatibility this method is not declared + * <code>abstract</code>, and the default implementation will throw an + * {@link java.lang.UnsupportedOperationException}.</p> + * + * @param key The key to wrap. + * @return The wrapped key. + * @throws java.security.InvalidKeyException If the key cannot be + * wrapped. + */ + protected byte[] engineWrap(Key key) throws InvalidKeyException, IllegalBlockSizeException + { + throw new UnsupportedOperationException(); + } +} diff --git a/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java b/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java new file mode 100644 index 000000000..0fddd54bb --- /dev/null +++ b/libjava/classpath/javax/crypto/EncryptedPrivateKeyInfo.java @@ -0,0 +1,317 @@ +/* EncryptedPrivateKeyInfo.java -- As in PKCS #8. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.OID; +import gnu.java.security.der.DER; +import gnu.java.security.der.DERReader; +import gnu.java.security.der.DERValue; + +import java.io.IOException; +import java.security.AlgorithmParameters; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.ArrayList; +import java.util.List; + +/** + * An implementation of the <code>EncryptedPrivateKeyInfo</code> ASN.1 + * type as specified in <a + * href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-8/">PKCS #8 - + * Private-Key Information Syntax Standard</a>. + * + * <p>The ASN.1 type <code>EncryptedPrivateKeyInfo</code> is: + * + * <blockquote> + * <pre>EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncrytpedData ::= OCTET STRING + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL }</pre> + * </blockquote> + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see java.security.spec.PKCS8EncodedKeySpec + */ +public class EncryptedPrivateKeyInfo +{ + + // Fields. + // ------------------------------------------------------------------------ + + /** The encrypted data. */ + private byte[] encryptedData; + + /** The encoded, encrypted key. */ + private byte[] encoded; + + /** The OID of the encryption algorithm. */ + private OID algOid; + + /** The encryption algorithm name. */ + private String algName; + + /** The encryption algorithm's parameters. */ + private AlgorithmParameters params; + + /** The encoded ASN.1 algorithm parameters. */ + private byte[] encodedParams; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new <code>EncryptedPrivateKeyInfo</code> object from raw + * encrypted data and the parameters used for encryption. + * + * <p>The <code>encryptedData</code> array is cloned. + * + * @param params The encryption algorithm parameters. + * @param encryptedData The encrypted key data. + * @throws java.lang.IllegalArgumentException If the + * <code>encryptedData</code> array is empty (zero-length). + * @throws java.security.NoSuchAlgorithmException If the algorithm + * specified in the parameters is not supported. + * @throws java.lang.NullPointerException If <code>encryptedData</code> + * is null. + */ + public EncryptedPrivateKeyInfo(AlgorithmParameters params, + byte[] encryptedData) + throws IllegalArgumentException, NoSuchAlgorithmException + { + if (encryptedData.length == 0) + { + throw new IllegalArgumentException("0-length encryptedData"); + } + this.params = params; + algName = params.getAlgorithm (); + algOid = getOid (algName); + this.encryptedData = (byte[]) encryptedData.clone(); + } + + /** + * Create a new <code>EncryptedPrivateKeyInfo</code> from an encoded + * representation, parsing the ASN.1 sequence. + * + * @param encoded The encoded info. + * @throws java.io.IOException If parsing the encoded data fails. + * @throws java.lang.NullPointerException If <code>encoded</code> is + * null. + */ + public EncryptedPrivateKeyInfo(byte[] encoded) + throws IOException + { + this.encoded = (byte[]) encoded.clone(); + decode(); + } + + /** + * Create a new <code>EncryptedPrivateKeyInfo</code> from the cipher + * name and the encrytpedData. + * + * <p>The <code>encryptedData</code> array is cloned. + * + * @param algName The name of the algorithm (as an object identifier). + * @param encryptedData The encrypted key data. + * @throws java.lang.IllegalArgumentException If the + * <code>encryptedData</code> array is empty (zero-length). + * @throws java.security.NoSuchAlgorithmException If algName is not + * the name of a supported algorithm. + * @throws java.lang.NullPointerException If <code>encryptedData</code> + * is null. + */ + public EncryptedPrivateKeyInfo(String algName, byte[] encryptedData) + throws IllegalArgumentException, NoSuchAlgorithmException, + NullPointerException + { + if (encryptedData.length == 0) + { + throw new IllegalArgumentException("0-length encryptedData"); + } + this.algName = algName.toString (); // do NP check + this.algOid = getOid (algName); + this.encryptedData = (byte[]) encryptedData.clone(); + } + + /** + * Return the OID for the given cipher name. + * + * @param str The string. + * @throws NoSuchAlgorithmException If the OID is not known. + */ + private static OID getOid (final String str) + throws NoSuchAlgorithmException + { + if (str.equalsIgnoreCase ("DSA")) + { + return new OID ("1.2.840.10040.4.3"); + } + // FIXME add more + + try + { + return new OID (str); + } + catch (Throwable t) + { + } + throw new NoSuchAlgorithmException ("cannot determine OID for '" + str + "'"); + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Return the name of the cipher used to encrypt this key. + * + * @return The algorithm name. + */ + public String getAlgName() + { + return algOid.toString(); + } + + public AlgorithmParameters getAlgParameters() + { + if (params == null && encodedParams != null) + { + try + { + params = AlgorithmParameters.getInstance(getAlgName()); + params.init(encodedParams); + } + catch (NoSuchAlgorithmException ignore) + { + // FIXME throw exception? + } + catch (IOException ignore) + { + } + } + return params; + } + + public synchronized byte[] getEncoded() throws IOException + { + if (encoded == null) encode(); + return (byte[]) encoded.clone(); + } + + public byte[] getEncryptedData() + { + return encryptedData; + } + + public PKCS8EncodedKeySpec getKeySpec(Cipher cipher) + throws InvalidKeySpecException + { + try + { + return new PKCS8EncodedKeySpec(cipher.doFinal(encryptedData)); + } + catch (Exception x) + { + throw new InvalidKeySpecException(x.toString()); + } + } + + // Own methods. + // ------------------------------------------------------------------------- + + private void decode() throws IOException + { + DERReader der = new DERReader(encoded); + DERValue val = der.read(); + if (val.getTag() != DER.SEQUENCE) + throw new IOException("malformed EncryptedPrivateKeyInfo"); + val = der.read(); + if (val.getTag() != DER.SEQUENCE) + throw new IOException("malformed AlgorithmIdentifier"); + int algpLen = val.getLength(); + DERValue oid = der.read(); + if (oid.getTag() != DER.OBJECT_IDENTIFIER) + throw new IOException("malformed AlgorithmIdentifier"); + algOid = (OID) oid.getValue(); + if (algpLen == 0) + { + val = der.read(); + if (val.getTag() != 0) + { + encodedParams = val.getEncoded(); + der.read(); + } + } + else if (oid.getEncodedLength() < val.getLength()) + { + val = der.read(); + encodedParams = val.getEncoded(); + } + val = der.read(); + if (val.getTag() != DER.OCTET_STRING) + throw new IOException("malformed AlgorithmIdentifier"); + encryptedData = (byte[]) val.getValue(); + } + + private void encode() throws IOException + { + List algId = new ArrayList(2); + algId.add(new DERValue(DER.OBJECT_IDENTIFIER, algOid)); + getAlgParameters(); + if (params != null) + { + algId.add (DERReader.read (params.getEncoded())); + } + else + { + algId.add (new DERValue (DER.NULL, null)); + } + List epki = new ArrayList(2); + epki.add(new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, algId)); + epki.add(new DERValue(DER.OCTET_STRING, encryptedData)); + encoded = new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, epki).getEncoded(); + } +} diff --git a/libjava/classpath/javax/crypto/ExemptionMechanism.java b/libjava/classpath/javax/crypto/ExemptionMechanism.java new file mode 100644 index 000000000..b8b17c4af --- /dev/null +++ b/libjava/classpath/javax/crypto/ExemptionMechanism.java @@ -0,0 +1,274 @@ +/* ExemptionMechanism.java -- Generic crypto-weakening mechanism. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.Engine; + +import java.lang.reflect.InvocationTargetException; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; + +/** + * An exemption mechanism, which will conditionally allow cryptography + * where it is not normally allowed, implements things such as <i>key + * recovery</i>, <i>key weakening</i>, or <i>key escrow</i>. + * + * <p><b>Implementation note</b>: this class is present for + * API-compatibility only; it is not actually used anywhere in this library + * and this library does not, in general, support crypto weakening. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class ExemptionMechanism +{ + + // Constants and fields. + // ------------------------------------------------------------------------ + + private static final String SERVICE = "ExemptionMechanism"; + private ExemptionMechanismSpi emSpi; + private Provider provider; + private String mechanism; + private boolean virgin; + + // Constructor. + // ------------------------------------------------------------------------ + + protected ExemptionMechanism(ExemptionMechanismSpi emSpi, Provider provider, + String mechanism) + { + this.emSpi = emSpi; + this.provider = provider; + this.mechanism = mechanism; + virgin = true; + } + + /** + * Create an instance of <code>ExemptionMechanism</code> for a designated + * <code>mechanism</code> from the first Security Provider offering it. + * + * @param mechanism the name of the exemption mechanism to create. + * @return a newly created instance of <code>ExemptionMechanism</code>. + * @throws IllegalArgumentException if the provider is null. + * @throws NoSuchAlgorithmException if no such exemption mechanism is + * available from any known Security Provider. + * @throws IllegalArgumentException if <code>mechanism</code> is + * <code>null</code> or is an empty string. + */ + public static final ExemptionMechanism getInstance(String mechanism) + throws NoSuchAlgorithmException + { + Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; + for (int i = 0; i < p.length; i++) + try + { + return getInstance(mechanism, p[i]); + } + catch (NoSuchAlgorithmException x) + { + lastException = x; + } + if (lastException != null) + throw lastException; + throw new NoSuchAlgorithmException(mechanism); + } + + /** + * Create an instance of <code>ExemptionMechanism</code> for a designated + * <code>mechanism</code> from a named <code>provider</code>. + * + * @param mechanism the name of the exemption mechanism to create. + * @param provider the security provider to provide the exemption + * <code>mechanism</code>. + * @return a newly created instance of <code>ExemptionMechanism</code>. + * @throws NoSuchAlgorithmException if no such exemption mechanism is + * available from the named <code>provider</code>. + * @throws NoSuchProviderException if no Security Provider with the designated + * name is known to the underlying JVM. + * @throws IllegalArgumentException if either <code>mechanism</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>mechanism</code> is an empty string. + */ + public static final ExemptionMechanism getInstance(String mechanism, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException + { + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + Provider p = Security.getProvider(provider); + if (p == null) + throw new NoSuchProviderException(provider); + return getInstance(mechanism, p); + } + + /** + * Create an instance of <code>ExemptionMechanism</code> for a designated + * <code>mechanism</code> from a designated <code>provider</code>. + * + * @param mechanism the name of the exemption mechanism to create. + * @param provider the security provider to provide the exemption + * <code>mechanism</code>. + * @return a newly created instance of <code>ExemptionMechanism</code>. + * @throws NoSuchAlgorithmException if an exemption mechanism could not be + * created. + * @throws IllegalArgumentException if either <code>mechanism</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>mechanism</code> is an empty string. + */ + public static final ExemptionMechanism getInstance(String mechanism, + Provider provider) + throws NoSuchAlgorithmException + { + StringBuilder sb = new StringBuilder("ExemptionMechanism [") + .append(mechanism).append("] from provider[") + .append(provider).append("] could not be created"); + Throwable cause; + try + { + Object spi = Engine.getInstance(SERVICE, mechanism, provider); + return new ExemptionMechanism((ExemptionMechanismSpi) spi, + provider, + mechanism); + } + catch (InvocationTargetException x) + { + cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + } + catch (ClassCastException x) + { + cause = x; + } + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; + } + + public final byte[] genExemptionBlob() + throws IllegalStateException, ExemptionMechanismException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return emSpi.engineGenExemptionBlob(); + } + + public final int genExemptionBlob(byte[] output) + throws IllegalStateException, ExemptionMechanismException, + ShortBufferException + { + return genExemptionBlob(output, 0); + } + + public final int genExemptionBlob(byte[] output, int outputOffset) + throws IllegalStateException, ExemptionMechanismException, + ShortBufferException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return emSpi.engineGenExemptionBlob(output, outputOffset); + } + + public final String getName() + { + return mechanism; + } + + public final int getOutputSize(int inputLength) throws IllegalStateException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return emSpi.engineGetOutputSize(inputLength); + } + + public final Provider getProvider() + { + return provider; + } + + public final void init(Key key) + throws ExemptionMechanismException, InvalidKeyException + { + emSpi.engineInit(key); + virgin = false; + } + + public final void init(Key key, AlgorithmParameters params) + throws ExemptionMechanismException, InvalidAlgorithmParameterException, + InvalidKeyException + { + emSpi.engineInit(key, params); + virgin = false; + } + + public final void init(Key key, AlgorithmParameterSpec params) + throws ExemptionMechanismException, InvalidAlgorithmParameterException, + InvalidKeyException + { + emSpi.engineInit(key, params); + virgin = false; + } + + public final boolean isCryptoAllowed(Key key) + throws ExemptionMechanismException + { + return true; + } + + protected void finalize() + { + } +} diff --git a/libjava/classpath/javax/crypto/ExemptionMechanismException.java b/libjava/classpath/javax/crypto/ExemptionMechanismException.java new file mode 100644 index 000000000..6cc44c70d --- /dev/null +++ b/libjava/classpath/javax/crypto/ExemptionMechanismException.java @@ -0,0 +1,78 @@ +/* ExemptionMechanismException -- An error in an exemption mechanism. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.GeneralSecurityException; + +/** + * Signals a general exception in an {@link ExemptionMechanism}. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class ExemptionMechanismException extends GeneralSecurityException +{ + + // Constant. + // ------------------------------------------------------------------------ + + /** Compatible with JDK1.4. */ + private static final long serialVersionUID = 1572699429277957109L; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new exception with no detail message. + */ + public ExemptionMechanismException() + { + super(); + } + + /** + * Create a new exception with a detail message. + * + * @param message The detail message. + */ + public ExemptionMechanismException(String message) + { + super(message); + } +} diff --git a/libjava/classpath/javax/crypto/ExemptionMechanismSpi.java b/libjava/classpath/javax/crypto/ExemptionMechanismSpi.java new file mode 100644 index 000000000..00406095e --- /dev/null +++ b/libjava/classpath/javax/crypto/ExemptionMechanismSpi.java @@ -0,0 +1,149 @@ +/* ExemptionMechanismSpi.java -- Exemption mechanism service provider interface. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.spec.AlgorithmParameterSpec; + +/** + * The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@link + * ExemptionMechanism} class. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public abstract class ExemptionMechanismSpi +{ + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new exemption mechanism SPI. + */ + public ExemptionMechanismSpi() + { + } + + // Abstract instance methods. + // ------------------------------------------------------------------------ + + /** + * Return a key blob for the key that this mechanism was initialized + * with. + * + * @return The key blob. + * @throws javax.crypto.ExemptionMechanismException If generating the + * blob fails. + */ + protected abstract byte[] engineGenExemptionBlob() + throws ExemptionMechanismException; + + /** + * Generate a key blob for the key that this mechanism was initialized + * with, storing it into the given byte array. + * + * @param output The destination for the key blob. + * @param outputOffset The index in the output array to start. + * @return The size of the key blob. + * @throws javax.crypto.ExemptionMechanismException If generating the + * blob fails. + * @throws javax.crypto.ShortBufferException If the output array is + * not large enough for the key blob. + */ + protected abstract int engineGenExemptionBlob(byte[] output, int outputOffset) + throws ExemptionMechanismException, ShortBufferException; + + /** + * Get the size of the output blob given an input key size. The actual + * blob may be shorter than the value returned by this method. Both + * values are in bytes. + * + * @param inputLength The input size. + * @return The output size. + */ + protected abstract int engineGetOutputSize(int inputLength); + + /** + * Initialize this mechanism with a key. + * + * @param key The key. + * @throws javax.crypto.ExemptionMechanismException If generating the + * blob fails. + * @throws java.security.InvalidKeyException If the supplied key + * cannot be used. + */ + protected abstract void engineInit(Key key) + throws ExemptionMechanismException, InvalidKeyException; + + /** + * Initialize this mechanism with a key and parameters. + * + * @param key The key. + * @param params The parameters. + * @throws javax.crypto.ExemptionMechanismException If generating the + * blob fails. + * @throws java.security.InvalidAlgorithmParameterExceptin If the + * supplied parameters are inappropriate. + * @throws java.security.InvalidKeyException If the supplied key + * cannot be used. + */ + protected abstract void engineInit(Key key, AlgorithmParameters params) + throws ExemptionMechanismException, InvalidAlgorithmParameterException, + InvalidKeyException; + + /** + * Initialize this mechanism with a key and parameters. + * + * @param key The key. + * @param params The parameters. + * @throws javax.crypto.ExemptionMechanismException If generating the + * blob fails. + * @throws java.security.InvalidAlgorithmParameterExceptin If the + * supplied parameters are inappropriate. + * @throws java.security.InvalidKeyException If the supplied key + * cannot be used. + */ + protected abstract void engineInit(Key key, AlgorithmParameterSpec params) + throws ExemptionMechanismException, InvalidAlgorithmParameterException, + InvalidKeyException; +} diff --git a/libjava/classpath/javax/crypto/IllegalBlockSizeException.java b/libjava/classpath/javax/crypto/IllegalBlockSizeException.java new file mode 100644 index 000000000..c08752aab --- /dev/null +++ b/libjava/classpath/javax/crypto/IllegalBlockSizeException.java @@ -0,0 +1,71 @@ +/* IllegalBlockSizeException.java -- Signals illegal block sizes. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.GeneralSecurityException; + +/** + * This exception is thrown when finishing encryption without padding or + * decryption and the input is not a multiple of the cipher's block + * size. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class IllegalBlockSizeException extends GeneralSecurityException +{ + + // Constant. + // ------------------------------------------------------------------------ + + /** Serialization constant. */ + private static final long serialVersionUID = -1965144811953540392L; + + // Constructors. + // ------------------------------------------------------------------------ + + public IllegalBlockSizeException() + { + super(); + } + + public IllegalBlockSizeException(String message) + { + super(message); + } +} diff --git a/libjava/classpath/javax/crypto/KeyAgreement.java b/libjava/classpath/javax/crypto/KeyAgreement.java new file mode 100644 index 000000000..fe3e226fa --- /dev/null +++ b/libjava/classpath/javax/crypto/KeyAgreement.java @@ -0,0 +1,378 @@ +/* KeyAgreement.java -- Engine for key agreement methods. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.Engine; + +import java.lang.reflect.InvocationTargetException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; + +/** + * Key agreement is a method in which two or more parties may agree on a + * secret key for symmetric cryptography or message authentication + * without transmitting any secrets in the clear. Key agreement + * algorithms typically use a public/private <i>key pair</i>, and the + * public key (along with some additional information) is sent across + * untrusted networks. + * + * <p>The most common form of key agreement used today is the + * <i>Diffie-Hellman key exchange algorithm</i>, described in <a + * href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/">PKCS #3 - + * Diffie Hellman Key Agreement Standard</a>. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see KeyGenerator + * @see SecretKey + */ +public class KeyAgreement +{ + + // Fields. + // ------------------------------------------------------------------------ + + private static final String SERVICE = "KeyAgreement"; + + /** The underlying key agreement implementation. */ + private KeyAgreementSpi kaSpi; + + /** The provider of this implementation. */ + private Provider provider; + + /** The name of this instance's algorithm. */ + private String algorithm; + + /** Singnals whether or not this instance has been initialized. */ + private boolean virgin; + + // Constructor. + // ------------------------------------------------------------------------ + + protected KeyAgreement(KeyAgreementSpi kaSpi, Provider provider, + String algorithm) + { + this.kaSpi = kaSpi; + this.provider = provider; + this.algorithm = algorithm; + virgin = true; + } + + /** + * Get an implementation of an algorithm from the first provider that + * implements it. + * + * @param algorithm The name of the algorithm to get. + * @return The proper KeyAgreement instacne, if found. + * @throws NoSuchAlgorithmException If the specified algorithm is not + * implemented by any installed provider. + * @throws IllegalArgumentException if <code>algorithm</code> is + * <code>null</code> or is an empty string. + */ + public static final KeyAgreement getInstance(String algorithm) + throws NoSuchAlgorithmException + { + Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; + for (int i = 0; i < p.length; i++) + try + { + return getInstance(algorithm, p[i]); + } + catch (NoSuchAlgorithmException x) + { + lastException = x; + } + if (lastException != null) + throw lastException; + throw new NoSuchAlgorithmException(algorithm); + } + + /** + * Return an implementation of an algorithm from a named provider. + * + * @param algorithm The name of the algorithm to create. + * @param provider The name of the provider from which to get the + * implementation. + * @return The proper KeyAgreement instance, if found. + * @throws NoSuchAlgorithmException If the named provider does not implement + * the algorithm. + * @throws NoSuchProviderException If the named provider does not exist. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final KeyAgreement getInstance(String algorithm, String provider) + throws NoSuchAlgorithmException, NoSuchProviderException + { + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + Provider p = Security.getProvider(provider); + if (p == null) + throw new NoSuchProviderException(provider); + return getInstance(algorithm, p); + } + + /** + * Return an implementation of an algorithm from a specific provider. + * + * @param algorithm The name of the algorithm to get. + * @param provider The provider from which to get the implementation. + * @return The proper KeyAgreement instance, if found. + * @throws NoSuchAlgorithmException If this provider does not implement the + * algorithm. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final KeyAgreement getInstance(String algorithm, + Provider provider) + throws NoSuchAlgorithmException + { + StringBuilder sb = new StringBuilder("KeyAgreement algorithm [") + .append(algorithm).append("] from provider[") + .append(provider).append("] could not be created"); + Throwable cause; + try + { + Object spi = Engine.getInstance(SERVICE, algorithm, provider); + return new KeyAgreement((KeyAgreementSpi) spi, provider, algorithm); + } + catch (InvocationTargetException x) + { + cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + } + catch (ClassCastException x) + { + cause = x; + } + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; + } + + /** + * Do a phase in the key agreement. The number of times this method is + * called depends upon the algorithm and the number of parties + * involved, but must be called at least once with the + * <code>lastPhase</code> flag set to <code>true</code>. + * + * @param key The key for this phase. + * @param lastPhase Should be <code>true</code> if this will be the + * last phase before generating the shared secret. + * @return The intermediate result, or <code>null</code> if there is + * no intermediate result. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized. + * @throws java.security.InvalidKeyException If the key is + * inappropriate for this algorithm. + */ + public final Key doPhase(Key key, boolean lastPhase) + throws IllegalStateException, InvalidKeyException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return kaSpi.engineDoPhase(key, lastPhase); + } + + /** + * Generate the shared secret in a new byte array. + * + * @return The shared secret. + * @throws java.lang.IllegalStateException If this instnace has not + * been initialized, or if not enough calls to + * <code>doPhase</code> have been made. + */ + public final byte[] generateSecret() throws IllegalStateException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return kaSpi.engineGenerateSecret(); + } + + /** + * Generate the shared secret and store it into the supplied array. + * + * @param sharedSecret The array in which to store the secret. + * @param offset The index in <code>sharedSecret</code> to start + * storing data. + * @return The length of the shared secret, in bytes. + * @throws java.lang.IllegalStateException If this instnace has not + * been initialized, or if not enough calls to + * <code>doPhase</code> have been made. + * @throws javax.crypto.ShortBufferException If the supplied array is + * not large enough to store the result. + */ + public final int generateSecret(byte[] sharedSecret, int offset) + throws IllegalStateException, ShortBufferException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return kaSpi.engineGenerateSecret(sharedSecret, offset); + } + + /** + * Generate the shared secret and return it as an appropriate {@link + * SecretKey}. + * + * @param algorithm The secret key's algorithm. + * @return The shared secret as a secret key. + * @throws java.lang.IllegalStateException If this instnace has not + * been initialized, or if not enough calls to + * <code>doPhase</code> have been made. + * @throws java.security.InvalidKeyException If the shared secret + * cannot be used to make a {@link SecretKey}. + * @throws java.security.NoSuchAlgorithmException If the specified + * algorithm does not exist. + */ + public final SecretKey generateSecret(String algorithm) + throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + return kaSpi.engineGenerateSecret(algorithm); + } + + /** + * Return the name of this key-agreement algorithm. + * + * @return The algorithm name. + */ + public final String getAlgorithm() + { + return algorithm; + } + + /** + * Return the provider of the underlying implementation. + * + * @return The provider. + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Initialize this key agreement with a key. This method will use the + * highest-priority {@link java.security.SecureRandom} as its source + * of randomness. + * + * @param key The key, usually the user's private key. + * @throws java.security.InvalidKeyException If the supplied key is + * not appropriate. + */ + public final void init(Key key) throws InvalidKeyException + { + init(key, new SecureRandom()); + } + + /** + * Initialize this key agreement with a key and a source of + * randomness. + * + * @param key The key, usually the user's private key. + * @param random The source of randomness. + * @throws java.security.InvalidKeyException If the supplied key is + * not appropriate. + */ + public final void init(Key key, SecureRandom random) + throws InvalidKeyException + { + kaSpi.engineInit(key, random); + virgin = false; // w00t! + } + + /** + * Initialize this key agreement with a key and parameters. This + * method will use the highest-priority {@link + * java.security.SecureRandom} as its source of randomness. + * + * @param key The key, usually the user's private key. + * @param params The algorithm parameters. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are not appropriate. + * @throws java.security.InvalidKeyException If the supplied key is + * not appropriate. + */ + public final void init(Key key, AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException, InvalidKeyException + { + init(key, params, new SecureRandom()); + } + + /** + * Initialize this key agreement with a key, parameters, and source of + * randomness. + * + * @param key The key, usually the user's private key. + * @param params The algorithm parameters. + * @param random The source of randomness. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are not appropriate. + * @throws java.security.InvalidKeyException If the supplied key is + * not appropriate. + */ + public final void init(Key key, AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException, InvalidKeyException + { + kaSpi.engineInit(key, params, random); + virgin = false; // w00t! + } +} diff --git a/libjava/classpath/javax/crypto/KeyAgreementSpi.java b/libjava/classpath/javax/crypto/KeyAgreementSpi.java new file mode 100644 index 000000000..d71c89c13 --- /dev/null +++ b/libjava/classpath/javax/crypto/KeyAgreementSpi.java @@ -0,0 +1,160 @@ +/* KeyAgreementSpi.java -- The key agreement service provider interface. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +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; + +/** + * This is the <i>Service Provider Interface</i> (<b>SPI</b>) for the + * {@link javax.crypto.KeyAgreement} class. + * + * <p>Providers wishing to implement a key agreement algorithm must + * subclass this and provide an appropriate implementation for all the + * abstract methods below, and provide an appropriate entry in the + * master {@link java.security.Provider} class (the service name for key + * agreement algorithms is <code>"KeyAgreement"</code>). + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see KeyAgreement + * @see SecretKey + */ +public abstract class KeyAgreementSpi +{ + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new KeyAgreementSpi instance. + */ + public KeyAgreementSpi() + { + } + + // Abstract instance methods. + // ------------------------------------------------------------------------ + + /** + * Do a phase in the key agreement. + * + * @param key The key to use for this phase. + * @param lastPhase <code>true</code> if this call should be the last + * phase. + * @return The intermediate result, or <code>null</code> if there is + * no intermediate result. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized. + * @throws java.security.InvalidKeyException If the supplied key is + * not appropriate. + */ + protected abstract Key engineDoPhase(Key key, boolean lastPhase) + throws IllegalStateException, InvalidKeyException; + + /** + * Generate the shared secret in a new byte array. + * + * @return The shared secret in a new byte array. + * @throws java.lang.IllegalStateException If this key agreement is + * not ready to generate the secret. + */ + protected abstract byte[] engineGenerateSecret() + throws IllegalStateException; + + /** + * Generate the shared secret, storing it into the specified array. + * + * @param sharedSecret The byte array in which to store the secret. + * @param offset The offset into the byte array to start. + * @return The size of the shared secret. + * @throws java.lang.IllegalStateException If this key agreement is + * not ready to generate the secret. + * @throws javax.crypto.ShortBufferException If there is not enough + * space in the supplied array for the shared secret. + */ + protected abstract int engineGenerateSecret(byte[] sharedSecret, int offset) + throws IllegalStateException, ShortBufferException; + + /** + * Generate the shared secret and return it as a {@link SecretKey}. + * + * @param algorithm The algorithm with which to generate the secret key. + * @return The shared secret as a secret key. + * @throws java.lang.IllegalStateException If this key agreement is + * not ready to generate the secret. + * @throws java.security.InvalidKeyException If the shared secret + * cannot be made into a {@link SecretKey}. + * @throws java.security.NoSuchAlgorithmException If + * <code>algorithm</code> cannot be found. + */ + protected abstract SecretKey engineGenerateSecret(String algorithm) + throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException; + + /** + * Initialize this key agreement with a key, parameters, and source of + * randomness. + * + * @param key The key to initialize with, usually a private key. + * @param params The parameters to initialize with. + * @param random The source of randomness to use. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inappropriate. + * @throws java.security.InvalidKeyException If the supplied key is + * inappropriate. + */ + protected abstract void engineInit(Key key, AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException, InvalidKeyException; + + /** + * Initialize this key agreement with a key and source of randomness. + * + * @param key The key to initialize with, usually a private key. + * @param random The source of randomness to use. + * @throws java.security.InvalidKeyException If the supplied key is + * inappropriate. + */ + protected abstract void engineInit(Key key, SecureRandom random) + throws InvalidKeyException; +} diff --git a/libjava/classpath/javax/crypto/KeyGenerator.java b/libjava/classpath/javax/crypto/KeyGenerator.java new file mode 100644 index 000000000..f0c80e1db --- /dev/null +++ b/libjava/classpath/javax/crypto/KeyGenerator.java @@ -0,0 +1,293 @@ +/* KeyGenerator.java -- Interface to a symmetric key generator. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.Engine; + +import java.lang.reflect.InvocationTargetException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; + +/** + * A generic producer of keys for symmetric cryptography. The keys + * returned may be simple wrappers around byte arrays, or, if the + * target cipher requires them, more complex objects. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see Cipher + * @see Mac + */ +public class KeyGenerator +{ + + // Constants and fields. + // ------------------------------------------------------------------------ + + private static final String SERVICE = "KeyGenerator"; + + /** The underlying generator implementation. */ + private KeyGeneratorSpi kgSpi; + + /** The provider of the implementation. */ + private Provider provider; + + /** The name of the algorithm. */ + private String algorithm; + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new key generator. + * + * @param kgSpi The underlying generator. + * @param provider The provider of this implementation. + * @param algorithm The algorithm's name. + */ + protected KeyGenerator(KeyGeneratorSpi kgSpi, Provider provider, + String algorithm) + { + this.kgSpi = kgSpi; + this.provider = provider; + this.algorithm = algorithm; + } + + /** + * Create a new key generator, returning the first available implementation. + * + * @param algorithm The generator algorithm name. + * @throws NoSuchAlgorithmException If the specified algorithm does not exist. + * @throws IllegalArgumentException if <code>algorithm</code> is + * <code>null</code> or is an empty string. + */ + public static final KeyGenerator getInstance(String algorithm) + throws NoSuchAlgorithmException + { + Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; + for (int i = 0; i < p.length; i++) + try + { + return getInstance(algorithm, p[i]); + } + catch (NoSuchAlgorithmException x) + { + lastException = x; + } + if (lastException != null) + throw lastException; + throw new NoSuchAlgorithmException(algorithm); + } + + /** + * Create a new key generator from the named provider. + * + * @param algorithm The generator algorithm name. + * @param provider The name of the provider to use. + * @return An appropriate key generator, if found. + * @throws NoSuchAlgorithmException If the specified algorithm is not + * implemented by the named provider. + * @throws NoSuchProviderException If the named provider does not exist. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final KeyGenerator getInstance(String algorithm, String provider) + throws NoSuchAlgorithmException, NoSuchProviderException + { + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + Provider p = Security.getProvider(provider); + if (p == null) + throw new NoSuchProviderException(provider); + return getInstance(algorithm, p); + } + + /** + * Create a new key generator from the supplied provider. + * + * @param algorithm The generator algorithm name. + * @param provider The provider to use. + * @return An appropriate key generator, if found. + * @throws NoSuchAlgorithmException If the specified algorithm is not + * implemented by the provider. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final KeyGenerator getInstance(String algorithm, + Provider provider) + throws NoSuchAlgorithmException + { + StringBuilder sb = new StringBuilder("KeyGenerator algorithm [") + .append(algorithm).append("] from provider[") + .append(provider).append("] could not be created"); + Throwable cause; + try + { + Object spi = Engine.getInstance(SERVICE, algorithm, provider); + KeyGenerator instance = new KeyGenerator((KeyGeneratorSpi) spi, + provider, + algorithm); + instance.init(new SecureRandom()); + return instance; + } + catch (InvocationTargetException x) + { + cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + } + catch (ClassCastException x) + { + cause = x; + } + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; + } + + /** + * Generate a key. + * + * @return The new key. + */ + public final SecretKey generateKey() + { + return kgSpi.engineGenerateKey(); + } + + /** + * Return the name of this key generator. + * + * @return The algorithm name. + */ + public final String getAlgorithm() + { + return algorithm; + } + + /** + * Return the provider of the underlying implementation. + * + * @return The provider. + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Initialize this key generator with a set of parameters; the + * highest-priority {@link java.security.SecureRandom} implementation + * will be used. + * + * @param params The algorithm parameters. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inapproprate. + */ + public final void init(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException + { + init(params, new SecureRandom()); + } + + /** + * Initialize this key generator with a set of parameters and a source + * of randomness. + * + * @param params The algorithm parameters. + * @param random The source of randomness. + * @throws java.security.InvalidAlgorithmParameterException If the + * supplied parameters are inapproprate. + */ + public final void init(AlgorithmParameterSpec params, SecureRandom random) + throws InvalidAlgorithmParameterException + { + kgSpi.engineInit(params, random); + } + + /** + * Initialize this key generator with a key size (in bits); the + * highest-priority {@link java.security.SecureRandom} implementation + * will be used. + * + * @param keySize The target key size, in bits. + * @throws java.security.InvalidParameterException If the + * key size is unsupported. + */ + public final void init(int keySize) + { + init(keySize, new SecureRandom()); + } + + /** + * Initialize this key generator with a key size (in bits) and a + * source of randomness. + * + * @param keySize The target key size, in bits. + * @param random The source of randomness. + * @throws java.security.InvalidAlgorithmParameterException If the + * key size is unsupported. + */ + public final void init(int keySize, SecureRandom random) + { + kgSpi.engineInit(keySize, random); + } + + /** + * Initialize this key generator with a source of randomness. The + * implementation-specific default parameters (such as key size) will + * be used. + * + * @param random The source of randomness. + */ + public final void init(SecureRandom random) + { + kgSpi.engineInit(random); + } +} diff --git a/libjava/classpath/javax/crypto/KeyGeneratorSpi.java b/libjava/classpath/javax/crypto/KeyGeneratorSpi.java new file mode 100644 index 000000000..1c481890b --- /dev/null +++ b/libjava/classpath/javax/crypto/KeyGeneratorSpi.java @@ -0,0 +1,112 @@ +/* KeyGeneratorSpi.java -- The key generator service provider interface. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.InvalidAlgorithmParameterException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +/** + * The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@link + * KeyGenerator} class. + * + * <p>Providers wishing to implement a key generator must subclass this + * and provide an appropriate implementation for all the abstract + * methods below, and provide an appropriate entry in the master {@link + * java.security.Provider} class (the service name for key generators is + * <code>"KeyGenerator"</code>). + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see KeyGenerator + */ +public abstract class KeyGeneratorSpi +{ + + // Constructor. + // ------------------------------------------------------------------------ + + /** Create a new key generator SPI. */ + public KeyGeneratorSpi() + { + } + + // Abstract instance methods. + // ------------------------------------------------------------------------ + + /** + * Generate a key, returning it as a {@link SecretKey}. + * + * @return The generated key. + */ + protected abstract SecretKey engineGenerateKey(); + + /** + * Initialize this key generator with parameters and a source of + * randomness. + * + * @param params The parameters. + * @param random The source of randomness. + * @throws java.security.InvalidAlgorithmParameterException If the + * parameters are inappropriate for this instance. + */ + protected abstract void engineInit(AlgorithmParameterSpec params, + SecureRandom random) + throws InvalidAlgorithmParameterException; + + /** + * Initialize this key generator with a key size (in bits) and a + * source of randomness. + * + * @param keySize The target key size, in bits. + * @param random The source of randomness. + * @throws java.security.InvalidParameterException If the + * key size is illogical or unsupported. + */ + protected abstract void engineInit(int keySize, SecureRandom random); + + /** + * Initialize this key generator with a source of randomness; the + * implementation should use reasonable default parameters (such as + * generated key size). + * + * @param random The source of randomness. + */ + protected abstract void engineInit(SecureRandom random); +} diff --git a/libjava/classpath/javax/crypto/Mac.java b/libjava/classpath/javax/crypto/Mac.java new file mode 100644 index 000000000..9175e5800 --- /dev/null +++ b/libjava/classpath/javax/crypto/Mac.java @@ -0,0 +1,434 @@ +/* Mac.java -- The message authentication code interface. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.Engine; + +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.AlgorithmParameterSpec; + +/** + * This class implements a "message authentication code" (MAC), a method + * to ensure the integrity of data transmitted between two parties who + * share a common secret key. + * + * <p>The best way to describe a MAC is as a <i>keyed one-way hash + * function</i>, which looks like: + * + * <blockquote><p><code>D = MAC(K, M)</code></blockquote> + * + * <p>where <code>K</code> is the key, <code>M</code> is the message, + * and <code>D</code> is the resulting digest. One party will usually + * send the concatenation <code>M || D</code> to the other party, who + * will then verify <code>D</code> by computing <code>D'</code> in a + * similar fashion. If <code>D == D'</code>, then the message is assumed + * to be authentic. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class Mac implements Cloneable +{ + + // Fields. + // ------------------------------------------------------------------------ + + private static final String SERVICE = "Mac"; + + /** The underlying MAC implementation. */ + private MacSpi macSpi; + + /** The provider we got our implementation from. */ + private Provider provider; + + /** The name of the algorithm. */ + private String algorithm; + + /** Whether or not we've been initialized. */ + private boolean virgin; + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Creates a new Mac instance. + * + * @param macSpi The underlying MAC implementation. + * @param provider The provider of this implementation. + * @param algorithm The name of this MAC algorithm. + */ + protected Mac(MacSpi macSpi, Provider provider, String algorithm) + { + this.macSpi = macSpi; + this.provider = provider; + this.algorithm = algorithm; + virgin = true; + } + + /** + * Create an instance of the named algorithm from the first provider with an + * appropriate implementation. + * + * @param algorithm The name of the algorithm. + * @return An appropriate Mac instance, if the specified algorithm is + * implemented by a provider. + * @throws NoSuchAlgorithmException If no implementation of the named + * algorithm is installed. + * @throws IllegalArgumentException if <code>algorithm</code> is + * <code>null</code> or is an empty string. + */ + public static final Mac getInstance(String algorithm) + throws NoSuchAlgorithmException + { + Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; + for (int i = 0; i < p.length; i++) + try + { + return getInstance(algorithm, p[i]); + } + catch (NoSuchAlgorithmException x) + { + lastException = x; + } + if (lastException != null) + throw lastException; + throw new NoSuchAlgorithmException(algorithm); + } + + /** + * Create an instance of the named algorithm from the named provider. + * + * @param algorithm The name of the algorithm. + * @param provider The name of the provider. + * @return An appropriate Mac instance, if the specified algorithm is + * implemented by the named provider. + * @throws NoSuchAlgorithmException If the named provider has no + * implementation of the algorithm. + * @throws NoSuchProviderException If the named provider does not exist. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final Mac getInstance(String algorithm, String provider) + throws NoSuchAlgorithmException, NoSuchProviderException + { + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + Provider p = Security.getProvider(provider); + if (p == null) + throw new NoSuchProviderException(provider); + return getInstance(algorithm, p); + } + + /** + * Create an instance of the named algorithm from a provider. + * + * @param algorithm The name of the algorithm. + * @param provider The provider. + * @return An appropriate Mac instance, if the specified algorithm is + * implemented by the provider. + * @throws NoSuchAlgorithmException If the provider has no implementation of + * the algorithm. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final Mac getInstance(String algorithm, Provider provider) + throws NoSuchAlgorithmException + { + StringBuilder sb = new StringBuilder("Mac algorithm [") + .append(algorithm).append("] from provider[") + .append(provider).append("] could not be created"); + Throwable cause; + try + { + Object spi = Engine.getInstance(SERVICE, algorithm, provider); + return new Mac((MacSpi) spi, provider, algorithm); + } + catch (InvocationTargetException x) + { + cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + } + catch (ClassCastException x) + { + cause = x; + } + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; + } + + /** + * Finishes the computation of a MAC and returns the digest. + * + * <p>After this method succeeds, it may be used again as just after a + * call to <code>init</code>, and can compute another MAC using the + * same key and parameters. + * + * @return The message authentication code. + * @throws java.lang.IllegalStateException If this instnace has not + * been initialized. + */ + public final byte[] doFinal() throws IllegalStateException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + byte[] digest = macSpi.engineDoFinal(); + reset(); + return digest; + } + + /** + * Finishes the computation of a MAC with a final byte array (or + * computes a MAC over those bytes only) and returns the digest. + * + * <p>After this method succeeds, it may be used again as just after a + * call to <code>init</code>, and can compute another MAC using the + * same key and parameters. + * + * @param input The bytes to add. + * @return The message authentication code. + * @throws java.lang.IllegalStateException If this instnace has not + * been initialized. + */ + public final byte[] doFinal(byte[] input) throws IllegalStateException + { + update(input); + byte[] digest = macSpi.engineDoFinal(); + reset(); + return digest; + } + + /** + * Finishes the computation of a MAC and places the result into the + * given array. + * + * <p>After this method succeeds, it may be used again as just after a + * call to <code>init</code>, and can compute another MAC using the + * same key and parameters. + * + * @param output The destination for the result. + * @param outOffset The index in the output array to start. + * @return The message authentication code. + * @throws java.lang.IllegalStateException If this instnace has not + * been initialized. + * @throws javax.crypto.ShortBufferException If <code>output</code> is + * not large enough to hold the result. + */ + public final void doFinal(byte[] output, int outOffset) + throws IllegalStateException, ShortBufferException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + if (output.length - outOffset < getMacLength()) + { + throw new ShortBufferException(); + } + byte[] mac = macSpi.engineDoFinal(); + System.arraycopy(mac, 0, output, outOffset, getMacLength()); + reset(); + } + + /** + * Returns the name of this MAC algorithm. + * + * @return The MAC name. + */ + public final String getAlgorithm() + { + return algorithm; + } + + /** + * Get the size of the MAC. This is the size of the array returned by + * {@link #doFinal()} and {@link #doFinal(byte[])}, and the minimum + * number of bytes that must be available in the byte array passed to + * {@link #doFinal(byte[],int)}. + * + * @return The MAC length. + */ + public final int getMacLength() + { + return macSpi.engineGetMacLength(); + } + + /** + * Get the provider of the underlying implementation. + * + * @return The provider. + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Initialize this MAC with a key and no parameters. + * + * @param key The key to initialize this instance with. + * @throws java.security.InvalidKeyException If the key is + * unacceptable. + */ + public final void init(Key key) throws InvalidKeyException + { + try + { + init(key, null); + } + catch (InvalidAlgorithmParameterException iape) + { + throw new IllegalArgumentException(algorithm + " needs parameters"); + } + } + + /** + * Initialize this MAC with a key and parameters. + * + * @param key The key to initialize this instance with. + * @param params The algorithm-specific parameters. + * @throws java.security.InvalidAlgorithmParameterException If the + * algorithm parameters are unacceptable. + * @throws java.security.InvalidKeyException If the key is + * unacceptable. + */ + public final void init(Key key, AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException, InvalidKeyException + { + macSpi.engineInit(key, params); + virgin = false; // w00t! + } + + /** + * Reset this instance. A call to this method returns this instance + * back to the state it was in just after it was initialized. + */ + public final void reset() + { + macSpi.engineReset(); + } + + /** + * Update the computation with a single byte. + * + * @param input The next byte. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized. + */ + public final void update(byte input) throws IllegalStateException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + macSpi.engineUpdate(input); + } + + /** + * Update the computation with a byte array. + * + * @param input The next bytes. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized. + */ + public final void update(byte[] input) throws IllegalStateException + { + update(input, 0, input.length); + } + + /** + * Update the computation with a portion of a byte array. + * + * @param input The next bytes. + * @param offset The index in <code>input</code> to start. + * @param length The number of bytes to update. + * @throws java.lang.IllegalStateException If this instance has not + * been initialized. + */ + public final void update(byte[] input, int offset, int length) + throws IllegalStateException + { + if (virgin) + { + throw new IllegalStateException("not initialized"); + } + macSpi.engineUpdate(input, offset, length); + } + + /** + * Update this MAC with the remaining bytes in the given buffer + * @param buffer The input buffer. + * @since 1.5 + */ + public final void update (final ByteBuffer buffer) + { + if (virgin) + throw new IllegalStateException ("not initialized"); + macSpi.engineUpdate(buffer); + } + + /** + * Clone this instance, if the underlying implementation supports it. + * + * @return A clone of this instance. + * @throws java.lang.CloneNotSupportedException If the underlying + * implementation is not cloneable. + */ + public final Object clone() throws CloneNotSupportedException + { + Mac result = new Mac((MacSpi) macSpi.clone(), provider, algorithm); + result.virgin = virgin; + return result; + } +} diff --git a/libjava/classpath/javax/crypto/MacSpi.java b/libjava/classpath/javax/crypto/MacSpi.java new file mode 100644 index 000000000..a03aa6983 --- /dev/null +++ b/libjava/classpath/javax/crypto/MacSpi.java @@ -0,0 +1,163 @@ +/* MacSpi.java -- The MAC service provider interface. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.nio.ByteBuffer; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.spec.AlgorithmParameterSpec; + +/** + * This is the <i>Service Provider Interface</i> (<b>SPI</b>) for the + * {@link Mac} class. + * + * <p>Providers wishing to implement a Mac must subclass this class and + * provide appropriate implementations of all its abstract methods, + * then provide an entry pointing to this implementation in the master + * {@link java.security.Provider} class. + * + * <p>Implementations may optionally implement the {@link + * java.lang.Cloneable} interface. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public abstract class MacSpi +{ + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new MacSpi instance. + */ + public MacSpi() + { + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Returns a clone of this instance if cloning is supported. + * + * @return A clone of this instance. + * @throws java.lang.CloneNotSupportedException If this instance does + * not support cloneing. + */ + public Object clone() throws CloneNotSupportedException + { + return super.clone(); + } + + // Abstract instance methods. + // ------------------------------------------------------------------------ + + /** + * Finalize the computation of this MAC and return the result as a + * byte array. + * + * @return The MAC. + */ + protected abstract byte[] engineDoFinal(); + + /** + * Return the total length, in bytes, of the computed MAC (the length + * of the byte array returned by {@link #doFinal()}. + * + * @return The MAC length. + */ + protected abstract int engineGetMacLength(); + + /** + * Initialize (or re-initialize) this instance. + * + * @param key The key to use. + * @param params The parameters to use. + * @throws java.security.InvalidAlgorithmParameterException If this + * instance rejects the specified parameters. + * @throws java.security.InvalidKeyException If this instance rejects + * the specified key. + */ + protected abstract void engineInit(Key key, AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException, InvalidKeyException; + + /** + * Reset this instance. After this method succeeds, the state of this + * instance should be the same as it was before any data was input + * (possibly after a call to {@link + * #init(java.security.Key,java.security.spec.AlgorithmParameterSpec)}, + * possibly not). + */ + protected abstract void engineReset(); + + /** + * Update this MAC with a single byte. + * + * @param input The next byte. + */ + protected abstract void engineUpdate(byte input); + + /** + * Update this MAC with a portion of a byte array. + * + * @param input The next bytes. + * @param offset The index in <code>input</code> at which to start. + * @param length The number of bytes to update. + */ + protected abstract void engineUpdate(byte[] input, int offset, int length); + + /** + * Update this MAC with the remaining bytes of a buffer. + * + * @param buffer The input buffer. + * @since 1.5 + */ + protected void engineUpdate (final ByteBuffer buffer) + { + byte[] buf = new byte[1024]; + while (buffer.hasRemaining ()) + { + int n = Math.min (buffer.remaining (), buf.length); + buffer.get (buf, 0, n); + engineUpdate (buf, 0, n); + } + } +} diff --git a/libjava/classpath/javax/crypto/NoSuchPaddingException.java b/libjava/classpath/javax/crypto/NoSuchPaddingException.java new file mode 100644 index 000000000..57ada3c5d --- /dev/null +++ b/libjava/classpath/javax/crypto/NoSuchPaddingException.java @@ -0,0 +1,71 @@ +/* NoSuchPaddingException.java -- Signals an unknown padding scheme. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.GeneralSecurityException; + +/** + * This exception is thrown when a particular padding scheme is + * requested but is not available. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class NoSuchPaddingException extends GeneralSecurityException +{ + + // Constant. + // ------------------------------------------------------------------------ + + /** Serialization constant. */ + private static final long serialVersionUID = -4572885201200175466L; + + // Constructors. + // ------------------------------------------------------------------------ + + public NoSuchPaddingException() + { + super(); + } + + public NoSuchPaddingException(String message) + { + super(message); + } +} diff --git a/libjava/classpath/javax/crypto/NullCipher.java b/libjava/classpath/javax/crypto/NullCipher.java new file mode 100644 index 000000000..1913afb35 --- /dev/null +++ b/libjava/classpath/javax/crypto/NullCipher.java @@ -0,0 +1,62 @@ +/* NullCipher.java -- The identity cipher. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +/** + * Trivial subclass of Cipher that implements the <i>identity + * transformation</i>, where the input is always copied to the output + * unchanged. Null ciphers can be instantiated with the public + * constructor. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class NullCipher extends Cipher +{ + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new identity cipher. + */ + public NullCipher() + { + super(new NullCipherImpl(), null, "NULL"); + } +} diff --git a/libjava/classpath/javax/crypto/NullCipherImpl.java b/libjava/classpath/javax/crypto/NullCipherImpl.java new file mode 100644 index 000000000..2ff5e0e77 --- /dev/null +++ b/libjava/classpath/javax/crypto/NullCipherImpl.java @@ -0,0 +1,127 @@ +/* NullCipherImpl.java -- implementation of NullCipher. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.AlgorithmParameters; +import java.security.Key; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +/** + * Implementation of the identity cipher. + */ +final class NullCipherImpl extends CipherSpi +{ + + // Constructor. + // ------------------------------------------------------------------------- + + NullCipherImpl() + { + super(); + } + + // Instance methods. + // ------------------------------------------------------------------------- + + protected void engineSetMode(String mode) { } + protected void engineSetPadding(String padding) { } + + protected int engineGetBlockSize() + { + return 1; + } + + protected int engineGetOutputSize(int inputLen) + { + return inputLen; + } + + protected byte[] engineGetIV() + { + return null; + } + + protected AlgorithmParameters engineGetParameters() + { + return null; + } + + protected void engineInit(int mode, Key key, SecureRandom random) { } + protected void engineInit(int mode, Key key, AlgorithmParameterSpec spec, SecureRandom random) { } + protected void engineInit(int mode, Key key, AlgorithmParameters params, SecureRandom random) { } + + protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) + { + if (input == null) + return new byte[0]; + if (inputOffset < 0 || inputLen < 0 || inputOffset + inputLen > input.length) + throw new ArrayIndexOutOfBoundsException(); + byte[] output = new byte[inputLen]; + System.arraycopy(input, inputOffset, output, 0, inputLen); + return output; + } + + protected int engineUpdate(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException + { + if (input == null) + return 0; + if (inputOffset < 0 || inputLen < 0 || inputOffset + inputLen > input.length + || outputOffset < 0) + throw new ArrayIndexOutOfBoundsException(); + if (output.length - outputOffset < inputLen) + throw new ShortBufferException(); + System.arraycopy(input, inputOffset, output, outputOffset, inputLen); + return inputLen; + } + + protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) + { + return engineUpdate(input, inputOffset, inputLen); + } + + protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, + byte[] output, int outputOffset) + throws ShortBufferException + { + return engineUpdate(input, inputOffset, inputLen, output, outputOffset); + } +} diff --git a/libjava/classpath/javax/crypto/SealedObject.java b/libjava/classpath/javax/crypto/SealedObject.java new file mode 100644 index 000000000..0f28f3335 --- /dev/null +++ b/libjava/classpath/javax/crypto/SealedObject.java @@ -0,0 +1,355 @@ +/* SealedObject.java -- An encrypted Serializable object. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +/** + * This class allows any {@link java.io.Serializable} object to be + * stored in an encrypted form. + * + * <p>When the sealed object is ready to be unsealed (and deserialized) + * the caller may use either + * + * <ol> + * <li>{@link #getObject(javax.crypto.Cipher)}, which uses an + * already-initialized {@link javax.crypto.Cipher}.<br> + * <br> + * or,</li> + * + * <li>{@link #getObject(java.security.Key)} or {@link + * #getObject(java.security.Key,java.lang.String)}, which will + * initialize a new cipher instance with the {@link #encodedParams} that + * were stored with this sealed object (this is so parameters, such as + * the IV, don't need to be known by the one unsealing the object).</li> + * </ol> + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class SealedObject implements Serializable +{ + + // Constants and fields. + // ------------------------------------------------------------------------ + + /** The encoded algorithm parameters. */ + protected byte[] encodedParams; + + /** The serialized, encrypted object. */ + private byte[] encryptedContent; + + /** The algorithm used to seal the object. */ + private String sealAlg; + + /** The parameter type. */ + private String paramsAlg; + + /** The cipher that decrypts when this object is unsealed. */ + private transient Cipher sealCipher; + + /** Compatible with JDK1.4. */ + private static final long serialVersionUID = 4482838265551344752L; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new sealed object from a {@link java.io.Serializable} + * object and a cipher. + * + * @param object The object to seal. + * @param cipher The cipher to encrypt with. + * @throws java.io.IOException If serializing the object fails. + * @throws javax.crypto.IllegalBlockSizeException If the cipher has no + * padding and the size of the serialized representation of the + * object is not a multiple of the cipher's block size. + */ + public SealedObject(Serializable object, Cipher cipher) + throws IOException, IllegalBlockSizeException + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(object); + oos.flush(); + try + { + encryptedContent = cipher.doFinal(baos.toByteArray()); + } + catch (IllegalStateException ise) + { + throw new IOException("cipher not in proper state"); + } + catch (BadPaddingException bpe) + { + throw new IOException( + "encrypting but got javax.crypto.BadPaddingException"); + } + sealAlg = cipher.getAlgorithm(); + encodedParams = cipher.getParameters().getEncoded(); + paramsAlg = cipher.getParameters().getAlgorithm(); + } + + /** + * Create a new sealed object from another sealed object. + * + * @param so The other sealed object. + */ + protected SealedObject(SealedObject so) + { + this.encodedParams = (byte[]) so.encodedParams.clone(); + this.encryptedContent = (byte[]) so.encryptedContent.clone(); + this.sealAlg = so.sealAlg; + this.paramsAlg = so.paramsAlg; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Get the name of the algorithm used to seal this object. + * + * @return The algorithm's name. + */ + public final String getAlgorithm() + { + return sealAlg; + } + + /** + * Unseal and deserialize this sealed object with a specified (already + * initialized) cipher. + * + * @param cipher The cipher to decrypt with. + * @return The original object. + * @throws java.io.IOException If reading fails. + * @throws java.lang.ClassNotFoundException If deserialization fails. + * @throws javax.crypto.IllegalBlockSizeException If the cipher has no + * padding and the encrypted data is not a multiple of the + * cipher's block size. + * @throws javax.crypto.BadPaddingException If the padding bytes are + * incorrect. + */ + public final Object getObject(Cipher cipher) + throws IOException, ClassNotFoundException, IllegalBlockSizeException, + BadPaddingException + { + sealCipher = cipher; + return unseal(); + } + + /** + * Unseal and deserialize this sealed object with the specified key. + * + * @param key The key to decrypt with. + * @return The original object. + * @throws java.io.IOException If reading fails. + * @throws java.lang.ClassNotFoundException If deserialization fails. + * @throws java.security.InvalidKeyException If the supplied key + * cannot be used to unseal this object. + * @throws java.security.NoSuchAlgorithmException If the algorithm + * used to originally seal this object is not available. + */ + public final Object getObject(Key key) + throws IOException, ClassNotFoundException, InvalidKeyException, + NoSuchAlgorithmException + { + try + { + if (sealCipher == null) + sealCipher = Cipher.getInstance(sealAlg); + } + catch (NoSuchPaddingException nspe) + { + throw new NoSuchAlgorithmException(nspe.getMessage()); + } + AlgorithmParameters params = null; + if (encodedParams != null) + { + params = AlgorithmParameters.getInstance(paramsAlg); + params.init(encodedParams); + } + try + { + sealCipher.init(Cipher.DECRYPT_MODE, key, params); + return unseal(); + } + catch (InvalidAlgorithmParameterException iape) + { + throw new IOException("bad parameters"); + } + catch (IllegalBlockSizeException ibse) + { + throw new IOException("illegal block size"); + } + catch (BadPaddingException bpe) + { + throw new IOException("bad padding"); + } + } + + /** + * Unseal and deserialize this sealed object with the specified key, + * using a cipher from the named provider. + * + * @param key The key to decrypt with. + * @param provider The name of the provider to use. + * @return The original object. + * @throws java.io.IOException If reading fails. + * @throws java.lang.ClassNotFoundException If deserialization fails. + * @throws java.security.InvalidKeyException If the supplied key + * cannot be used to unseal this object. + * @throws java.security.NoSuchAlgorithmException If the algorithm + * used to originally seal this object is not available from + * the named provider. + * @throws java.security.NoSuchProviderException If the named provider + * does not exist. + */ + public final Object getObject(Key key, String provider) + throws IOException, ClassNotFoundException, InvalidKeyException, + NoSuchAlgorithmException, NoSuchProviderException + { + try + { + sealCipher = Cipher.getInstance(sealAlg, provider); + } + catch (NoSuchPaddingException nspe) + { + throw new NoSuchAlgorithmException(nspe.getMessage()); + } + AlgorithmParameters params = null; + if (encodedParams != null) + { + params = AlgorithmParameters.getInstance(paramsAlg, provider); + params.init(encodedParams); + } + try + { + sealCipher.init(Cipher.DECRYPT_MODE, key, params); + return unseal(); + } + catch (InvalidAlgorithmParameterException iape) + { + throw new IOException("bad parameters"); + } + catch (IllegalBlockSizeException ibse) + { + throw new IOException("illegal block size"); + } + catch (BadPaddingException bpe) + { + throw new IOException("bad padding"); + } + } + + // Own methods. + // ------------------------------------------------------------------------ + + /** + * Deserialize this object. + * + * @param ois The input stream. + * @throws java.io.IOException If reading fails. + * @throws java.lang.ClassNotFoundException If reading fails. + */ + private void readObject(ObjectInputStream ois) + throws IOException, ClassNotFoundException + { + encodedParams = (byte[]) ois.readObject(); + encryptedContent = (byte[]) ois.readObject(); + sealAlg = (String) ois.readObject(); + paramsAlg = (String) ois.readObject(); + } + + /** + * Serialize this object. + * + * @param oos The output stream. + * @throws java.io.IOException If writing fails. + */ + private void writeObject(ObjectOutputStream oos) + throws IOException + { + oos.writeObject(encodedParams); + oos.writeObject(encryptedContent); + oos.writeObject(sealAlg); + oos.writeObject(paramsAlg); + } + + /** + * Unseal this object, returning it. + * + * @return The unsealed, deserialized Object. + * @throws java.io.IOException If reading fails. + * @throws java.io.ClassNotFoundException If reading fails. + * @throws javax.crypto.IllegalBlockSizeException If the cipher has no + * padding and the encrypted data is not a multiple of the + * cipher's block size. + * @throws javax.crypto.BadPaddingException If the padding bytes are + * incorrect. + */ + private Object unseal() + throws IOException, ClassNotFoundException, IllegalBlockSizeException, + BadPaddingException + { + ByteArrayInputStream bais = null; + try + { + bais = new ByteArrayInputStream(sealCipher.doFinal(encryptedContent)); + } + catch (IllegalStateException ise) + { + throw new IOException("cipher not initialized"); + } + ObjectInputStream ois = new ObjectInputStream(bais); + return ois.readObject(); + } +} diff --git a/libjava/classpath/javax/crypto/SecretKey.java b/libjava/classpath/javax/crypto/SecretKey.java new file mode 100644 index 000000000..5f95a1a0f --- /dev/null +++ b/libjava/classpath/javax/crypto/SecretKey.java @@ -0,0 +1,65 @@ +/* SecretKey.java -- A key for symmetric cryptography. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.Key; + +/** + * A secret key for symmetric cryptography. + * + * <p>This interface defines no new methods over {@link + * java.security.Key}, but rather is intended to be a <i>marker + * interface</i> and to provide type safety for secret keys.</p> + * + * <p>The format of secret keys should be <code>RAW</code>, as returned + * by {@link java.security.Key#getFormat()}.</p> + * + * <p>Concrete implementations of this interface should override the + * {@link java.lang.Object#equals} and {@link java.lang.Object#hashCode} + * methods of {@link java.lang.Object} to use the actual key data rather + * than the identity-based default methods.</p> + * + * @author Casey Marshall (csm@gnu.org) + * @see javax.crypto.SecretKeyFactory + * @see javax.crypto.Cipher + */ +public interface SecretKey extends Key +{ + long serialVersionUID = -4795878709595146952L; +} diff --git a/libjava/classpath/javax/crypto/SecretKeyFactory.java b/libjava/classpath/javax/crypto/SecretKeyFactory.java new file mode 100644 index 000000000..9749a8285 --- /dev/null +++ b/libjava/classpath/javax/crypto/SecretKeyFactory.java @@ -0,0 +1,255 @@ +/* SecretKeyFactory.java -- Factory for creating secret keys. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import gnu.java.security.Engine; + +import java.lang.reflect.InvocationTargetException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +/** + * A secret key factory translates {@link SecretKey} objects to and from + * {@link java.security.spec.KeySpec} objects, and can translate between + * different vendors' representations of {@link SecretKey} objects (for + * security or semantics; whichever applies). + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see SecretKey + */ +public class SecretKeyFactory +{ + + // Constants and fields. + // ------------------------------------------------------------------------ + + private static final String SERVICE = "SecretKeyFactory"; + + /** The underlying factory implementation. */ + private SecretKeyFactorySpi skfSpi; + + /** The provider of the implementation. */ + private Provider provider; + + /** The name of the algorithm. */ + private String algorithm; + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new secret key factory. + * + * @param skfSpi The underlying factory implementation. + * @param provider The provider. + * @param algorithm The algorithm name. + */ + protected SecretKeyFactory(SecretKeyFactorySpi skfSpi, Provider provider, + String algorithm) + { + this.skfSpi = skfSpi; + this.provider = provider; + this.algorithm = algorithm; + } + + /** + * Create a new secret key factory from the first appropriate instance. + * + * @param algorithm The algorithm name. + * @return The appropriate key factory, if found. + * @throws NoSuchAlgorithmException If no provider implements the specified + * algorithm. + * @throws IllegalArgumentException if <code>algorithm</code> is + * <code>null</code> or is an empty string. + */ + public static final SecretKeyFactory getInstance(String algorithm) + throws NoSuchAlgorithmException + { + Provider[] p = Security.getProviders(); + NoSuchAlgorithmException lastException = null; + for (int i = 0; i < p.length; i++) + try + { + return getInstance(algorithm, p[i]); + } + catch (NoSuchAlgorithmException x) + { + lastException = x; + } + if (lastException != null) + throw lastException; + throw new NoSuchAlgorithmException(algorithm); + } + + /** + * Create a new secret key factory from the named provider. + * + * @param algorithm The algorithm name. + * @param provider The provider name. + * @return The appropriate key factory, if found. + * @throws NoSuchAlgorithmException If the named provider does not implement + * the algorithm. + * @throws NoSuchProviderException If the named provider does not exist. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final SecretKeyFactory getInstance(String algorithm, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException + { + if (provider == null) + throw new IllegalArgumentException("provider MUST NOT be null"); + Provider p = Security.getProvider(provider); + if (p == null) + throw new NoSuchProviderException(provider); + return getInstance(algorithm, p); + } + + /** + * Create a new secret key factory from the specified provider. + * + * @param algorithm The algorithm name. + * @param provider The provider. + * @return The appropriate key factory, if found. + * @throws NoSuchAlgorithmException If the provider does not implement the + * algorithm. + * @throws IllegalArgumentException if either <code>algorithm</code> or + * <code>provider</code> is <code>null</code>, or if + * <code>algorithm</code> is an empty string. + */ + public static final SecretKeyFactory getInstance(String algorithm, + Provider provider) + throws NoSuchAlgorithmException + { + StringBuilder sb = new StringBuilder("SecretKeyFactory algorithm [") + .append(algorithm).append("] from provider[") + .append(provider).append("] could not be created"); + Throwable cause; + try + { + Object spi = Engine.getInstance(SERVICE, algorithm, provider); + return new SecretKeyFactory((SecretKeyFactorySpi) spi, provider, algorithm); + } + catch (InvocationTargetException x) + { + cause = x.getCause(); + if (cause instanceof NoSuchAlgorithmException) + throw (NoSuchAlgorithmException) cause; + if (cause == null) + cause = x; + } + catch (ClassCastException x) + { + cause = x; + } + NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString()); + x.initCause(cause); + throw x; + } + + /** + * Generate a secret key from a key specification, if possible. + * + * @param keySpec The key specification. + * @return The secret key. + * @throws java.security.InvalidKeySpecException If the key specification + * cannot be transformed into a secret key. + */ + public final SecretKey generateSecret(KeySpec keySpec) + throws InvalidKeySpecException + { + return skfSpi.engineGenerateSecret(keySpec); + } + + /** + * Get the algorithm name. + * + * @return The algorithm name. + */ + public final String getAlgorithm() + { + return algorithm; + } + + /** + * Get the key specification from a secret key. + * + * @param key The secret key. + * @param keySpec The target key specification class. + * @return The key specification. + * @throws java.security.spec.InvalidKeySpecException If the secret key cannot + * be transformed into the specified key specification. + */ + public final KeySpec getKeySpec(SecretKey key, Class keySpec) + throws InvalidKeySpecException + { + return skfSpi.engineGetKeySpec(key, keySpec); + } + + /** + * Get the provider of this implementation. + * + * @return The provider. + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Translate a secret key into another form. + * + * @param key The key to translate. + * @return The translated key. + * @throws java.security.InvalidKeyException If the argument cannot be + * translated. + */ + public final SecretKey translateKey(SecretKey key) + throws InvalidKeyException + { + return skfSpi.engineTranslateKey(key); + } +} diff --git a/libjava/classpath/javax/crypto/SecretKeyFactorySpi.java b/libjava/classpath/javax/crypto/SecretKeyFactorySpi.java new file mode 100644 index 000000000..6c9a3ca29 --- /dev/null +++ b/libjava/classpath/javax/crypto/SecretKeyFactorySpi.java @@ -0,0 +1,108 @@ +/* SecretKeyFactorySpi.java -- Secret key factory service provider interface. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.InvalidKeyException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + +/** + * The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@link + * SecretKeyFactory} class. + * + * <p>Providers wishing to implement a secret key factory must + * subclass this and provide an appropriate implementation for all the + * abstract methods below, and provide an appropriate entry in the + * master {@link java.security.Provider} class (the service name for + * secret key factories is <code>"SecretKeyFactory"</code>). + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see SecretKeyFactory + */ +public abstract class SecretKeyFactorySpi +{ + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new secret key factory SPI. + */ + public SecretKeyFactorySpi() + { + } + + // Abstract instance methods. + // ------------------------------------------------------------------------ + + /** + * Translate a {@link java.security.KeySpec} into a {@link SecretKey}. + * + * @param keySpec The key specification. + * @return The secret key. + * @throws java.security.spec.InvalidKeySpecException If the key specification + * cannot be translated into a secret key. + */ + protected abstract SecretKey engineGenerateSecret(KeySpec keySpec) + throws InvalidKeySpecException; + + /** + * Translate a {@link SecretKey} into a {@link java.security.KeySpec}. + * + * @param key The secret key. + * @param keySpec The desired key specification class. + * @return The key specification. + * @throws java.security.spec.InvalidKeySpecException If the secret key cannot + * be translated into the desired key specification. + */ + protected abstract KeySpec engineGetKeySpec(SecretKey key, Class keySpec) + throws InvalidKeySpecException; + + /** + * Translate a secret key into a different representation. + * + * @param key The secret key to translate. + * @return The translated key. + * @throws java.security.InvalidKeyException If the specified secret + * key cannot be translated. + */ + protected abstract SecretKey engineTranslateKey(SecretKey key) + throws InvalidKeyException; +} diff --git a/libjava/classpath/javax/crypto/ShortBufferException.java b/libjava/classpath/javax/crypto/ShortBufferException.java new file mode 100644 index 000000000..98d2101c3 --- /dev/null +++ b/libjava/classpath/javax/crypto/ShortBufferException.java @@ -0,0 +1,70 @@ +/* ShortBufferException.java -- Signals a short output buffer. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto; + +import java.security.GeneralSecurityException; + +/** + * This exception is thrown on an attempt to transform bytes into a + * buffer that is too short to contain the data. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class ShortBufferException extends GeneralSecurityException +{ + + // Constant. + // ------------------------------------------------------------------------ + + /** Serialization constant. */ + private static final long serialVersionUID = 8427718640832943747L; + + // Constructors. + // ------------------------------------------------------------------------ + + public ShortBufferException() + { + super(); + } + + public ShortBufferException(String message) + { + super(message); + } +} diff --git a/libjava/classpath/javax/crypto/interfaces/DHKey.java b/libjava/classpath/javax/crypto/interfaces/DHKey.java new file mode 100644 index 000000000..0c3ec97e0 --- /dev/null +++ b/libjava/classpath/javax/crypto/interfaces/DHKey.java @@ -0,0 +1,61 @@ +/* DHKey.java -- General interface for a Diffie-Hellman key. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.interfaces; + +import javax.crypto.spec.DHParameterSpec; + +/** + * This interface marks public/private keys in the Diffie-Hellman key + * exchange algorithm. Implementations of Diffie-Hellman keys should + * implement this interface, and applications can safely cast keys that + * are known to be Diffie-Hellman keys to this interface. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public interface DHKey +{ + /** + * Returns the Diffie-Hellman parameters for this key, which includes + * the generator and the prime. + * + * @return The Diffie-Hellman parameters. + */ + DHParameterSpec getParams(); +} diff --git a/libjava/classpath/javax/crypto/interfaces/DHPrivateKey.java b/libjava/classpath/javax/crypto/interfaces/DHPrivateKey.java new file mode 100644 index 000000000..12077bad2 --- /dev/null +++ b/libjava/classpath/javax/crypto/interfaces/DHPrivateKey.java @@ -0,0 +1,69 @@ +/* DHPrivateKey.java -- A Diffie-Hellman private key. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.interfaces; + +import java.math.BigInteger; +import java.security.PrivateKey; + +/** + * This interface marks a private key in the Diffie-Hellman key exchange + * algorithm. It should be treated with as much care as any {@link + * java.security.PrivateKey}. + * + * <p>Implementations of Diffie-Hellman private keys should implement + * this interface. Applications that know a particular key is a + * Diffie-Hellman private key can safely cast it to this interface. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see DHKey + * @see DHPublicKey + */ +public interface DHPrivateKey extends DHKey, PrivateKey +{ + /** Compatible with JDK1.4. */ + long serialVersionUID = 2211791113380396553L; + + /** + * Returns the private value <i>x</i>. + * + * @return The private value <i>x</i>. + */ + BigInteger getX(); +} diff --git a/libjava/classpath/javax/crypto/interfaces/DHPublicKey.java b/libjava/classpath/javax/crypto/interfaces/DHPublicKey.java new file mode 100644 index 000000000..d0519d4db --- /dev/null +++ b/libjava/classpath/javax/crypto/interfaces/DHPublicKey.java @@ -0,0 +1,68 @@ +/* DHPublicKey.java -- A Diffie-Hellman public key. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.interfaces; + +import java.math.BigInteger; +import java.security.PublicKey; + +/** + * This interface marks a public key in the Diffie-Hellman key-exchange + * algorithm. + * + * <p>Implementations of Diffie-Hellman public keys should implement + * this interface. Applications that know that a particular key is a + * Diffie-Hellman public key it can be safely cast to this interface. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see DHKey + * @see DHPrivateKey + */ +public interface DHPublicKey extends DHKey, PublicKey +{ + /** Compatible with JDK1.4. */ + long serialVersionUID = -6628103563352519193L; + + /** + * Get the public value <i>y</i>. + * + * @return The public value <i>y</i>. + */ + BigInteger getY(); +} diff --git a/libjava/classpath/javax/crypto/interfaces/PBEKey.java b/libjava/classpath/javax/crypto/interfaces/PBEKey.java new file mode 100644 index 000000000..df7f2e2b2 --- /dev/null +++ b/libjava/classpath/javax/crypto/interfaces/PBEKey.java @@ -0,0 +1,90 @@ +/* PBEKey.java -- A key derived from a password. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.interfaces; + +import javax.crypto.SecretKey; + +/** + * Interface to a password-derived key for password-based encryption + * (PBE). Applications working with a {@link javax.crypto.SecretKey} + * that is known to be a password-based key can safely cast such keys to + * this interface. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public interface PBEKey extends SecretKey +{ + /** Compatible with JDK1.4. */ + long serialVersionUID = -1430015993304333921L; + + /** + * Retruns the iteration count, or 0 if not specified. + * + * @return The iteration count. + */ + int getIterationCount(); + + /** + * Returns a copy of the password as a character array. It is the + * caller's responsibility to zero-out the password when it is no + * longer in use. + * + * <p>Although it is not specified in the documentation, + * implementations should not copy or clone the password array, but + * rather return the reference to the array itself, so the caller has + * the ability to erase the password. + * + * @return The password. + */ + char[] getPassword(); + + /** + * Returns a copy of the salt. It is the caller's responsibility to + * zero-out the salt when it is no longer in use. + * + * <p>Although it is not specified in the documentation, + * implementations should not copy or clone the salt array, but + * rather return the reference to the array itself, so the caller has + * the ability to erase the salt. + * + * @return The salt. + */ + byte[] getSalt(); +} diff --git a/libjava/classpath/javax/crypto/interfaces/package.html b/libjava/classpath/javax/crypto/interfaces/package.html new file mode 100644 index 000000000..9461e39fa --- /dev/null +++ b/libjava/classpath/javax/crypto/interfaces/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.crypto.interfaces package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.crypto.interfaces</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/javax/crypto/package.html b/libjava/classpath/javax/crypto/package.html new file mode 100644 index 000000000..d055fb578 --- /dev/null +++ b/libjava/classpath/javax/crypto/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.crypto package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.crypto</title></head> + +<body> +<p></p> + +</body> +</html> diff --git a/libjava/classpath/javax/crypto/spec/DESKeySpec.java b/libjava/classpath/javax/crypto/spec/DESKeySpec.java new file mode 100644 index 000000000..9075a77d2 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/DESKeySpec.java @@ -0,0 +1,220 @@ +/* DESKeySpec -- Keys for DES. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.InvalidKeyException; +import java.security.spec.KeySpec; + +/** + * This class is a transparent wrapper for DES keys, which are arrays + * of 8 bytes. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class DESKeySpec implements KeySpec +{ + + // Constants. + // ------------------------------------------------------------------------ + + /** + * The length of a DES key, in bytes. + */ + public static final int DES_KEY_LEN = 8; + + /** + * The key bytes. + */ + private byte[] key; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new DES key spec, copying the first 8 bytes from the + * byte array. + * + * @param key The key bytes. + * @throws java.security.InvalidKeyException If there are less than 8 + * bytes in the array. + */ + public DESKeySpec(byte[] key) throws InvalidKeyException + { + this(key, 0); + } + + /** + * Create a new DES key spec, starting at <code>offset</code> in + * the byte array. The first 8 bytes starting at <code>offset</code> + * are copied. + * + * @param key The key bytes. + * @param offset The offset into the byte array at which to begin. + * @throws java.security.InvalidKeyException If there are less than 8 + * bytes starting at <code>offset</code>. + */ + public DESKeySpec(byte[] key, int offset) throws InvalidKeyException + { + if (key.length - offset < DES_KEY_LEN) + { + throw new InvalidKeyException("DES keys must be 8 bytes long"); + } + this.key = new byte[DES_KEY_LEN]; + System.arraycopy(key, offset, this.key, 0, DES_KEY_LEN); + } + + // Class methods. + // ------------------------------------------------------------------------ + + /** + * Returns whether or not the given key is <i>parity adjusted</i>; + * i.e. every byte in the key has an odd number of "1" bits. + * + * @param key The key bytes, considered between <code>[offset, + * offset+7]</code> + * @param offset The offset into the byte array at which to begin. + * @return True if all bytes have an odd number of "1" bits. + * @throws java.security.InvalidKeyException If there are not enough + * bytes in the array. + */ + public static boolean isParityAdjusted(byte[] key, int offset) + throws InvalidKeyException + { + if (key.length - offset < DES_KEY_LEN) + { + throw new InvalidKeyException("DES keys must be 8 bytes long"); + } + boolean parity = false; + boolean oddbits = false; + for (int i = 0; i < DES_KEY_LEN; i++) + { + oddbits = false; + for (int j = 0; j < 8; j++) + { + oddbits ^= (key[i+offset] & 1 << j) != 0; + } + parity &= oddbits; + } + return parity; + } + + /** + * One-half of the weak and semiweak DES keys (the other half are the + * complements of these). + */ + private static final byte[][] WEAK_KEYS = new byte[][] { + { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0000 0000 0000 0000 + { -1, -1, -1, -1, 0, 0, 0, 0 }, // ffff ffff 0000 0000 + { 1, 1, 1, 1, 1, 1, 1, 1 }, // 0101 0101 0101 0101 + { 31, 31, 31, 31, 14, 14, 14, 14 }, // 1f1f 1f1f 0e0e 0e0e + { 1, -2, 1, -2, 1, -2, 1, -2 }, // 01fe 01fe 01fe 01fe + { 31, -32, 31, -32, -32, 31, -32, 31 }, // 1fe0 1fe0 0e1f 0e1f + { 1, -32, 1, -32, 1, -15, 1, -15 }, // 01e0 01e0 01f1 01f1 + { 31, -2, 31, -2, 14, -2, 14, -2 }, // 1ffe 1ffe 0efe 0efe + { 1, 31, 1, 31, 1, 14, 1, 14 }, // 011f 011f 010e 010e + { -32, -2, -32, -2, -15, -2, -15, -2 }, // e0fe e0fe f1fe f1fe + }; + + /** + * Tests if the bytes between <code>[offset, offset+7]</code> + * constitute a weak or semi-weak DES key. + * + * @param key The key bytes to check. + * @param offset The offset in the byte array to start. + * @return true If the key bytes are a weak key. + */ + public static boolean isWeak(byte[] key, int offset) + throws InvalidKeyException + { + if (key.length - offset < DES_KEY_LEN) + { + throw new InvalidKeyException("DES keys must be 8 bytes long"); + } + for (int i = 0; i < WEAK_KEYS.length; i++) + { + if (equalsOrComplementEquals(key, offset, WEAK_KEYS[i])) + { + return true; + } + } + return false; + } + + /** + * This method returns true if the first 8 bytes starting at + * <code>off</code> in <code>a</code> equal the first 8 bytes in + * <code>b</code>, or equal the <i>complement</i> of the first 8 bytes + * in <code>b</code>. + * + * @param a The first byte array. + * @param off The index into the first byte array. + * @param b The second byte array. + * @return <code>a == b || a == ~b</code> + */ + private static boolean equalsOrComplementEquals(byte[] a, int off, byte[] b) + { + boolean result = true; + for (int i = 0; i < DES_KEY_LEN; i++) + { + result &= a[off+i] == b[i]; + } + if (result) return true; + result = true; + for (int i = 0; i < DES_KEY_LEN; i++) + { + result &= a[off+i] == (~b[i]); + } + return result; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Return the key as a byte array. This method does not copy the byte + * array. + * + * @return The key bytes. + */ + public byte[] getKey() + { + return key; + } +} diff --git a/libjava/classpath/javax/crypto/spec/DESedeKeySpec.java b/libjava/classpath/javax/crypto/spec/DESedeKeySpec.java new file mode 100644 index 000000000..1f6a25026 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/DESedeKeySpec.java @@ -0,0 +1,151 @@ +/* DESedeKeySpec.java -- Keys for triple-DES. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.InvalidKeyException; +import java.security.spec.KeySpec; + +/** + * This class is a transparent wrapper for DES-EDE (Triple-DES) keys, + * which are arrays of 24 bytes. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class DESedeKeySpec implements KeySpec +{ + + // Constants. + // ------------------------------------------------------------------------ + + /** + * The length of a triple-DES key, in bytes. + */ + public static final int DES_EDE_KEY_LEN = 24; + + /** + * The key bytes. + */ + private byte[] key; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new DES-EDE key spec, copying the first 24 bytes from the + * byte array. + * + * @param key The key bytes. + * @throws java.security.InvalidKeyException If there are less than 24 + * bytes in the array. + */ + public DESedeKeySpec(byte[] key) throws InvalidKeyException + { + this(key, 0); + } + + /** + * Create a new DES-EDE key spec, starting at <code>offset</code> in + * the byte array. The first 24 bytes starting at <code>offset</code> + * are copied. + * + * @param key The key bytes. + * @param offset The offset into the byte array at which to begin. + * @throws java.security.InvalidKeyException If there are less than 24 + * bytes starting at <code>offset</code>. + */ + public DESedeKeySpec(byte[] key, int offset) throws InvalidKeyException + { + if (key.length - offset < DES_EDE_KEY_LEN) + { + throw new InvalidKeyException("DES-EDE keys must be 24 bytes long"); + } + this.key = new byte[DES_EDE_KEY_LEN]; + System.arraycopy(key, offset, this.key, 0, DES_EDE_KEY_LEN); + } + + // Class methods. + // ------------------------------------------------------------------------ + + /** + * Returns whether or not the given key is <i>parity adjusted</i>; + * i.e. every byte in the key has an odd number of "1" bits. + * + * @param key The key bytes, considered between <code>[offset, + * offset+23]</code> + * @param offset The offset into the byte array at which to begin. + * @return True if all bytes have an odd number of "1" bits. + * @throws java.security.InvalidKeyException If there are not enough + * bytes in the array. + */ + public static boolean isParityAdjusted(byte[] key, int offset) + throws InvalidKeyException + { + if (key.length - offset < DES_EDE_KEY_LEN) + { + throw new InvalidKeyException("DES-EDE keys must be 24 bytes long"); + } + boolean parity = false; + boolean oddbits = false; + for (int i = 0; i < DES_EDE_KEY_LEN; i++) + { + oddbits = false; + for (int j = 0; j < 8; j++) + { + oddbits ^= (key[i+offset] & 1 << j) != 0; + } + parity &= oddbits; + } + return parity; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Return the key as a byte array. This method does not copy the byte + * array. + * + * @return The key bytes. + */ + public byte[] getKey() + { + return key; + } +} diff --git a/libjava/classpath/javax/crypto/spec/DHGenParameterSpec.java b/libjava/classpath/javax/crypto/spec/DHGenParameterSpec.java new file mode 100644 index 000000000..0fc8ed58e --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/DHGenParameterSpec.java @@ -0,0 +1,100 @@ +/* DHGenParameterSpec.java -- Diffie-Hellman parameter generator spec. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * This class represents the parameters needed for generating + * Diffie-Hellman parameters. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see DHParameterSpec + */ +public class DHGenParameterSpec implements AlgorithmParameterSpec +{ + + // Variables. + // ------------------------------------------------------------------------ + + /** The length of the prime, in bits. */ + private int primeSize; + + /** The length of the exponent, in bits. */ + private int exponentSize; + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Create a new Diffie-Hellman parameter generator spec. + * + * @param primeSize The size of the prime, in bits. + * @param exponentSize The size of the exponent, in bits. + */ + public DHGenParameterSpec(int primeSize, int exponentSize) + { + this.primeSize = primeSize; + this.exponentSize = exponentSize; + } + + // Intance methods. + // ------------------------------------------------------------------------ + + /** + * Get the size of the exponent, in bits. + * + * @return The exponent size. + */ + public int getExponentSize() + { + return exponentSize; + } + + /** + * Get the size of the prime, in bits. + * + * @return The prime size. + */ + public int getPrimeSize() + { + return primeSize; + } +} diff --git a/libjava/classpath/javax/crypto/spec/DHParameterSpec.java b/libjava/classpath/javax/crypto/spec/DHParameterSpec.java new file mode 100644 index 000000000..4db82870f --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/DHParameterSpec.java @@ -0,0 +1,135 @@ +/* DHParameterSpec.java -- Parameters for Diffie-Hellman keys. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.math.BigInteger; +import java.security.spec.AlgorithmParameterSpec; + +/** + * The base set of parameters necessary to perform Diffie-Hellman key + * exchange. Each party in the key exchange shares these parameters. + * + * <p>Each set of parameters consists of a <i>base generator</i> + * <code>g</code>, a <i>prime modulus</i> <code>p</code>, and an + * optional length, in bits, of the private exponent. + * + * <p>See <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/">PKCS + * #3 - Diffie-Hellman Key Agreement Standard</a> for more information. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see javax.crypto.KeyAgreement + */ +public class DHParameterSpec implements AlgorithmParameterSpec +{ + + // Variables. + // ------------------------------------------------------------------------ + + /** The base generator g. */ + private BigInteger g; + + /** The prime modulus p. */ + private BigInteger p; + + /** The length, in bits, of the private exponent. */ + private int l; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new set of Diffie-Hellman parameters. + * + * @param p The prime modulus. + * @param g The base generator. + */ + public DHParameterSpec(BigInteger p, BigInteger g) + { + this(p, g, 0); + } + + /** + * Create a new set of Diffie-Hellman parameters. + * + * @param p The prime modulus. + * @param g The base generator. + * @param l The size of the private exponent, in bits. + */ + public DHParameterSpec(BigInteger p, BigInteger g, int l) + { + this.p = p; + this.g = g; + this.l = l; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Get the base generator, <i>g</i>. + * + * @return The base generator <i>g</i>. + */ + public BigInteger getG() + { + return g; + } + + /** + * Get the length of the private exponent, in bits. + * + * @return The length of the private exponent, in bits, or 0 if this + * has not been explicitly set. + */ + public int getL() + { + return l; + } + + /** + * Get the prime modulus, <i>p</i>. + * + * @return The prime modulus, <i>p</i>. + */ + public BigInteger getP() + { + return p; + } +} diff --git a/libjava/classpath/javax/crypto/spec/DHPrivateKeySpec.java b/libjava/classpath/javax/crypto/spec/DHPrivateKeySpec.java new file mode 100644 index 000000000..348a19264 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/DHPrivateKeySpec.java @@ -0,0 +1,115 @@ +/* DHPrivateKeySpec.java -- Wrapper for Diffie-Hellman private keys. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.math.BigInteger; +import java.security.spec.KeySpec; + +/** + * A wrapper for Diffie-Hellman private key data. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see DHPublicKeySpec + */ +public class DHPrivateKeySpec implements KeySpec +{ + + // Variables. + // ------------------------------------------------------------------------ + + /** The base generator. */ + private BigInteger g; + + /** The prime modulus. */ + private BigInteger p; + + /** The private exponent. */ + private BigInteger x; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new Diffie-Hellman private key spec. + * + * @param x The private exponent. + * @param p The prime modulus. + * @param g The base generator. + */ + public DHPrivateKeySpec(BigInteger x, BigInteger p, BigInteger g) + { + this.x = x; + this.p = p; + this.g = g; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Get the base generator. + * + * @return The base generator. + */ + public BigInteger getG() + { + return g; + } + + /** + * Get the prime modulus. + * + * @return The prime modulus. + */ + public BigInteger getP() + { + return p; + } + + /** + * Get the private exponent. + * + * @return The private exponent. + */ + public BigInteger getX() + { + return x; + } +} diff --git a/libjava/classpath/javax/crypto/spec/DHPublicKeySpec.java b/libjava/classpath/javax/crypto/spec/DHPublicKeySpec.java new file mode 100644 index 000000000..e81872785 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/DHPublicKeySpec.java @@ -0,0 +1,115 @@ +/* DHPublicKeySpec.java -- Wrapper for Diffie-Hellman public keys. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.math.BigInteger; +import java.security.spec.KeySpec; + +/** + * A wrapper for Diffie-Hellman public key data. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see DHPrivateKeySpec + */ +public class DHPublicKeySpec implements KeySpec +{ + + // Variables. + // ------------------------------------------------------------------------ + + /** The base generator. */ + private BigInteger g; + + /** The prime modulus. */ + private BigInteger p; + + /** The public value. */ + private BigInteger y; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new Diffie-Hellman public key spec. + * + * @param y The public value. + * @param p The prime modulus. + * @param g The base generator. + */ + public DHPublicKeySpec(BigInteger y, BigInteger p, BigInteger g) + { + this.y = y; + this.p = p; + this.g = g; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Get the base generator. + * + * @return The base generator. + */ + public BigInteger getG() + { + return g; + } + + /** + * Get the prime modulus. + * + * @return The prime modulus. + */ + public BigInteger getP() + { + return p; + } + + /** + * Get the public value. + * + * @return The public value. + */ + public BigInteger getY() + { + return y; + } +} diff --git a/libjava/classpath/javax/crypto/spec/IvParameterSpec.java b/libjava/classpath/javax/crypto/spec/IvParameterSpec.java new file mode 100644 index 000000000..3af38f58e --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/IvParameterSpec.java @@ -0,0 +1,96 @@ +/* IvParameterSpec.java -- A simple wrapper for initialization vectors. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * A wrapper for an initialization vector. An initialization vector is + * necessary for any cipher in any <i>feedback mode</i>, e.g. CBC. + * + * @author Casey Marshall (csm@gnu.org) + */ +public class IvParameterSpec implements AlgorithmParameterSpec +{ + + // Fields. + // ------------------------------------------------------------------------ + + /** The IV. */ + private byte[] iv; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new initialization vector spec from an entire byte array. + * + * @param iv The IV bytes. + */ + public IvParameterSpec(byte[] iv) + { + this(iv, 0, iv.length); + } + + /** + * Create a new initialization vector spec from part of a byte array. + * + * @param iv The IV bytes. + * @param off The offset into the IV bytes. + * @param len The number of IV bytes. + */ + public IvParameterSpec(byte[] iv, int off, int len) + { + this.iv = new byte[len]; + System.arraycopy(iv, off, this.iv, 0, len); + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Returns the IV. This method does not copy the byte array. + * + * @return The IV. + */ + public byte[] getIV() + { + return iv; + } +} diff --git a/libjava/classpath/javax/crypto/spec/PBEKeySpec.java b/libjava/classpath/javax/crypto/spec/PBEKeySpec.java new file mode 100644 index 000000000..f0ffa379a --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/PBEKeySpec.java @@ -0,0 +1,281 @@ +/* PBEKeySpec.java -- Wrapper for password-based keys. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.KeySpec; + +/** + * A wrapper for a password-based key, used for password-based + * encryption (PBE). + * + * <p>Examples of password-based encryption algorithms include: + * + * <ul> + * <li><a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/">PKCS #5 + * - Password-Based Cryptography Standard</a></li> + * <li><a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/">PKCS + * #12 - Personal Information Exchange Syntax Standard</a></li> + * </ul> + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + * @see javax.crypto.SecretKeyFactory + * @see PBEParameterSpec + */ +public class PBEKeySpec implements KeySpec +{ + + // Fields. + // ------------------------------------------------------------------------ + + /** The iteration count. */ + private int iterationCount; + + /** The generated key length. */ + private int keyLength; + + /** The password. */ + private char[] password; + + /** The salt. */ + private byte[] salt; + + /** The password state */ + private boolean passwordValid = true; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new PBE key spec with just a password. + * <p> + * A copy of the password argument is stored instead of the argument itself. + * + * @param password The password char array. + */ + public PBEKeySpec(char[] password) + { + setPassword(password); + + // load the default values for unspecified variables. + salt = null; + iterationCount = 0; + keyLength = 0; + } + + /** + * Create a PBE key spec with a password, salt, and iteration count. + * <p> + * A copy of the password and salt arguments are stored instead of the + * arguments themselves. + * + * @param password The password char array. + * @param salt The salt bytes. + * @param iterationCount The iteration count. + * @throws NullPointerException If salt is null + * @throws IllegalArgumentException If salt is an empty array, or + * iterationCount is negative + */ + public PBEKeySpec(char[] password, byte[] salt, int iterationCount) + { + setPassword(password); + setSalt(salt); + setIterationCount(iterationCount); + + // load default values into unspecified variables. + keyLength = 0; + } + + /** + * Create a PBE key spec with a password, salt, iteration count, and key + * length. + * <p> + * A copy of the password and salt arguments are stored instead of the + * arguments themselves. + * + * @param password The password char array. + * @param salt The salt bytes. + * @param iterationCount The iteration count. + * @param keyLength The generated key length. + * @throws NullPointerException If salt is null + * @throws IllegalArgumentException If salt is an empty array, if + * iterationCount or keyLength is negative + */ + public PBEKeySpec(char[] password, byte[] salt, int iterationCount, + int keyLength) + { + setPassword(password); + setSalt(salt); + setIterationCount(iterationCount); + setKeyLength(keyLength); + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Clear the password array by filling it with null characters. + * <p> + * This clears the stored copy of the password, not the original char array + * used to create the password. + */ + public final void clearPassword() + { + if (password == null) + return; + for (int i = 0; i < password.length; i++) + password[i] = '\u0000'; + + // since the password is cleared, it is no longer valid + passwordValid = false; + } + + /** + * Get the iteration count, or 0 if it has not been specified. + * + * @return The iteration count, or 0 if it has not been specified. + */ + public final int getIterationCount() + { + return iterationCount; + } + + /** + * Get the generated key length, or 0 if it has not been specified. + * + * @return The key length, or 0 if it has not been specified. + */ + public final int getKeyLength() + { + return keyLength; + } + + /** + * Get the password character array copy. + * <p> + * This returns a copy of the password, not the password itself. + * + * @return a clone of the password. + * @throws IllegalStateException If {@link #clearPassword()} has already been + * called. + */ + public final char[] getPassword() + { + if (! passwordValid) + throw new IllegalStateException("clearPassword() has been called, the " + + "password is no longer valid"); + return (char[]) password.clone(); + } + + /** + * Get the salt bytes array copy. + * <p> + * This returns a copy of the salt, not the salt itself. + * + * @return The salt. + */ + public final byte[] getSalt() + { + if (salt != null) + return (byte[]) salt.clone(); + return null; + } + + /** + * Set the password char array. + * <p> + * A copy of the password argument is stored instead of the argument itself. + * + * @param password The password to be set + */ + private void setPassword(char[] password) + { + if (password != null) + this.password = (char[]) password.clone(); + else + this.password = new char[0]; + + passwordValid = true; + } + + /** + * Set the salt byte array. + * <p> + * A copy of the salt arguments is stored instead of the argument itself. + * + * @param salt The salt to be set. + * @throws NullPointerException If the salt is null. + * @throws IllegalArgumentException If the salt is an empty array. + */ + private void setSalt(byte[] salt) + { + if (salt.length == 0) + throw new IllegalArgumentException("salt MUST NOT be an empty byte array"); + + this.salt = (byte[]) salt.clone(); + } + + /** + * Set the iterationCount. + * + * @param iterationCount The iteration count to be set. + * @throws IllegalArgumentException If the iterationCount is negative. + */ + private void setIterationCount(int iterationCount) + { + if (iterationCount < 0) + throw new IllegalArgumentException("iterationCount MUST be positive"); + + this.iterationCount = iterationCount; + } + + /** + * Set the keyLength. + * + * @param keyLength The keyLength to be set. + * @throws IllegalArgumentException if the keyLength is negative. + */ + private void setKeyLength(int keyLength) + { + if (keyLength < 0) + throw new IllegalArgumentException("keyLength MUST be positive"); + + this.keyLength = keyLength; + } +} diff --git a/libjava/classpath/javax/crypto/spec/PBEParameterSpec.java b/libjava/classpath/javax/crypto/spec/PBEParameterSpec.java new file mode 100644 index 000000000..322d9556c --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/PBEParameterSpec.java @@ -0,0 +1,100 @@ +/* PBEParameterSpec.java -- A wrapper for PBE parameters. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * A wrapper for the parameters used in <a + * href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/">PKCS #5 - + * Password-Based Cryptography Standard</a>. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class PBEParameterSpec implements AlgorithmParameterSpec +{ + + // Fields. + // ------------------------------------------------------------------------ + + /** The iteration count. */ + private int iterationCount; + + /** The salt. */ + private byte[] salt; + + // Constructor. + // ------------------------------------------------------------------------ + + /** + * Creates a new password-based encryption parameter specification. + * + * @param salt The salt. + * @param iterationCount The iteration count. + */ + public PBEParameterSpec(byte[] salt, int iterationCount) + { + this.salt = salt; + this.iterationCount = iterationCount; + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Get the iteration count. + * + * @return The iteration count. + */ + public int getIterationCount() + { + return iterationCount; + } + + /** + * Get the salt. + * + * @return The salt. + */ + public byte[] getSalt() + { + return salt; + } +} diff --git a/libjava/classpath/javax/crypto/spec/RC2ParameterSpec.java b/libjava/classpath/javax/crypto/spec/RC2ParameterSpec.java new file mode 100644 index 000000000..33155b2b3 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/RC2ParameterSpec.java @@ -0,0 +1,166 @@ +/* RC2ParameterSpec.java -- Wrapper for RC2 parameters. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * A wrapper for parameters for the <a + * href="http://www.rsasecurity.com/rsalabs/faq/3-6-2.html">RC2</a> + * block cipher ("RC" means either "Rivest Cipher" or "Ron's Code", + * depending upon who you ask and when). + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class RC2ParameterSpec implements AlgorithmParameterSpec +{ + + // Constants and fields. + // ------------------------------------------------------------------------ + + /** The length of an RC2 IV, in bytes. */ + private static final int RC2_IV_LENGTH = 8; + + /** The effective key length, in bits. */ + private int effectiveKeyBits; + + /** The initialization vector. */ + private byte[] iv; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create RC2 parameters without an IV. + * + * @param effectiveKeyBits The number of effective key bits. + */ + public RC2ParameterSpec(int effectiveKeyBits) + { + this.effectiveKeyBits = effectiveKeyBits; + } + + /** + * Create RC2 parameters with an IV. + * + * @param effectiveKeyBits The number of effective key bits. + * @param iv The IV; the first eight bytes of this array + * are used. + */ + public RC2ParameterSpec(int effectiveKeyBits, byte[] iv) + { + this(effectiveKeyBits, iv, 0); + } + + /** + * Create RC2 parameters with an IV. + * + * @param effectiveKeyBits The number of effective key bits. + * @param iv The IV; the first eight bytes of this array + * after <code>offset</code> are used. + * @param offset From whence to start in the array. + */ + public RC2ParameterSpec(int effectiveKeyBits, byte[] iv, int offset) + { + if (iv.length - offset < RC2_IV_LENGTH) + { + throw new IllegalArgumentException("IV too short"); + } + this.effectiveKeyBits = effectiveKeyBits; + this.iv = new byte[RC2_IV_LENGTH]; + System.arraycopy(iv, offset, this.iv, 0, RC2_IV_LENGTH); + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Get the number of effective key bits. + * + * @return The numer of effective key bits. + */ + public int getEffectiveKeyBits() + { + return effectiveKeyBits; + } + + /** + * Return the initialization vector, or <code>null</code> if none was + * specified. + * + * @return The IV, or null. + */ + public byte[] getIV() + { + return iv; + } + + public boolean equals(Object o) + { + if (this == o) return true; + byte[] oiv = ((RC2ParameterSpec) o).getIV(); + if (iv != oiv) + { + if (iv == null || oiv == null) return false; + if (iv.length != oiv.length) return false; + for (int i = 0; i < iv.length; i++) + { + if (iv[i] != oiv[i]) + { + return false; + } + } + } + return effectiveKeyBits == ((RC2ParameterSpec) o).getEffectiveKeyBits(); + } + + public int hashCode() + { + int code = effectiveKeyBits; + if (iv != null) + { + for (int i = 0; i < RC2_IV_LENGTH; i++) + { + code += iv[i]; + } + } + return code; + } +} diff --git a/libjava/classpath/javax/crypto/spec/RC5ParameterSpec.java b/libjava/classpath/javax/crypto/spec/RC5ParameterSpec.java new file mode 100644 index 000000000..8570c86b3 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/RC5ParameterSpec.java @@ -0,0 +1,202 @@ +/* RC5ParameterSpec.java -- parameters for RC5. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.AlgorithmParameterSpec; + +/** + * A wrapper for parameters to the <a + * href="http://www.rsasecurity.com/rsalabs/faq/3-6-4.html">RC5</a> + * block cipher. + * + * @author Casey Marshall (csm@gnu.org) + * @since 1.4 + */ +public class RC5ParameterSpec implements AlgorithmParameterSpec +{ + + // Fields. + // ------------------------------------------------------------------------ + + /** The IV. */ + private byte[] iv; + + /** The number of rounds. */ + private int rounds; + + /** The version number. */ + private int version; + + /** The word size, in bits. */ + private int wordSize; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create RC5 parameters without an IV. + * + * @param version The version number. + * @param rounds The number of rounds. + * @param wordSize The size of a word, in bits. + */ + public RC5ParameterSpec(int version, int rounds, int wordSize) + { + this.version = version; + this.rounds = rounds; + this.wordSize = wordSize; + } + + /** + * Create RC5 parameters with an IV. The bytes in <code>iv</code> in + * the range <code>[0, 2*(wordSize/8)-1]</code> are used. + * + * @param version The version number. + * @param rounds The number of rounds. + * @param wordSize The size of a word, in bits. + * @param iv The IV data. + */ + public RC5ParameterSpec(int version, int rounds, int wordSize, byte[] iv) + { + this(version, rounds, wordSize, iv, 0); + } + + /** + * Create RC5 parameters with an IV. The bytes in <code>iv</code> in + * the range <code>[off, off+2*(wordSize/8)-1]</code> are used. + * + * @param version The version number. + * @param rounds The number of rounds. + * @param wordSize The size of a word, in bits. + * @param iv The IV data. + * @param off From where in the array the IV starts. + */ + public + RC5ParameterSpec(int version, int rounds, int wordSize, byte[] iv, int off) + { + this(version, rounds, wordSize); + int ivLength = 2 * (wordSize / 8); + if (off < 0) + throw new IllegalArgumentException(); + if (iv.length - off < ivLength) + { + throw new IllegalArgumentException("IV too short"); + } + this.iv = new byte[ivLength]; + System.arraycopy(iv, off, this.iv, 0, ivLength); + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Return the initializaiton vector, or <code>null</code> if none was + * specified. + * + * @return The IV, or null. + */ + public byte[] getIV() + { + return iv; + } + + /** + * Get the number of rounds. + * + * @return The number of rounds. + */ + public int getRounds() + { + return rounds; + } + + /** + * Get the version number. + * + * @return The version number. + */ + public int getVersion() + { + return version; + } + + /** + * Get the word size, in bits. + * + * @return The word size, in bits. + */ + public int getWordSize() + { + return wordSize; + } + + public boolean equals(Object o) + { + if (this == o) return true; + byte[] oiv = ((RC5ParameterSpec) o).getIV(); + if (iv != oiv) + { + if (iv == null || oiv == null) return false; + if (iv.length != oiv.length) return false; + for (int i = 0; i < iv.length; i++) + { + if (iv[i] != oiv[i]) + { + return false; + } + } + } + return rounds == ((RC5ParameterSpec) o).getRounds() + && version == ((RC5ParameterSpec) o).getVersion() + && wordSize == ((RC5ParameterSpec) o).getWordSize(); + } + + public int hashCode() + { + int code = rounds + version + wordSize; + if (iv != null) + { + for (int i = 0; i < iv.length; i++) + { + code += iv[i]; + } + } + return code; + } +} diff --git a/libjava/classpath/javax/crypto/spec/SecretKeySpec.java b/libjava/classpath/javax/crypto/spec/SecretKeySpec.java new file mode 100644 index 000000000..86c4e05d4 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/SecretKeySpec.java @@ -0,0 +1,163 @@ +/* SecretKeySpec.java -- Wrapper for secret keys. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.crypto.spec; + +import java.security.spec.KeySpec; + +import javax.crypto.SecretKey; + +/** + * This is a simple wrapper around a raw byte array, for ciphers that do + * not require any key parameters other than the bytes themselves. + * + * <p>Since this class implements {@link javax.crypto.SecretKey}, which + * in turn extends {@link java.security.Key}, so instances of this class + * may be passed directly to the <code>init()</code> methods of {@link + * javax.crypto.Cipher}. + * + * @see javax.crypto.SecretKey + * @see javax.crypto.SecretKeyFactory + */ +public class SecretKeySpec implements KeySpec, SecretKey +{ + + // Constants and fields. + // ------------------------------------------------------------------------ + + /** Compatible with JDK1.4. */ + private static final long serialVersionUID = 6577238317307289933L; + + /** The key bytes. */ + private byte[] key; + + /** The algorithm's name. */ + private String algorithm; + + // Constructors. + // ------------------------------------------------------------------------ + + /** + * Create a new secret key spec from an entire byte array. + * + * @param key The key material. + * @param algorithm The name of the algorithm using this key. + */ + public SecretKeySpec(byte[] key, String algorithm) + { + this(key, 0, key.length, algorithm); + } + + /** + * Create a new secret key spec from part of a byte array. + * + * @param key The key material. + * @param off The offset at which key material begins. + * @param len The length of key material. + * @param algorithm The name of the algorithm using this key. + */ + public SecretKeySpec(byte[] key, int off, int len, String algorithm) + { + this.key = new byte[len]; + this.algorithm = algorithm; + System.arraycopy(key, off, this.key, 0, len); + } + + // Instance methods. + // ------------------------------------------------------------------------ + + /** + * Return the name of the algorithm associated with this secret key. + * + * @return The algorithm's name. + */ + public String getAlgorithm() + { + return algorithm; + } + + /** + * Return the key as a byte array. + * + * @return The key material. + */ + public byte[] getEncoded() + { + return key; + } + + /** + * This key's format, which is always "RAW". + * + * @return "RAW" + */ + public String getFormat() + { + return "RAW"; + } + + public boolean equals(Object o) + { + if (o instanceof SecretKeySpec) + { + byte[] okey = ((SecretKeySpec) o).getEncoded(); + if (key.length != okey.length) + return false; + for (int i = 0; i < key.length; i++) + { + if (key[i] != okey[i]) + return false; + } + return algorithm.equals(((SecretKeySpec) o).getAlgorithm()); + } + else + { + return false; + } + } + + public int hashCode() + { + int code = 0; + for (int i = 0; i < key.length; i++) + { + code ^= (key[i] & 0xff) << (i << 3 & 31); + } + return code ^ algorithm.hashCode(); + } +} diff --git a/libjava/classpath/javax/crypto/spec/package.html b/libjava/classpath/javax/crypto/spec/package.html new file mode 100644 index 000000000..8580c2f42 --- /dev/null +++ b/libjava/classpath/javax/crypto/spec/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.crypto.spec package. + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.crypto.spec</title></head> + +<body> +<p></p> + +</body> +</html> |