clean-crypto-1/0000775000175000017500000000000011370332423013474 5ustar moellermoellerclean-crypto-1/src/0000775000175000017500000000000011370332422014262 5ustar moellermoellerclean-crypto-1/src/main/0000775000175000017500000000000011370332422015206 5ustar moellermoellerclean-crypto-1/src/main/java/0000775000175000017500000000000011370332422016127 5ustar moellermoellerclean-crypto-1/src/main/java/javax/0000775000175000017500000000000011370332422017240 5ustar moellermoellerclean-crypto-1/src/main/java/javax/crypto/0000775000175000017500000000000011370332423020561 5ustar moellermoellerclean-crypto-1/src/main/java/javax/crypto/BadPaddingException.java0000664000175000017500000000377411370332423025273 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.GeneralSecurityException; /** * This exception is thrown when a particular padding mechanism is * expected for the input data but the data is not padded properly. * * @author Gigi Ankney * @since 1.4 */ public class BadPaddingException extends GeneralSecurityException { private static final long serialVersionUID = -5315033893984728443L; /** * Constructs a BadPaddingException with no detail * message. A detail message is a String that describes this * particular exception. */ public BadPaddingException() { super(); } /** * Constructs a BadPaddingException with the specified * detail message. * * @param msg the detail message. */ public BadPaddingException(String msg) { super(msg); } } clean-crypto-1/src/main/java/javax/crypto/Cipher.java0000664000175000017500000027045411370332423022652 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.*; import java.util.regex.*; import static java.util.Locale.ENGLISH; import java.security.*; import java.security.Provider.Service; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import javax.crypto.spec.*; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; import sun.security.util.Debug; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * This class provides the functionality of a cryptographic cipher for * encryption and decryption. It forms the core of the Java Cryptographic * Extension (JCE) framework. * *

In order to create a Cipher object, the application calls the * Cipher's getInstance method, and passes the name of the * requested transformation to it. Optionally, the name of a provider * may be specified. * *

A transformation is a string that describes the operation (or * set of operations) to be performed on the given input, to produce some * output. A transformation always includes the name of a cryptographic * algorithm (e.g., DES), and may be followed by a feedback mode and * padding scheme. * *

A transformation is of the form:

* *

* *

(in the latter case, * provider-specific default values for the mode and padding scheme are used). * For example, the following is a valid transformation:

* *

 *     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
 * 
* * Using modes such as CFB and OFB, block * ciphers can encrypt data in units smaller than the cipher's actual * block size. When requesting such a mode, you may optionally specify * the number of bits to be processed at a time by appending this number * to the mode name as shown in the "DES/CFB8/NoPadding" and * "DES/OFB32/PKCS5Padding" transformations. If no such * number is specified, a provider-specific default is used. (For * example, the SunJCE provider uses a default of 64 bits for DES.) * Thus, block ciphers can be turned into byte-oriented stream ciphers by * using an 8 bit mode such as CFB8 or OFB8. * * @author Jan Luehe * @see KeyGenerator * @see SecretKey * @since 1.4 */ public class Cipher { private static final Debug debug = Debug.getInstance("jca", "Cipher"); /** * Constant used to initialize cipher to encryption mode. */ public static final int ENCRYPT_MODE = 1; /** * Constant used to initialize cipher to decryption mode. */ public static final int DECRYPT_MODE = 2; /** * Constant used to initialize cipher to key-wrapping mode. */ public static final int WRAP_MODE = 3; /** * Constant used to initialize cipher to key-unwrapping mode. */ public static final int UNWRAP_MODE = 4; /** * Constant used to indicate the to-be-unwrapped key is a "public key". */ public static final int PUBLIC_KEY = 1; /** * Constant used to indicate the to-be-unwrapped key is a "private key". */ public static final int PRIVATE_KEY = 2; /** * Constant used to indicate the to-be-unwrapped key is a "secret key". */ public static final int SECRET_KEY = 3; // The provider private Provider provider; // The provider implementation (delegate) private CipherSpi spi; // The transformation private String transformation; // The exemption mechanism that needs to be enforced private ExemptionMechanism exmech; // Flag which indicates whether or not this cipher has been initialized private boolean initialized = false; // The operation mode - store the operation mode after the // cipher has been initialized. private int opmode = 0; // The OID for the KeyUsage extension in an X.509 v3 certificate private static final String KEY_USAGE_EXTENSION_OID = "2.5.29.15"; // next SPI to try in provider selection // null once provider is selected private CipherSpi firstSpi; // next service to try in provider selection // null once provider is selected private Service firstService; // remaining services to try in provider selection // null once provider is selected private Iterator serviceIterator; // list of transform Strings to lookup in the provider private List transforms; private final Object lock; /** * Creates a Cipher object. * * @param cipherSpi the delegate * @param provider the provider * @param transformation the transformation */ protected Cipher(CipherSpi cipherSpi, Provider provider, String transformation) { this.spi = cipherSpi; this.provider = provider; this.transformation = transformation; this.lock = null; } /** * Creates a Cipher object. Called internally and by NullCipher. * * @param cipherSpi the delegate * @param transformation the transformation */ Cipher(CipherSpi cipherSpi, String transformation) { this.spi = cipherSpi; this.transformation = transformation; this.lock = null; } private Cipher(CipherSpi firstSpi, Service firstService, Iterator serviceIterator, String transformation, List transforms) { this.firstSpi = firstSpi; this.firstService = firstService; this.serviceIterator = serviceIterator; this.transforms = transforms; this.transformation = transformation; this.lock = new Object(); } private static String[] tokenizeTransformation(String transformation) throws NoSuchAlgorithmException { if (transformation == null) { throw new NoSuchAlgorithmException("No transformation given"); } /* * array containing the components of a Cipher transformation: * * index 0: algorithm component (e.g., DES) * index 1: feedback component (e.g., CFB) * index 2: padding component (e.g., PKCS5Padding) */ String[] parts = new String[3]; int count = 0; StringTokenizer parser = new StringTokenizer(transformation, "/"); try { while (parser.hasMoreTokens() && count < 3) { parts[count++] = parser.nextToken().trim(); } if (count == 0 || count == 2 || parser.hasMoreTokens()) { throw new NoSuchAlgorithmException("Invalid transformation" + " format:" + transformation); } } catch (NoSuchElementException e) { throw new NoSuchAlgorithmException("Invalid transformation " + "format:" + transformation); } if ((parts[0] == null) || (parts[0].length() == 0)) { throw new NoSuchAlgorithmException("Invalid transformation:" + "algorithm not specified-" + transformation); } return parts; } // Provider attribute name for supported chaining mode private final static String ATTR_MODE = "SupportedModes"; // Provider attribute name for supported padding names private final static String ATTR_PAD = "SupportedPaddings"; // constants indicating whether the provider supports // a given mode or padding private final static int S_NO = 0; // does not support private final static int S_MAYBE = 1; // unable to determine private final static int S_YES = 2; // does support /** * Nested class to deal with modes and paddings. */ private static class Transform { // transform string to lookup in the provider final String transform; // the mode/padding suffix in upper case. for example, if the algorithm // to lookup is "DES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING" // if loopup is "DES", suffix is the empty string // needed because aliases prevent straight transform.equals() final String suffix; // value to pass to setMode() or null if no such call required final String mode; // value to pass to setPadding() or null if no such call required final String pad; Transform(String alg, String suffix, String mode, String pad) { this.transform = alg + suffix; this.suffix = suffix.toUpperCase(Locale.ENGLISH); this.mode = mode; this.pad = pad; } // set mode and padding for the given SPI void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException, NoSuchPaddingException { if (mode != null) { spi.engineSetMode(mode); } if (pad != null) { spi.engineSetPadding(pad); } } // check whether the given services supports the mode and // padding described by this Transform int supportsModePadding(Service s) { int smode = supportsMode(s); if (smode == S_NO) { return smode; } int spad = supportsPadding(s); // our constants are defined so that Math.min() is a tri-valued AND return Math.min(smode, spad); } // separate methods for mode and padding // called directly by Cipher only to throw the correct exception int supportsMode(Service s) { return supports(s, ATTR_MODE, mode); } int supportsPadding(Service s) { return supports(s, ATTR_PAD, pad); } private static int supports(Service s, String attrName, String value) { if (value == null) { return S_YES; } String regexp = s.getAttribute(attrName); if (regexp == null) { return S_MAYBE; } return matches(regexp, value) ? S_YES : S_NO; } // Map for previously compiled patterns // XXX use ConcurrentHashMap once available private final static Map patternCache = Collections.synchronizedMap(new HashMap()); private static boolean matches(String regexp, String str) { Pattern pattern = (Pattern)patternCache.get(regexp); if (pattern == null) { pattern = Pattern.compile(regexp); patternCache.put(regexp, pattern); } return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches(); } } private static List getTransforms(String transformation) throws NoSuchAlgorithmException { String[] parts = tokenizeTransformation(transformation); String alg = parts[0]; String mode = parts[1]; String pad = parts[2]; if ((mode != null) && (mode.length() == 0)) { mode = null; } if ((pad != null) && (pad.length() == 0)) { pad = null; } if ((mode == null) && (pad == null)) { // DES Transform tr = new Transform(alg, "", null, null); return Collections.singletonList(tr); } else { // if ((mode != null) && (pad != null)) { // DES/CBC/PKCS5Padding List list = new ArrayList(4); list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); list.add(new Transform(alg, "/" + mode, null, pad)); list.add(new Transform(alg, "//" + pad, mode, null)); list.add(new Transform(alg, "", mode, pad)); return list; } } // get the transform matching the specified service private static Transform getTransform(Service s, List transforms) { String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH); for (Iterator t = transforms.iterator(); t.hasNext(); ) { Transform tr = (Transform)t.next(); if (alg.endsWith(tr.suffix)) { return tr; } } return null; } /** * Returns a Cipher object that implements the specified * transformation. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new Cipher object encapsulating the * CipherSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param transformation the name of the transformation, e.g., * DES/CBC/PKCS5Padding. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard transformation names. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if transformation * is null, empty, in an invalid format, * or if no Provider supports a CipherSpi implementation for the * specified algorithm. * * @exception NoSuchPaddingException if transformation * contains a padding scheme that is not available. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation) throws NoSuchAlgorithmException, NoSuchPaddingException { List transforms = getTransforms(transformation); List cipherServices = new ArrayList(transforms.size()); for (Iterator t = transforms.iterator(); t.hasNext(); ) { Transform transform = (Transform)t.next(); cipherServices.add(new ServiceId("Cipher", transform.transform)); } List services = GetInstance.getServices(cipherServices); // make sure there is at least one service from a signed provider // and that it can use the specified mode and padding Iterator t = services.iterator(); Exception failure = null; while (t.hasNext()) { Service s = (Service)t.next(); Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } int canuse = tr.supportsModePadding(s); if (canuse == S_NO) { // does not support mode or padding we need, ignore continue; } if (canuse == S_YES) { return new Cipher(null, s, t, transformation, transforms); } else { // S_MAYBE, try out if it works try { CipherSpi spi = (CipherSpi)s.newInstance(null); tr.setModePadding(spi); return new Cipher(spi, s, t, transformation, transforms); } catch (Exception e) { failure = e; } } } throw new NoSuchAlgorithmException ("Cannot find any provider supporting " + transformation, failure); } /** * Returns a Cipher object that implements the specified * transformation. * *

A new Cipher object encapsulating the * CipherSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param transformation the name of the transformation, * e.g., DES/CBC/PKCS5Padding. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard transformation names. * * @param provider the name of the provider. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if transformation * is null, empty, in an invalid format, * or if a CipherSpi implementation for the specified algorithm * is not available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception NoSuchPaddingException if transformation * contains a padding scheme that is not available. * * @exception IllegalArgumentException if the provider * is null or empty. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { if ((provider == null) || (provider.length() == 0)) { throw new IllegalArgumentException("Missing provider"); } Provider p = Security.getProvider(provider); if (p == null) { throw new NoSuchProviderException("No such provider: " + provider); } return getInstance(transformation, p); } /** * Returns a Cipher object that implements the specified * transformation. * *

A new Cipher object encapsulating the * CipherSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param transformation the name of the transformation, * e.g., DES/CBC/PKCS5Padding. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard transformation names. * * @param provider the provider. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if transformation * is null, empty, in an invalid format, * or if a CipherSpi implementation for the specified algorithm * is not available from the specified Provider object. * * @exception NoSuchPaddingException if transformation * contains a padding scheme that is not available. * * @exception IllegalArgumentException if the provider * is null. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException { if (provider == null) { throw new IllegalArgumentException("Missing provider"); } Exception failure = null; List transforms = getTransforms(transformation); String paddingError = null; for (Iterator t = transforms.iterator(); t.hasNext();) { Transform tr = (Transform)t.next(); Service s = provider.getService("Cipher", tr.transform); if (s == null) { continue; } if (tr.supportsMode(s) == S_NO) { continue; } if (tr.supportsPadding(s) == S_NO) { paddingError = tr.pad; continue; } try { CipherSpi spi = (CipherSpi)s.newInstance(null); tr.setModePadding(spi); Cipher cipher = new Cipher(spi, transformation); cipher.provider = s.getProvider(); return cipher; } catch (Exception e) { failure = e; } } // throw NoSuchPaddingException if the problem is with padding if (failure instanceof NoSuchPaddingException) { throw (NoSuchPaddingException)failure; } if (paddingError != null) { throw new NoSuchPaddingException ("Padding not supported: " + paddingError); } throw new NoSuchAlgorithmException ("No such algorithm: " + transformation, failure); } // max number of debug warnings to print from chooseFirstProvider() private static int warnCount = 10; /** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because init() * is not the first method called. */ void chooseFirstProvider() { if (spi != null) { return; } synchronized (lock) { if (spi != null) { return; } if (debug != null) { int w = --warnCount; if (w >= 0) { debug.println("Cipher.init() not first method " + "called, disabling delayed provider selection"); if (w == 0) { debug.println("Further warnings of this type will " + "be suppressed"); } new Exception("Call trace").printStackTrace(); } } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; CipherSpi thisSpi; if (firstService != null) { s = firstService; thisSpi = firstSpi; firstService = null; firstSpi = null; } else { s = (Service)serviceIterator.next(); thisSpi = null; } Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } if (tr.supportsModePadding(s) == S_NO) { continue; } try { if (thisSpi == null) { Object obj = s.newInstance(null); if (obj instanceof CipherSpi == false) { continue; } thisSpi = (CipherSpi)obj; } tr.setModePadding(thisSpi); spi = thisSpi; provider = s.getProvider(); // not needed any more firstService = null; serviceIterator = null; transforms = null; return; } catch (Exception e) { lastException = e; } } ProviderException e = new ProviderException ("Could not construct CipherSpi instance"); if (lastException != null) { e.initCause(lastException); } throw e; } } private final static int I_KEY = 1; private final static int I_PARAMSPEC = 2; private final static int I_PARAMS = 3; private final static int I_CERT = 4; private void implInit(CipherSpi thisSpi, int type, int opmode, Key key, AlgorithmParameterSpec paramSpec, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { switch (type) { case I_KEY: thisSpi.engineInit(opmode, key, random); break; case I_PARAMSPEC: thisSpi.engineInit(opmode, key, paramSpec, random); break; case I_PARAMS: thisSpi.engineInit(opmode, key, params, random); break; case I_CERT: thisSpi.engineInit(opmode, key, random); break; default: throw new AssertionError("Internal Cipher error: " + type); } } private void chooseProvider(int initType, int opmode, Key key, AlgorithmParameterSpec paramSpec, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { synchronized (lock) { if (spi != null) { implInit(spi, initType, opmode, key, paramSpec, params, random); return; } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; CipherSpi thisSpi; if (firstService != null) { s = firstService; thisSpi = firstSpi; firstService = null; firstSpi = null; } else { s = (Service)serviceIterator.next(); thisSpi = null; } // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue; } Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } if (tr.supportsModePadding(s) == S_NO) { continue; } try { if (thisSpi == null) { thisSpi = (CipherSpi)s.newInstance(null); } tr.setModePadding(thisSpi); implInit(thisSpi, initType, opmode, key, paramSpec, params, random); provider = s.getProvider(); this.spi = thisSpi; firstService = null; serviceIterator = null; transforms = null; return; } catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() // SecurityException from crypto permission check if (lastException == null) { lastException = e; } } } // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException; } if (lastException instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)lastException; } if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException; } String kName = (key != null) ? key.getClass().getName() : "(null)"; throw new InvalidKeyException ("No installed provider supports this key: " + kName, lastException); } } /** * Returns the provider of this Cipher object. * * @return the provider of this Cipher object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } /** * Returns the algorithm name of this Cipher object. * *

This is the same name that was specified in one of the * getInstance calls that created this Cipher * object.. * * @return the algorithm name of this Cipher object. */ public final String getAlgorithm() { return this.transformation; } /** * Returns the block size (in bytes). * * @return the block size (in bytes), or 0 if the underlying algorithm is * not a block cipher */ public final int getBlockSize() { chooseFirstProvider(); return spi.engineGetBlockSize(); } /** * Returns the length in bytes that an output buffer would need to be in * order to hold the result of the next update or * doFinal operation, given the input length * inputLen (in bytes). * *

This call takes into account any unprocessed (buffered) data from a * previous update call, and padding. * *

The actual output length of the next update or * doFinal call may be smaller than the length returned by * this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not yet been initialized) */ public final int getOutputSize(int inputLen) { if (!initialized && !(this instanceof NullCipher)) { throw new IllegalStateException("Cipher not initialized"); } if (inputLen < 0) { throw new IllegalArgumentException("Input size must be equal " + "to or greater than zero"); } chooseFirstProvider(); return spi.engineGetOutputSize(inputLen); } /** * Returns the initialization vector (IV) in a new buffer. * *

This is useful in the case where a random IV was created, * or in the context of password-based encryption or * decryption, where the IV is derived from a user-supplied password. * * @return the initialization vector in a new buffer, or null if the * underlying algorithm does not use an IV, or if the IV has not yet * been set. */ public final byte[] getIV() { chooseFirstProvider(); return spi.engineGetIV(); } /** * Returns the parameters used with this cipher. * *

The returned parameters may be the same that were used to initialize * this cipher, or may contain a combination of default and random * parameter values used by the underlying cipher implementation if this * cipher requires algorithm parameters but was not initialized with any. * * @return the parameters used with this cipher, or null if this cipher * does not use any parameters. */ public final AlgorithmParameters getParameters() { chooseFirstProvider(); return spi.engineGetParameters(); } /** * Returns the exemption mechanism object used with this cipher. * * @return the exemption mechanism object used with this cipher, or * null if this cipher does not use any exemption mechanism. */ public final ExemptionMechanism getExemptionMechanism() { chooseFirstProvider(); return exmech; } // check if opmode is one of the defined constants // throw InvalidParameterExeption if not private static void checkOpmode(int opmode) { if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) { throw new InvalidParameterException("Invalid operation mode"); } } /** * Initializes this cipher with a key. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If this cipher requires any algorithm parameters that cannot be * derived from the given key, the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidKeyException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the {@link SecureRandom SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of * the following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the key * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or if this cipher is being initialized for * decryption and requires algorithm parameters that cannot be * determined from the given key, or if the given key has a keysize that * exceeds the maximum allowable keysize (as determined from the * configured jurisdiction policy files). */ public final void init(int opmode, Key key) throws InvalidKeyException { init(opmode, key, JceSecurity.RANDOM); } /** * Initializes this cipher with a key and a source of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If this cipher requires any algorithm parameters that cannot be * derived from the given key, the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidKeyException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the encryption key * @param random the source of randomness * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or if this cipher is being initialized for * decryption and requires algorithm parameters that cannot be * determined from the given key, or if the given key has a keysize that * exceeds the maximum allowable keysize (as determined from the * configured jurisdiction policy files). */ public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException { initialized = false; checkOpmode(opmode); if (spi != null) { spi.engineInit(opmode, key, random); } else { try { chooseProvider(I_KEY, opmode, key, null, null, random); } catch (InvalidAlgorithmParameterException e) { // should never occur throw new InvalidKeyException(e); } } initialized = true; this.opmode = opmode; } /** * Initializes this cipher with a key and a set of algorithm * parameters. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If this cipher requires any algorithm parameters and * params is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidAlgorithmParameterException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the {@link SecureRandom SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the encryption key * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files). * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher is being initialized for decryption and requires * algorithm parameters and params is null, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files). */ public final void init(int opmode, Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { init(opmode, key, params, JceSecurity.RANDOM); } /** * Initializes this cipher with a key, a set of algorithm * parameters, and a source of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If this cipher requires any algorithm parameters and * params is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidAlgorithmParameterException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the encryption key * @param params the algorithm parameters * @param random the source of randomness * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files). * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher is being initialized for decryption and requires * algorithm parameters and params is null, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files). */ public final void init(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { initialized = false; checkOpmode(opmode); if (spi != null) { spi.engineInit(opmode, key, params, random); } else { chooseProvider(I_PARAMSPEC, opmode, key, params, null, random); } initialized = true; this.opmode = opmode; } /** * Initializes this cipher with a key and a set of algorithm * parameters. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If this cipher requires any algorithm parameters and * params is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidAlgorithmParameterException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the {@link SecureRandom SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: ENCRYPT_MODE, * DECRYPT_MODE, WRAP_MODE * or UNWRAP_MODE) * @param key the encryption key * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files). * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher is being initialized for decryption and requires * algorithm parameters and params is null, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files). */ public final void init(int opmode, Key key, AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException { init(opmode, key, params, JceSecurity.RANDOM); } /** * Initializes this cipher with a key, a set of algorithm * parameters, and a source of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If this cipher requires any algorithm parameters and * params is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidAlgorithmParameterException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: ENCRYPT_MODE, * DECRYPT_MODE, WRAP_MODE * or UNWRAP_MODE) * @param key the encryption key * @param params the algorithm parameters * @param random the source of randomness * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or its keysize exceeds the maximum allowable * keysize (as determined from the configured jurisdiction policy files). * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or this cipher is being initialized for decryption and requires * algorithm parameters and params is null, or the given * algorithm parameters imply a cryptographic strength that would exceed * the legal limits (as determined from the configured jurisdiction * policy files). */ public final void init(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { initialized = false; checkOpmode(opmode); if (spi != null) { spi.engineInit(opmode, key, params, random); } else { chooseProvider(I_PARAMS, opmode, key, null, params, random); } initialized = true; this.opmode = opmode; } /** * Initializes this cipher with the public key from the given certificate. *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending * on the value of opmode. * *

If the certificate is of type X.509 and has a key usage * extension field marked as critical, and the value of the key usage * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for the operation represented by the value * of opmode, * an InvalidKeyException * is thrown. * *

If this cipher requires any algorithm parameters that cannot be * derived from the public key in the given certificate, the underlying * cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or ramdom values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidKeyException if it is being initialized for decryption or * key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them using the * SecureRandom * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param certificate the certificate * * @exception InvalidKeyException if the public key in the given * certificate is inappropriate for initializing this cipher, or this * cipher is being initialized for decryption or unwrapping keys and * requires algorithm parameters that cannot be determined from the * public key in the given certificate, or the keysize of the public key * in the given certificate has a keysize that exceeds the maximum * allowable keysize (as determined by the configured jurisdiction policy * files). */ public final void init(int opmode, Certificate certificate) throws InvalidKeyException { init(opmode, certificate, JceSecurity.RANDOM); } /** * Initializes this cipher with the public key from the given certificate * and * a source of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping * or key unwrapping, depending on * the value of opmode. * *

If the certificate is of type X.509 and has a key usage * extension field marked as critical, and the value of the key usage * extension field implies that the public key in * the certificate and its corresponding private key are not * supposed to be used for the operation represented by the value of * opmode, * an InvalidKeyException * is thrown. * *

If this cipher requires any algorithm parameters that cannot be * derived from the public key in the given certificate, * the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidKeyException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #getParameters() getParameters} or * {@link #getIV() getIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of the * following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param certificate the certificate * @param random the source of randomness * * @exception InvalidKeyException if the public key in the given * certificate is inappropriate for initializing this cipher, or this * cipher is being initialized for decryption or unwrapping keys and * requires algorithm parameters that cannot be determined from the * public key in the given certificate, or the keysize of the public key * in the given certificate has a keysize that exceeds the maximum * allowable keysize (as determined by the configured jurisdiction policy * files). */ public final void init(int opmode, Certificate certificate, SecureRandom random) throws InvalidKeyException { initialized = false; checkOpmode(opmode); // Check key usage if the certificate is of // type X.509. if (certificate instanceof java.security.cert.X509Certificate) { // Check whether the cert has a key usage extension // marked as a critical extension. X509Certificate cert = (X509Certificate)certificate; Set critSet = cert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty() && critSet.contains(KEY_USAGE_EXTENSION_OID)) { boolean[] keyUsageInfo = cert.getKeyUsage(); // keyUsageInfo[2] is for keyEncipherment; // keyUsageInfo[3] is for dataEncipherment. if ((keyUsageInfo != null) && (((opmode == Cipher.ENCRYPT_MODE) && (keyUsageInfo.length > 3) && (keyUsageInfo[3] == false)) || ((opmode == Cipher.WRAP_MODE) && (keyUsageInfo.length > 2) && (keyUsageInfo[2] == false)))) { throw new InvalidKeyException("Wrong key usage"); } } } PublicKey publicKey = (certificate==null? null:certificate.getPublicKey()); if (spi != null) { spi.engineInit(opmode, publicKey, random); } else { try { chooseProvider(I_CERT, opmode, publicKey, null, null, random); } catch (InvalidAlgorithmParameterException e) { // should never occur throw new InvalidKeyException(e); } } initialized = true; this.opmode = opmode; } /** * Ensures that Cipher is in a valid state for update() and doFinal() * calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE. * @throws IllegalStateException if Cipher object is not in valid state. */ private void checkCipherState() { if (!(this instanceof NullCipher)) { if (!initialized) { throw new IllegalStateException("Cipher not initialized"); } if ((opmode != Cipher.ENCRYPT_MODE) && (opmode != Cipher.DECRYPT_MODE)) { throw new IllegalStateException("Cipher not initialized " + "for encryption/decryption"); } } } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

The bytes in the input buffer are processed, and the * result is stored in a new buffer. * *

If input has a length of zero, this method returns * null. * * @param input the input buffer * * @return the new buffer with the result, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) */ public final byte[] update(byte[] input) { checkCipherState(); // Input sanity check if (input == null) { throw new IllegalArgumentException("Null input buffer"); } chooseFirstProvider(); if (input.length == 0) { return null; } return spi.engineUpdate(input, 0, input.length); } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, are processed, * and the result is stored in a new buffer. * *

If inputLen is zero, this method returns * null. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * * @return the new buffer with the result, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) */ public final byte[] update(byte[] input, int inputOffset, int inputLen) { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return null; } return spi.engineUpdate(input, inputOffset, inputLen); } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, are processed, * and the result is stored in the output buffer. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

If inputLen is zero, this method returns * a length of zero. * *

Note: this method should be copy-safe, which means the * input and output buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * @param output the buffer for the result * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output) throws ShortBufferException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return 0; } return spi.engineUpdate(input, inputOffset, inputLen, output, 0); } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, are processed, * and the result is stored in the output buffer, starting at * outputOffset inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

If inputLen is zero, this method returns * a length of zero. * *

Note: this method should be copy-safe, which means the * input and output buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception ShortBufferException if the given output buffer is too small * to hold the result */ public final int update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0 || outputOffset < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); if (inputLen == 0) { return 0; } return spi.engineUpdate(input, inputOffset, inputLen, output, outputOffset); } /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

All input.remaining() bytes starting at * input.position() are processed. The result is stored * in the output buffer. * Upon return, the input buffer's position will be equal * to its limit; its limit will not have changed. The output buffer's * position will have advanced by n, where n is the value returned * by this method; the output buffer's limit will not have changed. * *

If output.remaining() bytes are insufficient to * hold the result, a ShortBufferException is thrown. * In this case, repeat this call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

Note: this method should be copy-safe, which means the * input and output buffers can reference * the same block of memory and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input ByteBuffer * @param output the output ByteByffer * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalArgumentException if input and output are the * same object * @exception ReadOnlyBufferException if the output buffer is read-only * @exception ShortBufferException if there is insufficient space in the * output buffer * @since 1.5 */ public final int update(ByteBuffer input, ByteBuffer output) throws ShortBufferException { checkCipherState(); if ((input == null) || (output == null)) { throw new IllegalArgumentException("Buffers must not be null"); } if (input == output) { throw new IllegalArgumentException("Input and output buffers must " + "not be the same object, consider using buffer.duplicate()"); } if (output.isReadOnly()) { throw new ReadOnlyBufferException(); } chooseFirstProvider(); return spi.engineUpdate(input, output); } /** * Finishes a multiple-part encryption or decryption operation, depending * on how this cipher was initialized. * *

Input data that may have been buffered during a previous * update operation is processed, with padding (if requested) * being applied. * The result is stored in a new buffer. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @return the new buffer with the result * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final byte[] doFinal() throws IllegalBlockSizeException, BadPaddingException { checkCipherState(); chooseFirstProvider(); return spi.engineDoFinal(null, 0, 0); } /** * Finishes a multiple-part encryption or decryption operation, depending * on how this cipher was initialized. * *

Input data that may have been buffered during a previous * update operation is processed, with padding (if requested) * being applied. * The result is stored in the output buffer, starting at * outputOffset inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception ShortBufferException if the given output buffer is too small * to hold the result * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final int doFinal(byte[] output, int outputOffset) throws IllegalBlockSizeException, ShortBufferException, BadPaddingException { checkCipherState(); // Input sanity check if ((output == null) || (outputOffset < 0)) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); return spi.engineDoFinal(null, 0, 0, output, outputOffset); } /** * Encrypts or decrypts data in a single-part operation, or finishes a * multiple-part operation. The data is encrypted or decrypted, * depending on how this cipher was initialized. * *

The bytes in the input buffer, and any input bytes that * may have been buffered during a previous update operation, * are processed, with padding (if requested) being applied. * The result is stored in a new buffer. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param input the input buffer * * @return the new buffer with the result * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException, BadPaddingException { checkCipherState(); // Input sanity check if (input == null) { throw new IllegalArgumentException("Null input buffer"); } chooseFirstProvider(); return spi.engineDoFinal(input, 0, input.length); } /** * Encrypts or decrypts data in a single-part operation, or finishes a * multiple-part operation. The data is encrypted or decrypted, * depending on how this cipher was initialized. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, and any input * bytes that may have been buffered during a previous update * operation, are processed, with padding (if requested) being applied. * The result is stored in a new buffer. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * * @return the new buffer with the result * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final byte[] doFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); return spi.engineDoFinal(input, inputOffset, inputLen); } /** * Encrypts or decrypts data in a single-part operation, or finishes a * multiple-part operation. The data is encrypted or decrypted, * depending on how this cipher was initialized. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, and any input * bytes that may have been buffered during a previous update * operation, are processed, with padding (if requested) being applied. * The result is stored in the output buffer. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * *

Note: this method should be copy-safe, which means the * input and output buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * @param output the buffer for the result * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception ShortBufferException if the given output buffer is too small * to hold the result * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); return spi.engineDoFinal(input, inputOffset, inputLen, output, 0); } /** * Encrypts or decrypts data in a single-part operation, or finishes a * multiple-part operation. The data is encrypted or decrypted, * depending on how this cipher was initialized. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, and any input * bytes that may have been buffered during a previous * update operation, are processed, with padding * (if requested) being applied. * The result is stored in the output buffer, starting at * outputOffset inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * *

Note: this method should be copy-safe, which means the * input and output buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception ShortBufferException if the given output buffer is too small * to hold the result * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ public final int doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { checkCipherState(); // Input sanity check if (input == null || inputOffset < 0 || inputLen > (input.length - inputOffset) || inputLen < 0 || outputOffset < 0) { throw new IllegalArgumentException("Bad arguments"); } chooseFirstProvider(); return spi.engineDoFinal(input, inputOffset, inputLen, output, outputOffset); } /** * Encrypts or decrypts data in a single-part operation, or finishes a * multiple-part operation. The data is encrypted or decrypted, * depending on how this cipher was initialized. * *

All input.remaining() bytes starting at * input.position() are processed. The result is stored * in the output buffer. * Upon return, the input buffer's position will be equal * to its limit; its limit will not have changed. The output buffer's * position will have advanced by n, where n is the value returned * by this method; the output buffer's limit will not have changed. * *

If output.remaining() bytes are insufficient to * hold the result, a ShortBufferException is thrown. * In this case, repeat this call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to init. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * init) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * *

Note: this method should be copy-safe, which means the * input and output buffers can reference * the same byte array and no unprocessed input data is overwritten * when the result is copied into the output buffer. * * @param input the input ByteBuffer * @param output the output ByteBuffer * * @return the number of bytes stored in output * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized) * @exception IllegalArgumentException if input and output are the * same object * @exception ReadOnlyBufferException if the output buffer is read-only * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception ShortBufferException if there is insufficient space in the * output buffer * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes * @since 1.5 */ public final int doFinal(ByteBuffer input, ByteBuffer output) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { checkCipherState(); if ((input == null) || (output == null)) { throw new IllegalArgumentException("Buffers must not be null"); } if (input == output) { throw new IllegalArgumentException("Input and output buffers must " + "not be the same object, consider using buffer.duplicate()"); } if (output.isReadOnly()) { throw new ReadOnlyBufferException(); } chooseFirstProvider(); return spi.engineDoFinal(input, output); } /** * Wrap a key. * * @param key the key to be wrapped. * * @return the wrapped key. * * @exception IllegalStateException if this cipher is in a wrong * state (e.g., has not been initialized). * * @exception IllegalBlockSizeException if this cipher is a block * cipher, no padding has been requested, and the length of the * encoding of the key to be wrapped is not a * multiple of the block size. * * @exception InvalidKeyException if it is impossible or unsafe to * wrap the key with this cipher (e.g., a hardware protected key is * being passed to a software-only cipher). */ public final byte[] wrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { if (!(this instanceof NullCipher)) { if (!initialized) { throw new IllegalStateException("Cipher not initialized"); } if (opmode != Cipher.WRAP_MODE) { throw new IllegalStateException("Cipher not initialized " + "for wrapping keys"); } } chooseFirstProvider(); return spi.engineWrap(key); } /** * Unwrap a previously wrapped key. * * @param wrappedKey the key to be unwrapped. * * @param wrappedKeyAlgorithm the algorithm associated with the wrapped * key. * * @param wrappedKeyType the type of the wrapped key. This must be one of * SECRET_KEY, PRIVATE_KEY, or * PUBLIC_KEY. * * @return the unwrapped key. * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not been initialized). * * @exception NoSuchAlgorithmException if no installed providers * can create keys of type wrappedKeyType for the * wrappedKeyAlgorithm. * * @exception InvalidKeyException if wrappedKey does not * represent a wrapped key of type wrappedKeyType for * the wrappedKeyAlgorithm. */ public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { if (!(this instanceof NullCipher)) { if (!initialized) { throw new IllegalStateException("Cipher not initialized"); } if (opmode != Cipher.UNWRAP_MODE) { throw new IllegalStateException("Cipher not initialized " + "for unwrapping keys"); } } if ((wrappedKeyType != SECRET_KEY) && (wrappedKeyType != PRIVATE_KEY) && (wrappedKeyType != PUBLIC_KEY)) { throw new InvalidParameterException("Invalid key type"); } chooseFirstProvider(); return spi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType); } private AlgorithmParameterSpec getAlgorithmParameterSpec( AlgorithmParameters params) throws InvalidParameterSpecException { if (params == null) { return null; } String alg = params.getAlgorithm().toUpperCase(Locale.ENGLISH); if (alg.equalsIgnoreCase("RC2")) { return params.getParameterSpec(RC2ParameterSpec.class); } if (alg.equalsIgnoreCase("RC5")) { return params.getParameterSpec(RC5ParameterSpec.class); } if (alg.startsWith("PBE")) { return params.getParameterSpec(PBEParameterSpec.class); } if (alg.startsWith("DES")) { return params.getParameterSpec(IvParameterSpec.class); } return null; } // Used by getMaxAllowedKeyLength and getMaxAllowedParameterSpec // always returns CryptoAllPermission. Old stuff from bad old days. private static CryptoPermission getConfiguredPermission( String transformation) throws NullPointerException, NoSuchAlgorithmException { if (transformation == null) throw new NullPointerException(); // Called to make sure it is a valid transformation. tokenizeTransformation(transformation); return CryptoAllPermission.INSTANCE; } /** * Returns the maximum key length for the specified transformation * according to the installed JCE jurisdiction policy files. If * JCE unlimited strength jurisdiction policy files are installed, * Integer.MAX_VALUE will be returned. * For more information on default key size in JCE jurisdiction * policy files, please see Appendix E in the * * Java Cryptography Architecture Reference Guide. * * @param transformation the cipher transformation. * @return the maximum key length in bits or Integer.MAX_VALUE. * @exception NullPointerException if transformation is null. * @exception NoSuchAlgorithmException if transformation * is not a valid transformation, i.e. in the form of "algorithm" or * "algorithm/mode/padding". * @since 1.5 */ public static final int getMaxAllowedKeyLength(String transformation) throws NoSuchAlgorithmException { CryptoPermission cp = getConfiguredPermission(transformation); return cp.getMaxKeySize(); } /** * Returns an AlgorithmParameterSpec object which contains * the maximum cipher parameter value according to the * jurisdiction policy file. If JCE unlimited strength jurisdiction * policy files are installed or there is no maximum limit on the * parameters for the specified transformation in the policy file, * null will be returned. * * @param transformation the cipher transformation. * @return an AlgorithmParameterSpec which holds the maximum * value or null. * @exception NullPointerException if transformation * is null. * @exception NoSuchAlgorithmException if transformation * is not a valid transformation, i.e. in the form of "algorithm" or * "algorithm/mode/padding". * @since 1.5 */ public static final AlgorithmParameterSpec getMaxAllowedParameterSpec( String transformation) throws NoSuchAlgorithmException { CryptoPermission cp = getConfiguredPermission(transformation); return cp.getAlgorithmParameterSpec(); } } clean-crypto-1/src/main/java/javax/crypto/CipherInputStream.java0000664000175000017500000002674211370332423025045 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.io.*; /** * A CipherInputStream is composed of an InputStream and a Cipher so * that read() methods return data that are read in from the * underlying InputStream but have been additionally processed by the * Cipher. The Cipher must be fully initialized before being used by * a CipherInputStream. * *

For example, if the Cipher is initialized for decryption, the * CipherInputStream will attempt to read in data and decrypt them, * before returning the decrypted data. * *

This class adheres strictly to the semantics, especially the * failure semantics, of its ancestor classes * java.io.FilterInputStream and java.io.InputStream. This class has * exactly those methods specified in its ancestor classes, and * overrides them all. Moreover, this class catches all exceptions * that are not thrown by its ancestor classes. In particular, the * skip method skips, and the available * method counts only data that have been processed by the encapsulated Cipher. * *

It is crucial for a programmer using this class not to use * methods that are not defined or overriden in this class (such as a * new method or constructor that is later added to one of the super * classes), because the design and implementation of those methods * are unlikely to have considered security impact with regard to * CipherInputStream. * * @author Li Gong * @see java.io.InputStream * @see java.io.FilterInputStream * @see javax.crypto.Cipher * @see javax.crypto.CipherOutputStream * * @since 1.4 */ public class CipherInputStream extends FilterInputStream { // the cipher engine to use to process stream data private Cipher cipher; // the underlying input stream private InputStream input; /* the buffer holding data that have been read in from the underlying stream, but have not been processed by the cipher engine. the size 512 bytes is somewhat randomly chosen */ private byte[] ibuffer = new byte[512]; // having reached the end of the underlying input stream private boolean done = false; /* the buffer holding data that have been processed by the cipher engine, but have not been read out */ private byte[] obuffer; // the offset pointing to the next "new" byte private int ostart = 0; // the offset pointing to the last "new" byte private int ofinish = 0; /** * private convenience function. * * Entry condition: ostart = ofinish * * Exit condition: ostart <= ofinish * * return (ofinish-ostart) (we have this many bytes for you) * return 0 (no data now, but could have more later) * return -1 (absolutely no more data) */ private int getMoreData() throws IOException { if (done) return -1; int readin = input.read(ibuffer); if (readin == -1) { done = true; try { obuffer = cipher.doFinal(); } catch (IllegalBlockSizeException e) {obuffer = null;} catch (BadPaddingException e) {obuffer = null;} if (obuffer == null) return -1; else { ostart = 0; ofinish = obuffer.length; return ofinish; } } try { obuffer = cipher.update(ibuffer, 0, readin); } catch (IllegalStateException e) {obuffer = null;}; ostart = 0; if (obuffer == null) ofinish = 0; else ofinish = obuffer.length; return ofinish; } /** * Constructs a CipherInputStream from an InputStream and a * Cipher. *
Note: if the specified input stream or cipher is * null, a NullPointerException may be thrown later when * they are used. * @param is the to-be-processed input stream * @param c an initialized Cipher object */ public CipherInputStream(InputStream is, Cipher c) { super(is); input = is; cipher = c; } /** * Constructs a CipherInputStream from an InputStream without * specifying a Cipher. This has the effect of constructing a * CipherInputStream using a NullCipher. *
Note: if the specified input stream is null, a * NullPointerException may be thrown later when it is used. * @param is the to-be-processed input stream */ protected CipherInputStream(InputStream is) { super(is); input = is; cipher = new NullCipher(); } /** * Reads the next byte of data from this input stream. The value * byte is returned as an int in the range * 0 to 255. If no byte is available * because the end of the stream has been reached, the value * -1 is returned. This method blocks until input data * is available, the end of the stream is detected, or an exception * is thrown. *

* * @return the next byte of data, or -1 if the end of the * stream is reached. * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public int read() throws IOException { if (ostart >= ofinish) { // we loop for new data as the spec says we are blocking int i = 0; while (i == 0) i = getMoreData(); if (i == -1) return -1; } return ((int) obuffer[ostart++] & 0xff); }; /** * Reads up to b.length bytes of data from this input * stream into an array of bytes. *

* The read method of InputStream calls * the read method of three arguments with the arguments * b, 0, and b.length. * * @param b the buffer into which the data is read. * @return the total number of bytes read into the buffer, or * -1 is there is no more data because the end of * the stream has been reached. * @exception IOException if an I/O error occurs. * @see java.io.InputStream#read(byte[], int, int) * @since JCE1.2 */ public int read(byte b[]) throws IOException { return read(b, 0, b.length); } /** * Reads up to len bytes of data from this input stream * into an array of bytes. This method blocks until some input is * available. If the first argument is null, up to * len bytes are read and discarded. * * @param b the buffer into which the data is read. * @param off the start offset in the destination array * buf * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or * -1 if there is no more data because the end of * the stream has been reached. * @exception IOException if an I/O error occurs. * @see java.io.InputStream#read() * @since JCE1.2 */ public int read(byte b[], int off, int len) throws IOException { if (ostart >= ofinish) { // we loop for new data as the spec says we are blocking int i = 0; while (i == 0) i = getMoreData(); if (i == -1) return -1; } if (len <= 0) { return 0; } int available = ofinish - ostart; if (len < available) available = len; if (b != null) { System.arraycopy(obuffer, ostart, b, off, available); } ostart = ostart + available; return available; } /** * Skips n bytes of input from the bytes that can be read * from this input stream without blocking. * *

Fewer bytes than requested might be skipped. * The actual number of bytes skipped is equal to n or * the result of a call to * {@link #available() available}, * whichever is smaller. * If n is less than zero, no bytes are skipped. * *

The actual number of bytes skipped is returned. * * @param n the number of bytes to be skipped. * @return the actual number of bytes skipped. * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public long skip(long n) throws IOException { int available = ofinish - ostart; if (n > available) { n = available; } if (n < 0) { return 0; } ostart += n; return n; } /** * Returns the number of bytes that can be read from this input * stream without blocking. The available method of * InputStream returns 0. This method * should be overridden by subclasses. * * @return the number of bytes that can be read from this input stream * without blocking. * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public int available() throws IOException { return (ofinish - ostart); } /** * Closes this input stream and releases any system resources * associated with the stream. *

* The close method of CipherInputStream * calls the close method of its underlying input * stream. * * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public void close() throws IOException { input.close(); try { // throw away the unprocessed data cipher.doFinal(); } catch (BadPaddingException ex) { } catch (IllegalBlockSizeException ex) { } ostart = 0; ofinish = 0; } /** * Tests if this input stream supports the mark * and reset methods, which it does not. * * @return false, since this class does not support the * mark and reset methods. * @see java.io.InputStream#mark(int) * @see java.io.InputStream#reset() * @since JCE1.2 */ public boolean markSupported() { return false; } } clean-crypto-1/src/main/java/javax/crypto/CipherOutputStream.java0000664000175000017500000001665511370332423025250 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.io.*; /** * A CipherOutputStream is composed of an OutputStream and a Cipher so * that write() methods first process the data before writing them out * to the underlying OutputStream. The cipher must be fully * initialized before being used by a CipherOutputStream. * *

For example, if the cipher is initialized for encryption, the * CipherOutputStream will attempt to encrypt data before writing out the * encrypted data. * *

This class adheres strictly to the semantics, especially the * failure semantics, of its ancestor classes * java.io.OutputStream and java.io.FilterOutputStream. This class * has exactly those methods specified in its ancestor classes, and * overrides them all. Moreover, this class catches all exceptions * that are not thrown by its ancestor classes. * *

It is crucial for a programmer using this class not to use * methods that are not defined or overriden in this class (such as a * new method or constructor that is later added to one of the super * classes), because the design and implementation of those methods * are unlikely to have considered security impact with regard to * CipherOutputStream. * * @author Li Gong * @see java.io.OutputStream * @see java.io.FilterOutputStream * @see javax.crypto.Cipher * @see javax.crypto.CipherInputStream * * @since 1.4 */ public class CipherOutputStream extends FilterOutputStream { // the cipher engine to use to process stream data private Cipher cipher; // the underlying output stream private OutputStream output; /* the buffer holding one byte of incoming data */ private byte[] ibuffer = new byte[1]; // the buffer holding data ready to be written out private byte[] obuffer; /** * * Constructs a CipherOutputStream from an OutputStream and a * Cipher. *
Note: if the specified output stream or cipher is * null, a NullPointerException may be thrown later when * they are used. * * @param os the OutputStream object * @param c an initialized Cipher object */ public CipherOutputStream(OutputStream os, Cipher c) { super(os); output = os; cipher = c; }; /** * Constructs a CipherOutputStream from an OutputStream without * specifying a Cipher. This has the effect of constructing a * CipherOutputStream using a NullCipher. *
Note: if the specified output stream is null, a * NullPointerException may be thrown later when it is used. * * @param os the OutputStream object */ protected CipherOutputStream(OutputStream os) { super(os); output = os; cipher = new NullCipher(); } /** * Writes the specified byte to this output stream. * * @param b the byte. * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public void write(int b) throws IOException { ibuffer[0] = (byte) b; obuffer = cipher.update(ibuffer, 0, 1); if (obuffer != null) { output.write(obuffer); obuffer = null; } }; /** * Writes b.length bytes from the specified byte array * to this output stream. *

* The write method of * CipherOutputStream calls the write * method of three arguments with the three arguments * b, 0, and b.length. * * @param b the data. * @exception NullPointerException if b is null. * @exception IOException if an I/O error occurs. * @see javax.crypto.CipherOutputStream#write(byte[], int, int) * @since JCE1.2 */ public void write(byte b[]) throws IOException { write(b, 0, b.length); } /** * Writes len bytes from the specified byte array * starting at offset off to this output stream. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public void write(byte b[], int off, int len) throws IOException { obuffer = cipher.update(b, off, len); if (obuffer != null) { output.write(obuffer); obuffer = null; } } /** * Flushes this output stream by forcing any buffered output bytes * that have already been processed by the encapsulated cipher object * to be written out. * *

Any bytes buffered by the encapsulated cipher * and waiting to be processed by it will not be written out. For example, * if the encapsulated cipher is a block cipher, and the total number of * bytes written using one of the write methods is less than * the cipher's block size, no bytes will be written out. * * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public void flush() throws IOException { if (obuffer != null) { output.write(obuffer); obuffer = null; } output.flush(); } /** * Closes this output stream and releases any system resources * associated with this stream. *

* This method invokes the doFinal method of the encapsulated * cipher object, which causes any bytes buffered by the encapsulated * cipher to be processed. The result is written out by calling the * flush method of this output stream. *

* This method resets the encapsulated cipher object to its initial state * and calls the close method of the underlying output * stream. * * @exception IOException if an I/O error occurs. * @since JCE1.2 */ public void close() throws IOException { try { obuffer = cipher.doFinal(); } catch (IllegalBlockSizeException e) { obuffer = null; } catch (BadPaddingException e) { obuffer = null; } try { flush(); } catch (IOException ignored) {} out.close(); } } clean-crypto-1/src/main/java/javax/crypto/CipherSpi.java0000664000175000017500000011050511370332423023314 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.StringTokenizer; import java.util.NoSuchElementException; import java.security.AlgorithmParameters; import java.security.Provider; import java.security.Key; import java.security.SecureRandom; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.InvalidKeyException; import java.security.InvalidAlgorithmParameterException; import java.security.ProviderException; import java.security.spec.AlgorithmParameterSpec; import java.nio.ByteBuffer; /** * This class defines the Service Provider Interface (SPI) * for the Cipher class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a particular cipher algorithm. * *

In order to create an instance of Cipher, which * encapsulates an instance of this CipherSpi class, an * application calls one of the * {@link Cipher#getInstance(java.lang.String) getInstance} * factory methods of the * {@link Cipher Cipher} engine class and specifies the requested * transformation. * Optionally, the application may also specify the name of a provider. * *

A transformation is a string that describes the operation (or * set of operations) to be performed on the given input, to produce some * output. A transformation always includes the name of a cryptographic * algorithm (e.g., DES), and may be followed by a feedback mode and * padding scheme. * *

A transformation is of the form:

* *

    *
  • "algorithm/mode/padding" or *

    *

  • "algorithm" *
* *

(in the latter case, * provider-specific default values for the mode and padding scheme are used). * For example, the following is a valid transformation:

* *

 *     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
 * 
* *

A provider may supply a separate class for each combination * of algorithm/mode/padding, or may decide to provide more generic * classes representing sub-transformations corresponding to * algorithm or algorithm/mode or algorithm//padding * (note the double slashes), * in which case the requested mode and/or padding are set automatically by * the getInstance methods of Cipher, which invoke * the {@link #engineSetMode(java.lang.String) engineSetMode} and * {@link #engineSetPadding(java.lang.String) engineSetPadding} * methods of the provider's subclass of CipherSpi. * *

A Cipher property in a provider master class may have one of * the following formats: * *

    * *
  • *
     *     // provider's subclass of "CipherSpi" implements "algName" with
     *     // pluggable mode and padding
     *     Cipher.algName
     * 
    * *
  • *
     *     // provider's subclass of "CipherSpi" implements "algName" in the
     *     // specified "mode", with pluggable padding
     *     Cipher.algName/mode
     * 
    * *
  • *
     *     // provider's subclass of "CipherSpi" implements "algName" with the
     *     // specified "padding", with pluggable mode
     *     Cipher.algName//padding
     * 
    * *
  • *
     *     // provider's subclass of "CipherSpi" implements "algName" with the
     *     // specified "mode" and "padding"
     *     Cipher.algName/mode/padding
     * 
    * *
* *

For example, a provider may supply a subclass of CipherSpi * that implements DES/ECB/PKCS5Padding, one that implements * DES/CBC/PKCS5Padding, one that implements * DES/CFB/PKCS5Padding, and yet another one that implements * DES/OFB/PKCS5Padding. That provider would have the following * Cipher properties in its master class:

* *

    * *
  • *
     *     Cipher.DES/ECB/PKCS5Padding
     * 
    * *
  • *
     *     Cipher.DES/CBC/PKCS5Padding
     * 
    * *
  • *
     *     Cipher.DES/CFB/PKCS5Padding
     * 
    * *
  • *
     *     Cipher.DES/OFB/PKCS5Padding
     * 
    * *
* *

Another provider may implement a class for each of the above modes * (i.e., one class for ECB, one for CBC, one for CFB, * and one for OFB), one class for PKCS5Padding, * and a generic DES class that subclasses from CipherSpi. * That provider would have the following * Cipher properties in its master class:

* *

    * *
  • *
     *     Cipher.DES
     * 
    * *
* *

The getInstance factory method of the Cipher * engine class follows these rules in order to instantiate a provider's * implementation of CipherSpi for a * transformation of the form "algorithm": * *

    *
  1. * Check if the provider has registered a subclass of CipherSpi * for the specified "algorithm". *

    If the answer is YES, instantiate this * class, for whose mode and padding scheme default values (as supplied by * the provider) are used. *

    If the answer is NO, throw a NoSuchAlgorithmException * exception. *

* *

The getInstance factory method of the Cipher * engine class follows these rules in order to instantiate a provider's * implementation of CipherSpi for a * transformation of the form "algorithm/mode/padding": * *

    *
  1. * Check if the provider has registered a subclass of CipherSpi * for the specified "algorithm/mode/padding" transformation. *

    If the answer is YES, instantiate it. *

    If the answer is NO, go to the next step.

    *

  2. * Check if the provider has registered a subclass of CipherSpi * for the sub-transformation "algorithm/mode". *

    If the answer is YES, instantiate it, and call * engineSetPadding(padding) on the new instance. *

    If the answer is NO, go to the next step.

    *

  3. * Check if the provider has registered a subclass of CipherSpi * for the sub-transformation "algorithm//padding" (note the double * slashes). *

    If the answer is YES, instantiate it, and call * engineSetMode(mode) on the new instance. *

    If the answer is NO, go to the next step.

    *

  4. * Check if the provider has registered a subclass of CipherSpi * for the sub-transformation "algorithm". *

    If the answer is YES, instantiate it, and call * engineSetMode(mode) and * engineSetPadding(padding) on the new instance. *

    If the answer is NO, throw a NoSuchAlgorithmException * exception. *

* * @author Jan Luehe * @see KeyGenerator * @see SecretKey * @since 1.4 */ public abstract class CipherSpi { /** * Sets the mode of this cipher. * * @param mode the cipher mode * * @exception NoSuchAlgorithmException if the requested cipher mode does * not exist */ protected abstract void engineSetMode(String mode) throws NoSuchAlgorithmException; /** * Sets the padding mechanism of this cipher. * * @param padding the padding mechanism * * @exception NoSuchPaddingException if the requested padding mechanism * does not exist */ protected abstract void engineSetPadding(String padding) throws NoSuchPaddingException; /** * Returns the block size (in bytes). * * @return the block size (in bytes), or 0 if the underlying algorithm is * not a block cipher */ protected abstract int engineGetBlockSize(); /** * Returns the length in bytes that an output buffer would * need to be in order to hold the result of the next update * or doFinal operation, given the input length * inputLen (in bytes). * *

This call takes into account any unprocessed (buffered) data from a * previous update call, and padding. * *

The actual output length of the next update or * doFinal call may be smaller than the length returned by * this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) */ protected abstract int engineGetOutputSize(int inputLen); /** * Returns the initialization vector (IV) in a new buffer. * *

This is useful in the context of password-based encryption or * decryption, where the IV is derived from a user-provided passphrase. * * @return the initialization vector in a new buffer, or null if the * underlying algorithm does not use an IV, or if the IV has not yet * been set. */ protected abstract byte[] engineGetIV(); /** * Returns the parameters used with this cipher. * *

The returned parameters may be the same that were used to initialize * this cipher, or may contain a combination of default and random * parameter values used by the underlying cipher implementation if this * cipher requires algorithm parameters but was not initialized with any. * * @return the parameters used with this cipher, or null if this cipher * does not use any parameters. */ protected abstract AlgorithmParameters engineGetParameters(); /** * Initializes this cipher with a key and a source * of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending on * the value of opmode. * *

If this cipher requires any algorithm parameters that cannot be * derived from the given key, the underlying cipher * implementation is supposed to generate the required parameters itself * (using provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidKeyException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #engineGetParameters() engineGetParameters} or * {@link #engineGetIV() engineGetIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of * the following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the encryption key * @param random the source of randomness * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher, or if this cipher is being initialized for * decryption and requires algorithm parameters that cannot be * determined from the given key. */ protected abstract void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException; /** * Initializes this cipher with a key, a set of * algorithm parameters, and a source of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending on * the value of opmode. * *

If this cipher requires any algorithm parameters and * params is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidAlgorithmParameterException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #engineGetParameters() engineGetParameters} or * {@link #engineGetIV() engineGetIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of * the following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the encryption key * @param params the algorithm parameters * @param random the source of randomness * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or if this cipher is being initialized for decryption and requires * algorithm parameters and params is null. */ protected abstract void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * Initializes this cipher with a key, a set of * algorithm parameters, and a source of randomness. * *

The cipher is initialized for one of the following four operations: * encryption, decryption, key wrapping or key unwrapping, depending on * the value of opmode. * *

If this cipher requires any algorithm parameters and * params is null, the underlying cipher implementation is * supposed to generate the required parameters itself (using * provider-specific default or random values) if it is being * initialized for encryption or key wrapping, and raise an * InvalidAlgorithmParameterException if it is being * initialized for decryption or key unwrapping. * The generated parameters can be retrieved using * {@link #engineGetParameters() engineGetParameters} or * {@link #engineGetIV() engineGetIV} (if the parameter is an IV). * *

If this cipher (including its underlying feedback or padding scheme) * requires any random bytes (e.g., for parameter generation), it will get * them from random. * *

Note that when a Cipher object is initialized, it loses all * previously-acquired state. In other words, initializing a Cipher is * equivalent to creating a new instance of that Cipher and initializing * it. * * @param opmode the operation mode of this cipher (this is one of * the following: * ENCRYPT_MODE, DECRYPT_MODE, * WRAP_MODE or UNWRAP_MODE) * @param key the encryption key * @param params the algorithm parameters * @param random the source of randomness * * @exception InvalidKeyException if the given key is inappropriate for * initializing this cipher * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this cipher, * or if this cipher is being initialized for decryption and requires * algorithm parameters and params is null. */ protected abstract void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, are processed, * and the result is stored in a new buffer. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * * @return the new buffer with the result, or null if the underlying * cipher is a block cipher and the input data is too short to result in a * new block. */ protected abstract byte[] engineUpdate(byte[] input, int inputOffset, int inputLen); /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, are processed, * and the result is stored in the output buffer, starting at * outputOffset inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception ShortBufferException if the given output buffer is too small * to hold the result */ protected abstract int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException; /** * Continues a multiple-part encryption or decryption operation * (depending on how this cipher was initialized), processing another data * part. * *

All input.remaining() bytes starting at * input.position() are processed. The result is stored * in the output buffer. * Upon return, the input buffer's position will be equal * to its limit; its limit will not have changed. The output buffer's * position will have advanced by n, where n is the value returned * by this method; the output buffer's limit will not have changed. * *

If output.remaining() bytes are insufficient to * hold the result, a ShortBufferException is thrown. * *

Subclasses should consider overriding this method if they can * process ByteBuffers more efficiently than byte arrays. * * @param input the input ByteBuffer * @param output the output ByteByffer * * @return the number of bytes stored in output * * @exception ShortBufferException if there is insufficient space in the * output buffer * * @throws NullPointerException if either parameter is null * @since 1.5 */ protected int engineUpdate(ByteBuffer input, ByteBuffer output) throws ShortBufferException { try { return bufferCrypt(input, output, true); } catch (IllegalBlockSizeException e) { // never thrown for engineUpdate() throw new ProviderException("Internal error in update()"); } catch (BadPaddingException e) { // never thrown for engineUpdate() throw new ProviderException("Internal error in update()"); } } /** * Encrypts or decrypts data in a single-part operation, * or finishes a multiple-part operation. * The data is encrypted or decrypted, depending on how this cipher was * initialized. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, and any input * bytes that may have been buffered during a previous update * operation, are processed, with padding (if requested) being applied. * The result is stored in a new buffer. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to * engineInit. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * engineInit) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * * @return the new buffer with the result * * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ protected abstract byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException; /** * Encrypts or decrypts data in a single-part operation, * or finishes a multiple-part operation. * The data is encrypted or decrypted, depending on how this cipher was * initialized. * *

The first inputLen bytes in the input * buffer, starting at inputOffset inclusive, and any input * bytes that may have been buffered during a previous update * operation, are processed, with padding (if requested) being applied. * The result is stored in the output buffer, starting at * outputOffset inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to * engineInit. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * engineInit) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * * @param input the input buffer * @param inputOffset the offset in input where the input * starts * @param inputLen the input length * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception ShortBufferException if the given output buffer is too small * to hold the result * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes */ protected abstract int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException; /** * Encrypts or decrypts data in a single-part operation, * or finishes a multiple-part operation. * The data is encrypted or decrypted, depending on how this cipher was * initialized. * *

All input.remaining() bytes starting at * input.position() are processed. The result is stored * in the output buffer. * Upon return, the input buffer's position will be equal * to its limit; its limit will not have changed. The output buffer's * position will have advanced by n, where n is the value returned * by this method; the output buffer's limit will not have changed. * *

If output.remaining() bytes are insufficient to * hold the result, a ShortBufferException is thrown. * *

Upon finishing, this method resets this cipher object to the state * it was in when previously initialized via a call to * engineInit. * That is, the object is reset and available to encrypt or decrypt * (depending on the operation mode that was specified in the call to * engineInit) more data. * *

Note: if any exception is thrown, this cipher object may need to * be reset before it can be used again. * *

Subclasses should consider overriding this method if they can * process ByteBuffers more efficiently than byte arrays. * * @param input the input ByteBuffer * @param output the output ByteByffer * * @return the number of bytes stored in output * * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested (only in encryption mode), and the total * input length of the data processed by this cipher is not a multiple of * block size; or if this encryption algorithm is unable to * process the input data provided. * @exception ShortBufferException if there is insufficient space in the * output buffer * @exception BadPaddingException if this cipher is in decryption mode, * and (un)padding has been requested, but the decrypted data is not * bounded by the appropriate padding bytes * * @throws NullPointerException if either parameter is null * @since 1.5 */ protected int engineDoFinal(ByteBuffer input, ByteBuffer output) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { return bufferCrypt(input, output, false); } // copied from sun.security.jca.JCAUtil // will be changed to reference that method once that code has been // integrated and promoted static int getTempArraySize(int totalSize) { return Math.min(4096, totalSize); } /** * Implementation for encryption using ByteBuffers. Used for both * engineUpdate() and engineDoFinal(). */ private int bufferCrypt(ByteBuffer input, ByteBuffer output, boolean isUpdate) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { if ((input == null) || (output == null)) { throw new NullPointerException ("Input and output buffers must not be null"); } int inPos = input.position(); int inLimit = input.limit(); int inLen = inLimit - inPos; if (isUpdate && (inLen == 0)) { return 0; } int outLenNeeded = engineGetOutputSize(inLen); if (output.remaining() < outLenNeeded) { throw new ShortBufferException("Need at least " + outLenNeeded + " bytes of space in output buffer"); } boolean a1 = input.hasArray(); boolean a2 = output.hasArray(); if (a1 && a2) { byte[] inArray = input.array(); int inOfs = input.arrayOffset() + inPos; byte[] outArray = output.array(); int outPos = output.position(); int outOfs = output.arrayOffset() + outPos; int n; if (isUpdate) { n = engineUpdate(inArray, inOfs, inLen, outArray, outOfs); } else { n = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs); } input.position(inLimit); output.position(outPos + n); return n; } else if (!a1 && a2) { int outPos = output.position(); byte[] outArray = output.array(); int outOfs = output.arrayOffset() + outPos; byte[] inArray = new byte[getTempArraySize(inLen)]; int total = 0; while (inLen > 0) { int chunk = Math.min(inLen, inArray.length); input.get(inArray, 0, chunk); int n; if (isUpdate || (inLen != chunk)) { n = engineUpdate(inArray, 0, chunk, outArray, outOfs); } else { n = engineDoFinal(inArray, 0, chunk, outArray, outOfs); } total += n; outOfs += n; inLen -= chunk; } output.position(outPos + total); return total; } else { // output is not backed by an accessible byte[] byte[] inArray; int inOfs; if (a1) { inArray = input.array(); inOfs = input.arrayOffset() + inPos; } else { inArray = new byte[getTempArraySize(inLen)]; inOfs = 0; } byte[] outArray = new byte[getTempArraySize(outLenNeeded)]; int outSize = outArray.length; int total = 0; boolean resized = false; while (inLen > 0) { int chunk = Math.min(inLen, outSize); if ((a1 == false) && (resized == false)) { input.get(inArray, 0, chunk); inOfs = 0; } try { int n; if (isUpdate || (inLen != chunk)) { n = engineUpdate(inArray, inOfs, chunk, outArray, 0); } else { n = engineDoFinal(inArray, inOfs, chunk, outArray, 0); } resized = false; inOfs += chunk; inLen -= chunk; output.put(outArray, 0, n); total += n; } catch (ShortBufferException e) { if (resized) { // we just resized the output buffer, but it still // did not work. Bug in the provider, abort throw (ProviderException)new ProviderException ("Could not determine buffer size").initCause(e); } // output buffer is too small, realloc and try again resized = true; int newOut = engineGetOutputSize(chunk); outArray = new byte[newOut]; } } input.position(inLimit); return total; } } /** * Wrap a key. * *

This concrete method has been added to this previously-defined * abstract class. (For backwards compatibility, it cannot be abstract.) * It may be overridden by a provider to wrap a key. * Such an override is expected to throw an IllegalBlockSizeException or * InvalidKeyException (under the specified circumstances), * if the given key cannot be wrapped. * If this method is not overridden, it always throws an * UnsupportedOperationException. * * @param key the key to be wrapped. * * @return the wrapped key. * * @exception IllegalBlockSizeException if this cipher is a block cipher, * no padding has been requested, and the length of the encoding of the * key to be wrapped is not a multiple of the block size. * * @exception InvalidKeyException if it is impossible or unsafe to * wrap the key with this cipher (e.g., a hardware protected key is * being passed to a software-only cipher). */ protected byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { throw new UnsupportedOperationException(); } /** * Unwrap a previously wrapped key. * *

This concrete method has been added to this previously-defined * abstract class. (For backwards compatibility, it cannot be abstract.) * It may be overridden by a provider to unwrap a previously wrapped key. * Such an override is expected to throw an InvalidKeyException if * the given wrapped key cannot be unwrapped. * If this method is not overridden, it always throws an * UnsupportedOperationException. * * @param wrappedKey the key to be unwrapped. * * @param wrappedKeyAlgorithm the algorithm associated with the wrapped * key. * * @param wrappedKeyType the type of the wrapped key. This is one of * SECRET_KEY, PRIVATE_KEY, or * PUBLIC_KEY. * * @return the unwrapped key. * * @exception NoSuchAlgorithmException if no installed providers * can create keys of type wrappedKeyType for the * wrappedKeyAlgorithm. * * @exception InvalidKeyException if wrappedKey does not * represent a wrapped key of type wrappedKeyType for * the wrappedKeyAlgorithm. */ protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { throw new UnsupportedOperationException(); } /** * Returns the key size of the given key object in bits. *

This concrete method has been added to this previously-defined * abstract class. It throws an UnsupportedOperationException * if it is not overridden by the provider. * * @param key the key object. * * @return the key size of the given key object. * * @exception InvalidKeyException if key is invalid. */ protected int engineGetKeySize(Key key) throws InvalidKeyException { throw new UnsupportedOperationException(); } } clean-crypto-1/src/main/java/javax/crypto/CryptoAllPermission.java0000664000175000017500000001217011370332423025407 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.util.Enumeration; import java.util.Vector; /** * The CryptoAllPermission is a permission that implies * any other crypto permissions. *

* * @see java.security.Permission * @see java.security.AllPermission * * @author Sharon Liu * @since 1.4 */ final class CryptoAllPermission extends CryptoPermission { private static final long serialVersionUID = -5066513634293192112L; // This class is similar to java.security.AllPermission. static final String ALG_NAME = "CryptoAllPermission"; static final CryptoAllPermission INSTANCE = new CryptoAllPermission(); private CryptoAllPermission() { super(ALG_NAME); } /** * Checks if the specified permission is implied by * this object. * * @param p the permission to check against. * * @return true if the specified permission is an * instance of CryptoPermission. */ public boolean implies(Permission p) { return (p instanceof CryptoPermission); } /** * Checks two CryptoAllPermission objects for equality. * Two CryptoAllPermission objects are always equal. * * @param obj the object to test for equality with this object. * * @return true if obj is a CryptoAllPermission object. */ public boolean equals(Object obj) { return (obj == INSTANCE); } /** * * Returns the hash code value for this object. * * @return a hash code value for this object. */ public int hashCode() { return 1; } /** * Returns a new PermissionCollection object for storing * CryptoAllPermission objects. *

* * @return a new PermissionCollection object suitable for * storing CryptoAllPermissions. */ public PermissionCollection newPermissionCollection() { return new CryptoAllPermissionCollection(); } } /** * A CryptoAllPermissionCollection stores a collection * of CryptoAllPermission permissions. * * @see java.security.Permission * @see java.security.Permissions * @see javax.crypto.CryptoPermission * * @author Sharon Liu */ final class CryptoAllPermissionCollection extends PermissionCollection implements java.io.Serializable { private static final long serialVersionUID = 7450076868380144072L; // true if a CryptoAllPermission has been added private boolean all_allowed; /** * Create an empty CryptoAllPermissions object. */ CryptoAllPermissionCollection() { all_allowed = false; } /** * Adds a permission to the CryptoAllPermissions. * * @param permission the Permission object to add. * * @exception SecurityException - if this CryptoAllPermissionCollection * object has been marked readonly */ public void add(Permission permission) { if (isReadOnly()) throw new SecurityException("attempt to add a Permission to " + "a readonly PermissionCollection"); if (permission != CryptoAllPermission.INSTANCE) return; all_allowed = true; } /** * Check and see if this set of permissions implies the permissions * expressed in "permission". * * @param p the Permission object to compare * * @return true if the given permission is implied by this * CryptoAllPermissionCollection. */ public boolean implies(Permission permission) { if (!(permission instanceof CryptoPermission)) { return false; } return all_allowed; } /** * Returns an enumeration of all the CryptoAllPermission * objects in the container. * * @return an enumeration of all the CryptoAllPermission objects. */ public Enumeration elements() { Vector v = new Vector(1); if (all_allowed) v.add(CryptoAllPermission.INSTANCE); return v.elements(); } } clean-crypto-1/src/main/java/javax/crypto/CryptoPermission.java0000664000175000017500000004126111370332423024761 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.security.spec.AlgorithmParameterSpec; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import javax.crypto.spec.*; /** * The CryptoPermission class extends the * java.security.Permission class. A * CryptoPermission object is used to represent * the ability of an application/applet to use certain * algorithms with certain key sizes and other * restrictions in certain environments.

* * @see java.security.Permission * * @author Jan Luehe * @author Sharon Liu * @since 1.4 */ class CryptoPermission extends java.security.Permission { private static final long serialVersionUID = 8987399626114087514L; private String alg; private int maxKeySize = Integer.MAX_VALUE; // no restriction on maxKeySize private String exemptionMechanism = null; private AlgorithmParameterSpec algParamSpec = null; private boolean checkParam = false; // no restriction on param static final String ALG_NAME_WILDCARD = "*"; /** * Constructor that takes an algorithm name. * * This constructor implies that the given algorithm can be * used without any restrictions. * * @param alg the algorithm name. */ CryptoPermission(String alg) { super(null); this.alg = alg; } /** * Constructor that takes an algorithm name and a maximum * key size. * * This constructor implies that the given algorithm can be * used with a key size up to maxKeySize. * * @param alg the algorithm name. * * @param maxKeySize the maximum allowable key size, * specified in number of bits. */ CryptoPermission(String alg, int maxKeySize) { super(null); this.alg = alg; this.maxKeySize = maxKeySize; } /** * Constructor that takes an algorithm name, a maximum * key size, and an AlgorithmParameterSpec object. * * This constructor implies that the given algorithm can be * used with a key size up to maxKeySize, and * algorithm * parameters up to the limits set in algParamSpec. * * @param alg the algorithm name. * * @param maxKeySize the maximum allowable key size, * specified in number of bits. * * @param algParamSpec the limits for allowable algorithm * parameters. */ CryptoPermission(String alg, int maxKeySize, AlgorithmParameterSpec algParamSpec) { super(null); this.alg = alg; this.maxKeySize = maxKeySize; this.checkParam = true; this.algParamSpec = algParamSpec; } /** * Constructor that takes an algorithm name and the name of * an exemption mechanism. * * This constructor implies that the given algorithm can be * used without any key size or algorithm parameter restrictions * provided that the specified exemption mechanism is enforced. * * @param alg the algorithm name. * * @param exemptionMechanism the name of the exemption mechanism. */ CryptoPermission(String alg, String exemptionMechanism) { super(null); this.alg = alg; this.exemptionMechanism = exemptionMechanism; } /** * Constructor that takes an algorithm name, a maximum key * size, and the name of an exemption mechanism. * * This constructor implies that the given algorithm can be * used with a key size up to maxKeySize * provided that the * specified exemption mechanism is enforced. * * @param alg the algorithm name. * @param maxKeySize the maximum allowable key size, * specified in number of bits. * @param exemptionMechanism the name of the exemption * mechanism. */ CryptoPermission(String alg, int maxKeySize, String exemptionMechanism) { super(null); this.alg = alg; this.exemptionMechanism = exemptionMechanism; this.maxKeySize = maxKeySize; } /** * Constructor that takes an algorithm name, a maximum key * size, the name of an exemption mechanism, and an * AlgorithmParameterSpec object. * * This constructor implies that the given algorithm can be * used with a key size up to maxKeySize * and algorithm * parameters up to the limits set in algParamSpec * provided that * the specified exemption mechanism is enforced. * * @param alg the algorithm name. * @param maxKeySize the maximum allowable key size, * specified in number of bits. * @param algParamSpec the limit for allowable algorithm * parameter spec. * @param exemptionMechanism the name of the exemption * mechanism. */ CryptoPermission(String alg, int maxKeySize, AlgorithmParameterSpec algParamSpec, String exemptionMechanism) { super(null); this.alg = alg; this.exemptionMechanism = exemptionMechanism; this.maxKeySize = maxKeySize; this.checkParam = true; this.algParamSpec = algParamSpec; } /** * Checks if the specified permission is "implied" by * this object. *

* More specifically, this method returns true if:

*

    *
  • p is an instance of CryptoPermission, and

    *

  • p's algorithm name equals or (in the case of wildcards) * is implied by this permission's algorithm name, and

    *

  • p's maximum allowable key size is less or * equal to this permission's maximum allowable key size, and

    *

  • p's algorithm parameter spec equals or is * implied by this permission's algorithm parameter spec, and

    *

  • p's exemptionMechanism equals or * is implied by this permission's * exemptionMechanism (a null exemption mechanism * implies any other exemption mechanism). *
* * @param p the permission to check against. * * @return true if the specified permission is equal to or * implied by this permission, false otherwise. */ public boolean implies(Permission p) { if (!(p instanceof CryptoPermission)) return false; CryptoPermission cp = (CryptoPermission)p; if ((!alg.equalsIgnoreCase(cp.alg)) && (!alg.equalsIgnoreCase(ALG_NAME_WILDCARD))) { return false; } // alg is the same as cp's alg or // alg is a wildcard. if (cp.maxKeySize <= this.maxKeySize) { // check algParamSpec. if (!impliesParameterSpec(cp.checkParam, cp.algParamSpec)) { return false; } // check exemptionMechanism. if (impliesExemptionMechanism(cp.exemptionMechanism)) { return true; } } return false; } /** * Checks two CryptoPermission objects for equality. Checks that * obj is a CryptoPermission, and has the same * algorithm name, * exemption mechanism name, maximum allowable key size and * algorithm parameter spec * as this object. *

* @param obj the object to test for equality with this object. * @return true if obj is equal to this object. */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof CryptoPermission)) return false; CryptoPermission that = (CryptoPermission) obj; if (!(alg.equalsIgnoreCase(that.alg)) || (maxKeySize != that.maxKeySize)) { return false; } if (this.checkParam != that.checkParam) { return false; } return (equalObjects(this.exemptionMechanism, that.exemptionMechanism) && equalObjects(this.algParamSpec, that.algParamSpec)); } /** * Returns the hash code value for this object. * * @return a hash code value for this object. */ public int hashCode() { int retval = alg.hashCode(); retval ^= maxKeySize; if (exemptionMechanism != null) { retval ^= exemptionMechanism.hashCode(); } if (checkParam) retval ^= 100; if (algParamSpec != null) { retval ^= algParamSpec.hashCode(); } return retval; } /** * There is no action defined for a CryptoPermission * onject. */ public String getActions() { return null; } /** * Returns a new PermissionCollection object for storing * CryptoPermission objects. * * @return a new PermissionCollection object suitable for storing * CryptoPermissions. */ public PermissionCollection newPermissionCollection() { return new CryptoPermissionCollection(); } /** * Returns the algorithm name associated with * this CryptoPermission object. */ final String getAlgorithm() { return alg; } /** * Returns the exemption mechanism name * associated with this CryptoPermission * object. */ final String getExemptionMechanism() { return exemptionMechanism; } /** * Returns the maximum allowable key size associated * with this CryptoPermission object. */ final int getMaxKeySize() { return maxKeySize; } /** * Returns true if there is a limitation on the * AlgorithmParameterSpec associated with this * CryptoPermission object and false if otherwise. */ final boolean getCheckParam() { return checkParam; } /** * Returns the AlgorithmParameterSpec * associated with this CryptoPermission * object. */ final AlgorithmParameterSpec getAlgorithmParameterSpec() { return algParamSpec; } /** * Returns a string describing this CryptoPermission. The convention is to * specify the class name, the algorithm name, the maximum allowable * key size, and the name of the exemption mechanism, in the following * format: '("ClassName" "algorithm" "keysize" "exemption_mechanism")'. * * @return information about this CryptoPermission. */ public String toString() { StringBuilder buf = new StringBuilder(100); buf.append("(CryptoPermission " + alg + " " + maxKeySize); if (algParamSpec != null) { if (algParamSpec instanceof RC2ParameterSpec) { buf.append(" , effective " + ((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits()); } else if (algParamSpec instanceof RC5ParameterSpec) { buf.append(" , rounds " + ((RC5ParameterSpec)algParamSpec).getRounds()); } } if (exemptionMechanism != null) { // OPTIONAL buf.append(" " + exemptionMechanism); } buf.append(")"); return buf.toString(); } private boolean impliesExemptionMechanism(String exemptionMechanism) { if (this.exemptionMechanism == null) { return true; } if (exemptionMechanism == null) { return false; } if (this.exemptionMechanism.equals(exemptionMechanism)) { return true; } return false; } private boolean impliesParameterSpec(boolean checkParam, AlgorithmParameterSpec algParamSpec) { if ((this.checkParam) && checkParam) { if (algParamSpec == null) { return true; } else if (this.algParamSpec == null) { return false; } if (this.algParamSpec.getClass() != algParamSpec.getClass()) { return false; } if (algParamSpec instanceof RC2ParameterSpec) { if (((RC2ParameterSpec)algParamSpec).getEffectiveKeyBits() <= ((RC2ParameterSpec) (this.algParamSpec)).getEffectiveKeyBits()) { return true; } } if (algParamSpec instanceof RC5ParameterSpec) { if (((RC5ParameterSpec)algParamSpec).getRounds() <= ((RC5ParameterSpec)this.algParamSpec).getRounds()) { return true; } } if (algParamSpec instanceof PBEParameterSpec) { if (((PBEParameterSpec)algParamSpec).getIterationCount() <= ((PBEParameterSpec)this.algParamSpec).getIterationCount()) { return true; } } // For classes we don't know, the following // may be the best try. if (this.algParamSpec.equals(algParamSpec)) { return true; } return false; } else if (this.checkParam) { return false; } else { return true; } } private boolean equalObjects(Object obj1, Object obj2) { if (obj1 == null) { return (obj2 == null ? true : false); } return obj1.equals(obj2); } } /** * A CryptoPermissionCollection stores a set of CryptoPermission * permissions. * * @see java.security.Permission * @see java.security.Permissions * @see java.security.PermissionCollection * * @author Sharon Liu */ final class CryptoPermissionCollection extends PermissionCollection implements Serializable { private static final long serialVersionUID = -511215555898802763L; private Vector permissions; /** * Creates an empty CryptoPermissionCollection * object. */ CryptoPermissionCollection() { permissions = new Vector(3); } /** * Adds a permission to the CryptoPermissionCollection. * * @param permission the Permission object to add. * * @exception SecurityException - if this CryptoPermissionCollection * object has been marked readOnly. */ public void add(Permission permission) { if (isReadOnly()) throw new SecurityException("attempt to add a Permission " + "to a readonly PermissionCollection"); if (!(permission instanceof CryptoPermission)) return; permissions.addElement(permission); } /** * Check and see if this CryptoPermission object implies * the given Permission object. * * @param p the Permission object to compare * * @return true if the given permission is implied by this * CryptoPermissionCollection, false if not. */ public boolean implies(Permission permission) { if (!(permission instanceof CryptoPermission)) return false; CryptoPermission cp = (CryptoPermission)permission; Enumeration e = permissions.elements(); while (e.hasMoreElements()) { CryptoPermission x = (CryptoPermission) e.nextElement(); if (x.implies(cp)) { return true; } } return false; } /** * Returns an enumeration of all the CryptoPermission objects * in the container. * * @return an enumeration of all the CryptoPermission objects. */ public Enumeration elements() { return permissions.elements(); } } clean-crypto-1/src/main/java/javax/crypto/CryptoPermissions.java0000664000175000017500000003761311370332423025152 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.util.NoSuchElementException; import java.io.Serializable; import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; /** * This class contains CryptoPermission objects, organized into * PermissionCollections according to algorithm names. * *

When the add method is called to add a * CryptoPermission, the CryptoPermission is stored in the * appropriate PermissionCollection. If no such * collection exists yet, the algorithm name associated with * the CryptoPermission object is * determined and the newPermissionCollection method * is called on the CryptoPermission or CryptoAllPermission class to * create the PermissionCollection and add it to the Permissions object. * * @see javax.crypto.CryptoPermission * @see java.security.PermissionCollection * @see java.security.Permissions * * @author Sharon Liu * @since 1.4 */ final class CryptoPermissions extends PermissionCollection implements Serializable { private static final long serialVersionUID = 4946547168093391015L; // This class is similar to java.security.Permissions private Hashtable perms; /** * Creates a new CryptoPermissions object containing * no CryptoPermissionCollections. */ CryptoPermissions() { perms = new Hashtable(7); } /** * Populates the crypto policy from the specified * InputStream into this CryptoPermissions object. * * @param in the InputStream to load from. * * @exception SecurityException if cannot load * successfully. */ void load(InputStream in) throws IOException, CryptoPolicyParser.ParsingException { CryptoPolicyParser parser = new CryptoPolicyParser(); parser.read(new BufferedReader(new InputStreamReader(in, "UTF-8"))); CryptoPermission[] parsingResult = parser.getPermissions(); for (int i = 0; i < parsingResult.length; i++) { this.add(parsingResult[i]); } } /** * Returns true if this CryptoPermissions object doesn't * contain any CryptoPermission objects; otherwise, returns * false. */ boolean isEmpty() { return perms.isEmpty(); } /** * Adds a permission object to the PermissionCollection for the * algorithm returned by * (CryptoPermission)permission.getAlgorithm(). * * This method creates * a new PermissionCollection object (and adds the permission to it) * if an appropriate collection does not yet exist.

* * @param permission the Permission object to add. * * @exception SecurityException if this CryptoPermissions object is * marked as readonly. * * @see isReadOnly */ public void add(Permission permission) { if (isReadOnly()) throw new SecurityException("Attempt to add a Permission " + "to a readonly CryptoPermissions " + "object"); if (!(permission instanceof CryptoPermission)) return; CryptoPermission cryptoPerm = (CryptoPermission)permission; PermissionCollection pc = getPermissionCollection(cryptoPerm); pc.add(cryptoPerm); String alg = cryptoPerm.getAlgorithm(); if (!perms.containsKey(alg)) { perms.put(alg, pc); } } /** * Checks if this object's PermissionCollection for permissons * of the specified permission's algorithm implies the specified * permission. Returns true if the checking succeeded. * * @param permission the Permission object to check. * * @return true if "permission" is implied by the permissions * in the PermissionCollection it belongs to, false if not. * */ public boolean implies(Permission permission) { if (!(permission instanceof CryptoPermission)) { return false; } CryptoPermission cryptoPerm = (CryptoPermission)permission; PermissionCollection pc = getPermissionCollection(cryptoPerm.getAlgorithm()); return pc.implies(cryptoPerm); } /** * Returns an enumeration of all the Permission objects in all the * PermissionCollections in this CryptoPermissions object. * * @return an enumeration of all the Permissions. */ public Enumeration elements() { // go through each Permissions in the hash table // and call their elements() function. return new PermissionsEnumerator(perms.elements()); } /** * Returns a CryptoPermissions object which * represents the minimum of the specified * CryptoPermissions object and this * CryptoPermissions object. * * @param other the CryptoPermission * object to compare with this object. */ CryptoPermissions getMinimum(CryptoPermissions other) { if (other == null) { return null; } if (this.perms.containsKey(CryptoAllPermission.ALG_NAME)) { return other; } if (other.perms.containsKey(CryptoAllPermission.ALG_NAME)) { return this; } CryptoPermissions ret = new CryptoPermissions(); PermissionCollection thatWildcard = (PermissionCollection)other.perms.get( CryptoPermission.ALG_NAME_WILDCARD); int maxKeySize = 0; if (thatWildcard != null) { maxKeySize = ((CryptoPermission) thatWildcard.elements().nextElement()).getMaxKeySize(); } // For each algorithm in this CryptoPermissions, // find out if there is anything we should add into // ret. Enumeration thisKeys = this.perms.keys(); while (thisKeys.hasMoreElements()) { String alg = (String)thisKeys.nextElement(); PermissionCollection thisPc = (PermissionCollection)this.perms.get(alg); PermissionCollection thatPc = (PermissionCollection)other.perms.get(alg); CryptoPermission[] partialResult; if (thatPc == null) { if (thatWildcard == null) { // The other CryptoPermissions // doesn't allow this given // algorithm at all. Just skip this // algorithm. continue; } partialResult = getMinimum(maxKeySize, thisPc); } else { partialResult = getMinimum(thisPc, thatPc); } for (int i = 0; i < partialResult.length; i++) { ret.add(partialResult[i]); } } PermissionCollection thisWildcard = (PermissionCollection)this.perms.get( CryptoPermission.ALG_NAME_WILDCARD); // If this CryptoPermissions doesn't // have a wildcard, we are done. if (thisWildcard == null) { return ret; } // Deal with the algorithms only appear // in the other CryptoPermissions. maxKeySize = ((CryptoPermission) thisWildcard.elements().nextElement()).getMaxKeySize(); Enumeration thatKeys = other.perms.keys(); while (thatKeys.hasMoreElements()) { String alg = (String)thatKeys.nextElement(); if (this.perms.containsKey(alg)) { continue; } PermissionCollection thatPc = (PermissionCollection)other.perms.get(alg); CryptoPermission[] partialResult; partialResult = getMinimum(maxKeySize, thatPc); for (int i = 0; i < partialResult.length; i++) { ret.add(partialResult[i]); } } return ret; } /** * Get the minimum of the two given PermissionCollection * thisPc and thatPc. * * @param thisPc the first given PermissionColloection * object. * * @param thatPc the second given PermissionCollection * object. */ private CryptoPermission[] getMinimum(PermissionCollection thisPc, PermissionCollection thatPc) { Vector permVector = new Vector(2); Enumeration thisPcPermissions = thisPc.elements(); // For each CryptoPermission in // thisPc object, do the following: // 1) if this CryptoPermission is implied // by thatPc, this CryptoPermission // should be returned, and we can // move on to check the next // CryptoPermission in thisPc. // 2) otherwise, we should return // all CryptoPermissions in thatPc // which // are implied by this CryptoPermission. // Then we can move on to the // next CryptoPermission in thisPc. while (thisPcPermissions.hasMoreElements()) { CryptoPermission thisCp = (CryptoPermission)thisPcPermissions.nextElement(); Enumeration thatPcPermissions = thatPc.elements(); while (thatPcPermissions.hasMoreElements()) { CryptoPermission thatCp = (CryptoPermission)thatPcPermissions.nextElement(); if (thatCp.implies(thisCp)) { permVector.addElement(thisCp); break; } if (thisCp.implies(thatCp)) { permVector.addElement(thatCp); } } } CryptoPermission[] ret = new CryptoPermission[permVector.size()]; permVector.copyInto(ret); return ret; } /** * Returns all the CryptoPermission objects in the given * PermissionCollection object * whose maximum keysize no greater than maxKeySize. * For all CryptoPermission objects with a maximum keysize greater * than maxKeySize, this method constructs a * corresponding CryptoPermission object whose maximum keysize is * set to maxKeySize, and includes that in the result. * * @param maxKeySize the given maximum key size. * * @param pc the given PermissionCollection object. */ private CryptoPermission[] getMinimum(int maxKeySize, PermissionCollection pc) { Vector permVector = new Vector(1); Enumeration enum_ = pc.elements(); while (enum_.hasMoreElements()) { CryptoPermission cp = (CryptoPermission)enum_.nextElement(); if (cp.getMaxKeySize() <= maxKeySize) { permVector.addElement(cp); } else { if (cp.getCheckParam()) { permVector.addElement( new CryptoPermission(cp.getAlgorithm(), maxKeySize, cp.getAlgorithmParameterSpec(), cp.getExemptionMechanism())); } else { permVector.addElement( new CryptoPermission(cp.getAlgorithm(), maxKeySize, cp.getExemptionMechanism())); } } } CryptoPermission[] ret = new CryptoPermission[permVector.size()]; permVector.copyInto(ret); return ret; } /** * Returns the PermissionCollection for the * specified algorithm. Returns null if there * isn't such a PermissionCollection. * * @param alg the algorithm name. */ PermissionCollection getPermissionCollection(String alg) { // If this CryptoPermissions includes CryptoAllPermission, // we should return CryptoAllPermission. if (perms.containsKey(CryptoAllPermission.ALG_NAME)) { return (PermissionCollection)(perms.get(CryptoAllPermission.ALG_NAME)); } PermissionCollection pc = (PermissionCollection)perms.get(alg); // If there isn't a PermissionCollection for // the given algorithm,we should return the // PermissionCollection for the wildcard // if there is one. if (pc == null) { pc = (PermissionCollection)perms.get( CryptoPermission.ALG_NAME_WILDCARD); } return pc; } /** * Returns the PermissionCollection for the algorithm * associated with the specified CryptoPermission * object. Creates such a PermissionCollection * if such a PermissionCollection does not * exist yet. * * @param cryptoPerm the CryptoPermission object. */ private PermissionCollection getPermissionCollection( CryptoPermission cryptoPerm) { String alg = cryptoPerm.getAlgorithm(); PermissionCollection pc = (PermissionCollection)perms.get(alg); if (pc == null) { pc = cryptoPerm.newPermissionCollection(); } return pc; } } final class PermissionsEnumerator implements Enumeration { // all the perms private Enumeration perms; // the current set private Enumeration permset; PermissionsEnumerator(Enumeration e) { perms = e; permset = getNextEnumWithMore(); } public synchronized boolean hasMoreElements() { // if we enter with permissionimpl null, we know // there are no more left. if (permset == null) return false; // try to see if there are any left in the current one if (permset.hasMoreElements()) return true; // get the next one that has something in it... permset = getNextEnumWithMore(); // if it is null, we are done! return (permset != null); } public synchronized Object nextElement() { // hasMoreElements will update permset to the next permset // with something in it... if (hasMoreElements()) { return permset.nextElement(); } else { throw new NoSuchElementException("PermissionsEnumerator"); } } private Enumeration getNextEnumWithMore() { while (perms.hasMoreElements()) { PermissionCollection pc = (PermissionCollection) perms.nextElement(); Enumeration next = pc.elements(); if (next.hasMoreElements()) return next; } return null; } } clean-crypto-1/src/main/java/javax/crypto/CryptoPolicyParser.java0000664000175000017500000005404211370332423025246 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.io.*; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.util.StringTokenizer; import static java.util.Locale.ENGLISH; import java.security.GeneralSecurityException; import java.security.spec.AlgorithmParameterSpec; import java.lang.reflect.*; /** * JCE has two pairs of jurisdiction policy files: one represents U.S. export * laws, and the other represents the local laws of the country where the * JCE will be used. * * The jurisdiction policy file has the same syntax as JDK policy files except * that JCE has new permission classes called javax.crypto.CryptoPermission * and javax.crypto.CryptoAllPermission. * * The format of a permission entry in the jurisdiction policy file is: * * permission [, * [[, ][, * [, , ]]]]; * * @author Sharon Liu * * @see java.security.Permissions * @see java.security.spec.AlgrithomParameterSpec * @see javax.crypto.CryptoPermission * @see javax.crypto.CryptoAllPermission * @see javax.crypto.CryptoPermissions * @since 1.4 */ final class CryptoPolicyParser { private Vector grantEntries; // Convenience variables for parsing private StreamTokenizer st; private int lookahead; /** * Creates a CryptoPolicyParser object. */ CryptoPolicyParser() { grantEntries = new Vector(); } /** * Reads a policy configuration using a Reader object.

* * @param policy the policy Reader object. * * @exception ParsingException if the policy configuration * contains a syntax error. * * @exception IOException if an error occurs while reading * the policy configuration. */ void read(Reader policy) throws ParsingException, IOException { if (!(policy instanceof BufferedReader)) { policy = new BufferedReader(policy); } /* * Configure the stream tokenizer: * Recognize strings between "..." * Don't convert words to lowercase * Recognize both C-style and C++-style comments * Treat end-of-line as white space, not as a token */ st = new StreamTokenizer(policy); st.resetSyntax(); st.wordChars('a', 'z'); st.wordChars('A', 'Z'); st.wordChars('.', '.'); st.wordChars('0', '9'); st.wordChars('_', '_'); st.wordChars('$', '$'); st.wordChars(128 + 32, 255); st.whitespaceChars(0, ' '); st.commentChar('/'); st.quoteChar('\''); st.quoteChar('"'); st.lowerCaseMode(false); st.ordinaryChar('/'); st.slashSlashComments(true); st.slashStarComments(true); st.parseNumbers(); /* * The crypto jurisdiction policy must be consistent. The * following hashtable is used for checking consistency. */ Hashtable processedPermissions = null; /* * The main parsing loop. The loop is executed once for each entry * in the policy file. The entries are delimited by semicolons. Once * we've read in the information for an entry, go ahead and try to * add it to the grantEntries. */ lookahead = st.nextToken(); while (lookahead != StreamTokenizer.TT_EOF) { if (peek("grant")) { GrantEntry ge = parseGrantEntry(processedPermissions); if (ge != null) grantEntries.addElement(ge); } else { throw new ParsingException(st.lineno(), "expected grant " + "statement"); } match(";"); } } /** * parse a Grant entry */ private GrantEntry parseGrantEntry(Hashtable processedPermissions) throws ParsingException, IOException { GrantEntry e = new GrantEntry(); match("grant"); match("{"); while(!peek("}")) { if (peek("Permission")) { CryptoPermissionEntry pe = parsePermissionEntry(processedPermissions); e.add(pe); match(";"); } else { throw new ParsingException(st.lineno(), "expected permission entry"); } } match("}"); return e; } /** * parse a CryptoPermission entry */ private CryptoPermissionEntry parsePermissionEntry( Hashtable processedPermissions) throws ParsingException, IOException { CryptoPermissionEntry e = new CryptoPermissionEntry(); match("Permission"); e.cryptoPermission = match("permission type"); if (e.cryptoPermission.equals("javax.crypto.CryptoAllPermission")) { // Done with the CryptoAllPermission entry. e.alg = CryptoAllPermission.ALG_NAME; e.maxKeySize = Integer.MAX_VALUE; return e; } // Should see the algorithm name. if (peek("\"")) { // Algorithm name - always convert to upper case after parsing. e.alg = match("quoted string").toUpperCase(ENGLISH); } else { // The algorithm name can be a wildcard. if (peek("*")) { match("*"); e.alg = CryptoPermission.ALG_NAME_WILDCARD; } else { throw new ParsingException(st.lineno(), "Missing the algorithm name"); } } peekAndMatch(","); // May see the exemption mechanism name. if (peek("\"")) { // Exemption mechanism name - convert to upper case too. e.exemptionMechanism = match("quoted string").toUpperCase(ENGLISH); } peekAndMatch(","); // Check whether this entry is consistent with other permission entries // that have been read. if (!isConsistent(e.alg, e.exemptionMechanism, processedPermissions)) { throw new ParsingException(st.lineno(), "Inconsistent policy"); } // Should see the maxKeySize if not at the end of this entry yet. if (peek("number")) { e.maxKeySize = match(); } else { if (peek("*")) { match("*"); e.maxKeySize = Integer.MAX_VALUE; } else { if (!peek(";")) { throw new ParsingException(st.lineno(), "Missing the maximum " + "allowable key size"); } else { // At the end of this permission entry e.maxKeySize = Integer.MAX_VALUE; } } } peekAndMatch(","); // May see an AlgorithmParameterSpec class name. if (peek("\"")) { // AlgorithmParameterSpec class name. String algParamSpecClassName = match("quoted string"); Vector paramsV = new Vector(1); while (peek(",")) { match(","); if (peek("number")) { paramsV.addElement(new Integer(match())); } else { if (peek("*")) { match("*"); paramsV.addElement(new Integer(Integer.MAX_VALUE)); } else { throw new ParsingException(st.lineno(), "Expecting an integer"); } } } Integer[] params = new Integer[paramsV.size()]; paramsV.copyInto(params); e.checkParam = true; e.algParamSpec = getInstance(algParamSpecClassName, params); } return e; } private static final AlgorithmParameterSpec getInstance(String type, Integer[] params) throws ParsingException { AlgorithmParameterSpec ret = null; try { Class apsClass = Class.forName(type); Class[] paramClasses = new Class[params.length]; for (int i = 0; i < params.length; i++) { paramClasses[i] = int.class; } Constructor c = apsClass.getConstructor(paramClasses); ret = (AlgorithmParameterSpec) c.newInstance((Object[]) params); } catch (Exception e) { throw new ParsingException("Cannot call the constructor of " + type + e); } return ret; } private boolean peekAndMatch(String expect) throws ParsingException, IOException { if (peek(expect)) { match(expect); return true; } return false; } private boolean peek(String expect) { boolean found = false; switch (lookahead) { case StreamTokenizer.TT_WORD: if (expect.equalsIgnoreCase(st.sval)) found = true; break; case StreamTokenizer.TT_NUMBER: if (expect.equalsIgnoreCase("number")) { found = true; } break; case ',': if (expect.equals(",")) found = true; break; case '{': if (expect.equals("{")) found = true; break; case '}': if (expect.equals("}")) found = true; break; case '"': if (expect.equals("\"")) found = true; break; case '*': if (expect.equals("*")) found = true; break; case ';': if (expect.equals(";")) found = true; break; default: break; } return found; } /** * Excepts to match a non-negative number. */ private int match() throws ParsingException, IOException { int value = -1; int lineno = st.lineno(); String sValue = null; switch (lookahead) { case StreamTokenizer.TT_NUMBER: value = (int)st.nval; if (value < 0) { sValue = String.valueOf(st.nval); } lookahead = st.nextToken(); break; default: sValue = st.sval; break; } if (value <= 0) { throw new ParsingException(lineno, "a non-negative number", sValue); } return value; } private String match(String expect) throws ParsingException, IOException { String value = null; switch (lookahead) { case StreamTokenizer.TT_NUMBER: throw new ParsingException(st.lineno(), expect, "number "+String.valueOf(st.nval)); case StreamTokenizer.TT_EOF: throw new ParsingException("expected "+expect+", read end of file"); case StreamTokenizer.TT_WORD: if (expect.equalsIgnoreCase(st.sval)) { lookahead = st.nextToken(); } else if (expect.equalsIgnoreCase("permission type")) { value = st.sval; lookahead = st.nextToken(); } else throw new ParsingException(st.lineno(), expect, st.sval); break; case '"': if (expect.equalsIgnoreCase("quoted string")) { value = st.sval; lookahead = st.nextToken(); } else if (expect.equalsIgnoreCase("permission type")) { value = st.sval; lookahead = st.nextToken(); } else throw new ParsingException(st.lineno(), expect, st.sval); break; case ',': if (expect.equals(",")) lookahead = st.nextToken(); else throw new ParsingException(st.lineno(), expect, ","); break; case '{': if (expect.equals("{")) lookahead = st.nextToken(); else throw new ParsingException(st.lineno(), expect, "{"); break; case '}': if (expect.equals("}")) lookahead = st.nextToken(); else throw new ParsingException(st.lineno(), expect, "}"); break; case ';': if (expect.equals(";")) lookahead = st.nextToken(); else throw new ParsingException(st.lineno(), expect, ";"); break; case '*': if (expect.equals("*")) lookahead = st.nextToken(); else throw new ParsingException(st.lineno(), expect, "*"); break; default: throw new ParsingException(st.lineno(), expect, new String(new char[] {(char)lookahead})); } return value; } CryptoPermission[] getPermissions() { Vector result = new Vector(); Enumeration grantEnum = grantEntries.elements(); while (grantEnum.hasMoreElements()) { GrantEntry ge = (GrantEntry)grantEnum.nextElement(); Enumeration permEnum = ge.permissionElements(); while (permEnum.hasMoreElements()) { CryptoPermissionEntry pe = (CryptoPermissionEntry)permEnum.nextElement(); if (pe.cryptoPermission.equals( "javax.crypto.CryptoAllPermission")) { result.addElement(CryptoAllPermission.INSTANCE); } else { if (pe.checkParam) { result.addElement(new CryptoPermission( pe.alg, pe.maxKeySize, pe.algParamSpec, pe.exemptionMechanism)); } else { result.addElement(new CryptoPermission( pe.alg, pe.maxKeySize, pe.exemptionMechanism)); } } } } CryptoPermission[] ret = new CryptoPermission[result.size()]; result.copyInto(ret); return ret; } private boolean isConsistent(String alg, String exemptionMechanism, Hashtable processedPermissions) { String thisExemptionMechanism = exemptionMechanism == null ? "none" : exemptionMechanism; if (processedPermissions == null) { processedPermissions = new Hashtable(); Vector exemptionMechanisms = new Vector(1); exemptionMechanisms.addElement(thisExemptionMechanism); processedPermissions.put(alg, exemptionMechanisms); return true; } if (processedPermissions.containsKey(CryptoAllPermission.ALG_NAME)) { return false; } Vector exemptionMechanisms; if (processedPermissions.containsKey(alg)) { exemptionMechanisms = (Vector)processedPermissions.get(alg); if (exemptionMechanisms.contains(thisExemptionMechanism)) { return false; } } else { exemptionMechanisms = new Vector(1); } exemptionMechanisms.addElement(thisExemptionMechanism); processedPermissions.put(alg, exemptionMechanisms); return true; } /** * Each grant entry in the policy configuration file is represented by a * GrantEntry object.

* *

* For example, the entry *

     *      grant {
     *       permission javax.crypto.CryptoPermission "DES", 56;
     *      };
     *
     * 
* is represented internally *
     *
     * pe = new CryptoPermissionEntry("javax.crypto.CryptoPermission",
     *                           "DES", 56);
     *
     * ge = new GrantEntry();
     *
     * ge.add(pe);
     *
     * 
* * @see java.security.Permission * @see javax.crypto.CryptoPermission * @see javax.crypto.CryptoPermissions */ private static class GrantEntry { private Vector permissionEntries; GrantEntry() { permissionEntries = new Vector(); } void add(CryptoPermissionEntry pe) { permissionEntries.addElement(pe); } boolean remove(CryptoPermissionEntry pe) { return permissionEntries.removeElement(pe); } boolean contains(CryptoPermissionEntry pe) { return permissionEntries.contains(pe); } /** * Enumerate all the permission entries in this GrantEntry. */ Enumeration permissionElements(){ return permissionEntries.elements(); } } /** * Each crypto permission entry in the policy configuration file is * represented by a CryptoPermissionEntry object.

* *

* For example, the entry *

     *     permission javax.crypto.CryptoPermission "DES", 56;
     * 
* is represented internally *
     *
     * pe = new CryptoPermissionEntry("javax.crypto.cryptoPermission",
     *                           "DES", 56);
     * 
* * @see java.security.Permissions * @see javax.crypto.CryptoPermission * @see javax.crypto.CryptoAllPermission */ private static class CryptoPermissionEntry { String cryptoPermission; String alg; String exemptionMechanism; int maxKeySize; boolean checkParam; AlgorithmParameterSpec algParamSpec; CryptoPermissionEntry() { // Set default values. maxKeySize = 0; alg = null; exemptionMechanism = null; checkParam = false; algParamSpec = null; } /** * Calculates a hash code value for the object. Objects * which are equal will also have the same hashcode. */ public int hashCode() { int retval = cryptoPermission.hashCode(); if (alg != null) retval ^= alg.hashCode(); if (exemptionMechanism != null) { retval ^= exemptionMechanism.hashCode(); } retval ^= maxKeySize; if (checkParam) retval ^= 100; if (algParamSpec != null) { retval ^= algParamSpec.hashCode(); } return retval; } public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof CryptoPermissionEntry)) return false; CryptoPermissionEntry that = (CryptoPermissionEntry) obj; if (this.cryptoPermission == null) { if (that.cryptoPermission != null) return false; } else { if (!this.cryptoPermission.equals( that.cryptoPermission)) return false; } if (this.alg == null) { if (that.alg != null) return false; } else { if (!this.alg.equalsIgnoreCase(that.alg)) return false; } if (!(this.maxKeySize == that.maxKeySize)) return false; if (this.checkParam != that.checkParam) return false; if (this.algParamSpec == null) { if (that.algParamSpec != null) return false; } else { if (!this.algParamSpec.equals(that.algParamSpec)) return false; } // everything matched -- the 2 objects are equal return true; } } static final class ParsingException extends GeneralSecurityException { private static final long serialVersionUID = 7147241245566588374L; /** * Constructs a ParsingException with the specified * detail message. * @param msg the detail message. */ ParsingException(String msg) { super(msg); } ParsingException(int line, String msg) { super("line " + line + ": " + msg); } ParsingException(int line, String expect, String actual) { super("line "+line+": expected '"+expect+"', found '"+actual+"'"); } } } clean-crypto-1/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java0000664000175000017500000004166211370332423026212 0ustar moellermoeller/* * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.io.*; import java.security.*; import java.security.spec.*; import sun.security.x509.AlgorithmId; import sun.security.util.DerValue; import sun.security.util.DerInputStream; import sun.security.util.DerOutputStream; /** * This class implements the EncryptedPrivateKeyInfo type * as defined in PKCS #8. *

Its ASN.1 definition is as follows: * *

 * EncryptedPrivateKeyInfo ::=  SEQUENCE {
 *     encryptionAlgorithm   AlgorithmIdentifier,
 *     encryptedData   OCTET STRING }
 *
 * AlgorithmIdentifier  ::=  SEQUENCE  {
 *     algorithm              OBJECT IDENTIFIER,
 *     parameters             ANY DEFINED BY algorithm OPTIONAL  }
 * 
* * @author Valerie Peng * * @see java.security.spec.PKCS8EncodedKeySpec * * @since 1.4 */ public class EncryptedPrivateKeyInfo { // the "encryptionAlgorithm" field private AlgorithmId algid; // the "encryptedData" field private byte[] encryptedData; // the ASN.1 encoded contents of this class private byte[] encoded = null; /** * Constructs (i.e., parses) an EncryptedPrivateKeyInfo from * its ASN.1 encoding. * @param encoded the ASN.1 encoding of this object. The contents of * the array are copied to protect against subsequent modification. * @exception NullPointerException if the encoded is null. * @exception IOException if error occurs when parsing the ASN.1 encoding. */ public EncryptedPrivateKeyInfo(byte[] encoded) throws IOException { if (encoded == null) { throw new NullPointerException("the encoded parameter " + "must be non-null"); } this.encoded = (byte[])encoded.clone(); DerValue val = new DerValue(this.encoded); DerValue[] seq = new DerValue[2]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); if (val.data.available() != 0) { throw new IOException("overrun, bytes = " + val.data.available()); } this.algid = AlgorithmId.parse(seq[0]); if (seq[0].data.available() != 0) { throw new IOException("encryptionAlgorithm field overrun"); } this.encryptedData = seq[1].getOctetString(); if (seq[1].data.available() != 0) { throw new IOException("encryptedData field overrun"); } } /** * Constructs an EncryptedPrivateKeyInfo from the * encryption algorithm name and the encrypted data. * *

Note: This constructor will use null as the value of the * algorithm parameters. If the encryption algorithm has * parameters whose value is not null, a different constructor, * e.g. EncryptedPrivateKeyInfo(AlgorithmParameters, byte[]), * should be used. * * @param algName encryption algorithm name. See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard Cipher algorithm names. * @param encryptedData encrypted data. The contents of * encrypedData are copied to protect against subsequent * modification when constructing this object. * @exception NullPointerException if algName or * encryptedData is null. * @exception IllegalArgumentException if encryptedData * is empty, i.e. 0-length. * @exception NoSuchAlgorithmException if the specified algName is * not supported. */ public EncryptedPrivateKeyInfo(String algName, byte[] encryptedData) throws NoSuchAlgorithmException { if (algName == null) throw new NullPointerException("the algName parameter " + "must be non-null"); this.algid = AlgorithmId.get(algName); if (encryptedData == null) { throw new NullPointerException("the encryptedData " + "parameter must be non-null"); } else if (encryptedData.length == 0) { throw new IllegalArgumentException("the encryptedData " + "parameter must not be empty"); } else { this.encryptedData = (byte[])encryptedData.clone(); } // delay the generation of ASN.1 encoding until // getEncoded() is called this.encoded = null; } /** * Constructs an EncryptedPrivateKeyInfo from the * encryption algorithm parameters and the encrypted data. * * @param algParams the algorithm parameters for the encryption * algorithm. algParams.getEncoded() should return * the ASN.1 encoded bytes of the parameters field * of the AlgorithmIdentifer component of the * EncryptedPrivateKeyInfo type. * @param encryptedData encrypted data. The contents of * encrypedData are copied to protect against * subsequent modification when constructing this object. * @exception NullPointerException if algParams or * encryptedData is null. * @exception IllegalArgumentException if encryptedData * is empty, i.e. 0-length. * @exception NoSuchAlgorithmException if the specified algName of * the specified algParams parameter is not supported. */ public EncryptedPrivateKeyInfo(AlgorithmParameters algParams, byte[] encryptedData) throws NoSuchAlgorithmException { if (algParams == null) { throw new NullPointerException("algParams must be non-null"); } this.algid = AlgorithmId.get(algParams); if (encryptedData == null) { throw new NullPointerException("encryptedData must be non-null"); } else if (encryptedData.length == 0) { throw new IllegalArgumentException("the encryptedData " + "parameter must not be empty"); } else { this.encryptedData = (byte[])encryptedData.clone(); } // delay the generation of ASN.1 encoding until // getEncoded() is called this.encoded = null; } /** * Returns the encryption algorithm. *

Note: Standard name is returned instead of the specified one * in the constructor when such mapping is available. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard Cipher algorithm names. * * @return the encryption algorithm name. */ public String getAlgName() { return this.algid.getName(); } /** * Returns the algorithm parameters used by the encryption algorithm. * @return the algorithm parameters. */ public AlgorithmParameters getAlgParameters() { return this.algid.getParameters(); } /** * Returns the encrypted data. * @return the encrypted data. Returns a new array * each time this method is called. */ public byte[] getEncryptedData() { return (byte[])this.encryptedData.clone(); } /** * Extract the enclosed PKCS8EncodedKeySpec object from the * encrypted data and return it. *
Note: In order to successfully retrieve the enclosed * PKCS8EncodedKeySpec object, cipher needs * to be initialized to either Cipher.DECRYPT_MODE or * Cipher.UNWRAP_MODE, with the same key and parameters used * for generating the encrypted data. * * @param cipher the initialized cipher object which will be * used for decrypting the encrypted data. * @return the PKCS8EncodedKeySpec object. * @exception NullPointerException if cipher * is null. * @exception InvalidKeySpecException if the given cipher is * inappropriate for the encrypted data or the encrypted * data is corrupted and cannot be decrypted. */ public PKCS8EncodedKeySpec getKeySpec(Cipher cipher) throws InvalidKeySpecException { byte[] encoded = null; try { encoded = cipher.doFinal((byte[])encryptedData); checkPKCS8Encoding(encoded); } catch (GeneralSecurityException gse) { InvalidKeySpecException ikse = new InvalidKeySpecException( "Cannot retrieve the PKCS8EncodedKeySpec"); ikse.initCause(gse); throw ikse; } catch (IOException ioe) { InvalidKeySpecException ikse = new InvalidKeySpecException( "Cannot retrieve the PKCS8EncodedKeySpec"); ikse.initCause(ioe); throw ikse; } catch (IllegalStateException ise) { InvalidKeySpecException ikse = new InvalidKeySpecException( "Cannot retrieve the PKCS8EncodedKeySpec"); ikse.initCause(ise); throw ikse; } return new PKCS8EncodedKeySpec(encoded); } private PKCS8EncodedKeySpec getKeySpecImpl(Key decryptKey, Provider provider) throws NoSuchAlgorithmException, InvalidKeyException { byte[] encoded = null; Cipher c; try { if (provider == null) { // use the most preferred one c = Cipher.getInstance(algid.getName()); } else { c = Cipher.getInstance(algid.getName(), provider); } c.init(Cipher.DECRYPT_MODE, decryptKey, algid.getParameters()); encoded = c.doFinal(encryptedData); checkPKCS8Encoding(encoded); } catch (NoSuchAlgorithmException nsae) { // rethrow throw nsae; } catch (GeneralSecurityException gse) { InvalidKeyException ike = new InvalidKeyException ("Cannot retrieve the PKCS8EncodedKeySpec"); ike.initCause(gse); throw ike; } catch (IOException ioe) { InvalidKeyException ike = new InvalidKeyException ("Cannot retrieve the PKCS8EncodedKeySpec"); ike.initCause(ioe); throw ike; } return new PKCS8EncodedKeySpec(encoded); } /** * Extract the enclosed PKCS8EncodedKeySpec object from the * encrypted data and return it. * @param decryptKey key used for decrypting the encrypted data. * @return the PKCS8EncodedKeySpec object. * @exception NullPointerException if decryptKey * is null. * @exception NoSuchAlgorithmException if cannot find appropriate * cipher to decrypt the encrypted data. * @exception InvalidKeyException if decryptKey * cannot be used to decrypt the encrypted data or the decryption * result is not a valid PKCS8KeySpec. * * @since 1.5 */ public PKCS8EncodedKeySpec getKeySpec(Key decryptKey) throws NoSuchAlgorithmException, InvalidKeyException { if (decryptKey == null) { throw new NullPointerException("decryptKey is null"); } return getKeySpecImpl(decryptKey, null); } /** * Extract the enclosed PKCS8EncodedKeySpec object from the * encrypted data and return it. * @param decryptKey key used for decrypting the encrypted data. * @param providerName the name of provider whose Cipher * implementation will be used. * @return the PKCS8EncodedKeySpec object. * @exception NullPointerException if decryptKey * or providerName is null. * @exception NoSuchProviderException if no provider * providerName is registered. * @exception NoSuchAlgorithmException if cannot find appropriate * cipher to decrypt the encrypted data. * @exception InvalidKeyException if decryptKey * cannot be used to decrypt the encrypted data or the decryption * result is not a valid PKCS8KeySpec. * * @since 1.5 */ public PKCS8EncodedKeySpec getKeySpec(Key decryptKey, String providerName) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException { if (decryptKey == null) { throw new NullPointerException("decryptKey is null"); } if (providerName == null) { throw new NullPointerException("provider is null"); } Provider provider = Security.getProvider(providerName); if (provider == null) { throw new NoSuchProviderException("provider " + providerName + " not found"); } return getKeySpecImpl(decryptKey, provider); } /** * Extract the enclosed PKCS8EncodedKeySpec object from the * encrypted data and return it. * @param decryptKey key used for decrypting the encrypted data. * @param provider the name of provider whose Cipher implementation * will be used. * @return the PKCS8EncodedKeySpec object. * @exception NullPointerException if decryptKey * or provider is null. * @exception NoSuchAlgorithmException if cannot find appropriate * cipher to decrypt the encrypted data in provider. * @exception InvalidKeyException if decryptKey * cannot be used to decrypt the encrypted data or the decryption * result is not a valid PKCS8KeySpec. * * @since 1.5 */ public PKCS8EncodedKeySpec getKeySpec(Key decryptKey, Provider provider) throws NoSuchAlgorithmException, InvalidKeyException { if (decryptKey == null) { throw new NullPointerException("decryptKey is null"); } if (provider == null) { throw new NullPointerException("provider is null"); } return getKeySpecImpl(decryptKey, provider); } /** * Returns the ASN.1 encoding of this object. * @return the ASN.1 encoding. Returns a new array * each time this method is called. * @exception IOException if error occurs when constructing its * ASN.1 encoding. */ public byte[] getEncoded() throws IOException { if (this.encoded == null) { DerOutputStream out = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream(); // encode encryption algorithm algid.encode(tmp); // encode encrypted data tmp.putOctetString(encryptedData); // wrap everything into a SEQUENCE out.write(DerValue.tag_Sequence, tmp); this.encoded = out.toByteArray(); } return (byte[])this.encoded.clone(); } private static void checkTag(DerValue val, byte tag, String valName) throws IOException { if (val.getTag() != tag) { throw new IOException("invalid key encoding - wrong tag for " + valName); } } private static void checkPKCS8Encoding(byte[] encodedKey) throws IOException { DerInputStream in = new DerInputStream(encodedKey); DerValue[] values = in.getSequence(3); switch (values.length) { case 4: checkTag(values[3], DerValue.TAG_CONTEXT, "attributes"); case 3: checkTag(values[0], DerValue.tag_Integer, "version"); DerInputStream algid = values[1].toDerInputStream(); algid.getOID(); if (algid.available() != 0) { algid.getDerValue(); } checkTag(values[2], DerValue.tag_OctetString, "privateKey"); break; default: throw new IOException("invalid key encoding"); } } } clean-crypto-1/src/main/java/javax/crypto/ExemptionMechanism.java0000664000175000017500000004512211370332423025225 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.AlgorithmParameters; import java.security.Provider; import java.security.Key; import java.security.Security; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.InvalidKeyException; import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; import sun.security.jca.GetInstance.Instance; /** * This class provides the functionality of an exemption mechanism, examples * of which are key recovery, key weakening, and * key escrow. * *

Applications or applets that use an exemption mechanism may be granted * stronger encryption capabilities than those which don't. * * @since 1.4 */ public class ExemptionMechanism { // The provider private Provider provider; // The provider implementation (delegate) private ExemptionMechanismSpi exmechSpi; // The name of the exemption mechanism. private String mechanism; // Flag which indicates whether this ExemptionMechanism // result is generated successfully. private boolean done = false; // State information private boolean initialized = false; // Store away the key at init() time for later comparison. private Key keyStored = null; /** * Creates a ExemptionMechanism object. * * @param exmechSpi the delegate * @param provider the provider * @param mechanism the exemption mechanism */ protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi, Provider provider, String mechanism) { this.exmechSpi = exmechSpi; this.provider = provider; this.mechanism = mechanism; } /** * Returns the exemption mechanism name of this * ExemptionMechanism object. * *

This is the same name that was specified in one of the * getInstance calls that created this * ExemptionMechanism object. * * @return the exemption mechanism name of this * ExemptionMechanism object. */ public final String getName() { return this.mechanism; } /** * Returns an ExemptionMechanism object that implements the * specified exemption mechanism algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new ExemptionMechanism object encapsulating the * ExemptionMechanismSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested exemption * mechanism. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard exemption mechanism names. * * @return the new ExemptionMechanism object. * * @exception NullPointerException if algorithm * is null. * * @exception NoSuchAlgorithmException if no Provider supports an * ExemptionMechanismSpi implementation for the * specified algorithm. * * @see java.security.Provider */ public static final ExemptionMechanism getInstance(String algorithm) throws NoSuchAlgorithmException { Instance instance = JceSecurity.getInstance("ExemptionMechanism", ExemptionMechanismSpi.class, algorithm); return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl, instance.provider, algorithm); } /** * Returns an ExemptionMechanism object that implements the * specified exemption mechanism algorithm. * *

A new ExemptionMechanism object encapsulating the * ExemptionMechanismSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * @param algorithm the standard name of the requested exemption mechanism. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard exemption mechanism names. * * @param provider the name of the provider. * * @return the new ExemptionMechanism object. * * @exception NullPointerException if algorithm * is null. * * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider * is null or empty. * * @see java.security.Provider */ public static final ExemptionMechanism getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = JceSecurity.getInstance("ExemptionMechanism", ExemptionMechanismSpi.class, algorithm, provider); return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl, instance.provider, algorithm); } /** * Returns an ExemptionMechanism object that implements the * specified exemption mechanism algorithm. * *

A new ExemptionMechanism object encapsulating the * ExemptionMechanismSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the standard name of the requested exemption mechanism. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard exemption mechanism names. * * @param provider the provider. * * @return the new ExemptionMechanism object. * * @exception NullPointerException if algorithm * is null. * * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider * is null. * * @see java.security.Provider */ public static final ExemptionMechanism getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = JceSecurity.getInstance("ExemptionMechanism", ExemptionMechanismSpi.class, algorithm, provider); return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl, instance.provider, algorithm); } /** * Returns the provider of this ExemptionMechanism object. * * @return the provider of this ExemptionMechanism object. */ public final Provider getProvider() { return this.provider; } /** * Returns whether the result blob has been generated successfully by this * exemption mechanism. * *

The method also makes sure that the key passed in is the same as * the one this exemption mechanism used in initializing and generating * phases. * * @param key the key the crypto is going to use. * * @return whether the result blob of the same key has been generated * successfully by this exemption mechanism; false if key * is null. * * @exception ExemptionMechanismException if problem(s) encountered * while determining whether the result blob has been generated successfully * by this exemption mechanism object. */ public final boolean isCryptoAllowed(Key key) throws ExemptionMechanismException { boolean ret = false; if (done && (key != null)) { // Check if the key passed in is the same as the one // this exemption mechanism used. ret = keyStored.equals(key); } return ret; } /** * Returns the length in bytes that an output buffer would need to be in * order to hold the result of the next * {@link #genExemptionBlob(byte[]) genExemptionBlob} * operation, given the input length inputLen (in bytes). * *

The actual output length of the next * {@link #genExemptionBlob(byte[]) genExemptionBlob} * call may be smaller than the length returned by this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) * * @exception IllegalStateException if this exemption mechanism is in a * wrong state (e.g., has not yet been initialized) */ public final int getOutputSize(int inputLen) throws IllegalStateException { if (!initialized) { throw new IllegalStateException( "ExemptionMechanism not initialized"); } if (inputLen < 0) { throw new IllegalArgumentException( "Input size must be equal to " + "or greater than zero"); } return exmechSpi.engineGetOutputSize(inputLen); } /** * Initializes this exemption mechanism with a key. * *

If this exemption mechanism requires any algorithm parameters * that cannot be derived from the given key, the * underlying exemption mechanism implementation is supposed to * generate the required parameters itself (using provider-specific * default values); in the case that algorithm parameters must be * specified by the caller, an InvalidKeyException is raised. * * @param key the key for this exemption mechanism * * @exception InvalidKeyException if the given key is inappropriate for * this exemption mechanism. * @exception ExemptionMechanismException if problem(s) encountered in the * process of initializing. */ public final void init(Key key) throws InvalidKeyException, ExemptionMechanismException { done = false; initialized = false; keyStored = key; exmechSpi.engineInit(key); initialized = true; } /** * Initializes this exemption mechanism with a key and a set of algorithm * parameters. * *

If this exemption mechanism requires any algorithm parameters * and params is null, the underlying exemption * mechanism implementation is supposed to generate the required * parameters itself (using provider-specific default values); in the case * that algorithm parameters must be specified by the caller, an * InvalidAlgorithmParameterException is raised. * * @param key the key for this exemption mechanism * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * this exemption mechanism. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this exemption mechanism. * @exception ExemptionMechanismException if problem(s) encountered in the * process of initializing. */ public final void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException, ExemptionMechanismException { done = false; initialized = false; keyStored = key; exmechSpi.engineInit(key, params); initialized = true; } /** * Initializes this exemption mechanism with a key and a set of algorithm * parameters. * *

If this exemption mechanism requires any algorithm parameters * and params is null, the underlying exemption mechanism * implementation is supposed to generate the required parameters itself * (using provider-specific default values); in the case that algorithm * parameters must be specified by the caller, an * InvalidAlgorithmParameterException is raised. * * @param key the key for this exemption mechanism * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * this exemption mechanism. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this exemption mechanism. * @exception ExemptionMechanismException if problem(s) encountered in the * process of initializing. */ public final void init(Key key, AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException, ExemptionMechanismException { done = false; initialized = false; keyStored = key; exmechSpi.engineInit(key, params); initialized = true; } /** * Generates the exemption mechanism key blob. * * @return the new buffer with the result key blob. * * @exception IllegalStateException if this exemption mechanism is in * a wrong state (e.g., has not been initialized). * @exception ExemptionMechanismException if problem(s) encountered in the * process of generating. */ public final byte[] genExemptionBlob() throws IllegalStateException, ExemptionMechanismException { if (!initialized) { throw new IllegalStateException( "ExemptionMechanism not initialized"); } byte[] blob = exmechSpi.engineGenExemptionBlob(); done = true; return blob; } /** * Generates the exemption mechanism key blob, and stores the result in * the output buffer. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * @param output the buffer for the result * * @return the number of bytes stored in output * * @exception IllegalStateException if this exemption mechanism is in * a wrong state (e.g., has not been initialized). * @exception ShortBufferException if the given output buffer is too small * to hold the result. * @exception ExemptionMechanismException if problem(s) encountered in the * process of generating. */ public final int genExemptionBlob(byte[] output) throws IllegalStateException, ShortBufferException, ExemptionMechanismException { if (!initialized) { throw new IllegalStateException ("ExemptionMechanism not initialized"); } int n = exmechSpi.engineGenExemptionBlob(output, 0); done = true; return n; } /** * Generates the exemption mechanism key blob, and stores the result in * the output buffer, starting at outputOffset * inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #getOutputSize(int) getOutputSize} to determine how big * the output buffer should be. * * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception IllegalStateException if this exemption mechanism is in * a wrong state (e.g., has not been initialized). * @exception ShortBufferException if the given output buffer is too small * to hold the result. * @exception ExemptionMechanismException if problem(s) encountered in the * process of generating. */ public final int genExemptionBlob(byte[] output, int outputOffset) throws IllegalStateException, ShortBufferException, ExemptionMechanismException { if (!initialized) { throw new IllegalStateException ("ExemptionMechanism not initialized"); } int n = exmechSpi.engineGenExemptionBlob(output, outputOffset); done = true; return n; } /** * Ensures that the key stored away by this ExemptionMechanism * object will be wiped out when there are no more references to it. */ protected void finalize() { keyStored = null; // Are there anything else we could do? } } clean-crypto-1/src/main/java/javax/crypto/ExemptionMechanismException.java0000664000175000017500000000402411370332423027100 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.GeneralSecurityException; /** * This is the generic ExemptionMechanism exception. * * @since 1.4 */ public class ExemptionMechanismException extends GeneralSecurityException { private static final long serialVersionUID = 1572699429277957109L; /** * Constructs a ExemptionMechanismException with no detailed message. * (A detailed message is a String that describes this particular * exception.) */ public ExemptionMechanismException() { super(); } /** * Constructs a ExemptionMechanismException with the specified * detailed message. (A detailed message is a String that describes * this particular exception.) * * @param msg the detailed message. */ public ExemptionMechanismException(String msg) { super(msg); } } clean-crypto-1/src/main/java/javax/crypto/ExemptionMechanismSpi.java0000664000175000017500000001616111370332423025702 0ustar moellermoeller/* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.Key; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; /** * This class defines the Service Provider Interface (SPI) * for the ExemptionMechanism class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a particular exemption mechanism. * * @author Sharon Liu * * @since 1.4 */ public abstract class ExemptionMechanismSpi { /** * Returns the length in bytes that an output buffer would need to be in * order to hold the result of the next * {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob} * operation, given the input length inputLen (in bytes). * *

The actual output length of the next * {@link #engineGenExemptionBlob(byte[], int) engineGenExemptionBlob} * call may be smaller than the length returned by this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) */ protected abstract int engineGetOutputSize(int inputLen); /** * Initializes this exemption mechanism with a key. * *

If this exemption mechanism requires any algorithm parameters * that cannot be derived from the given key, the underlying * exemption mechanism implementation is supposed to generate the required * parameters itself (using provider-specific default values); in the case * that algorithm parameters must be specified by the caller, an * InvalidKeyException is raised. * * @param key the key for this exemption mechanism * * @exception InvalidKeyException if the given key is inappropriate for * this exemption mechanism. * @exception ExemptionMechanismException if problem(s) encountered in the * process of initializing. */ protected abstract void engineInit(Key key) throws InvalidKeyException, ExemptionMechanismException; /** * Initializes this exemption mechanism with a key and a set of algorithm * parameters. * *

If this exemption mechanism requires any algorithm parameters and * params is null, the underlying exemption mechanism * implementation is supposed to generate the required parameters * itself (using provider-specific default values); in the case that * algorithm parameters must be specified by the caller, an * InvalidAlgorithmParameterException is raised. * * @param key the key for this exemption mechanism * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * this exemption mechanism. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this exemption mechanism. * @exception ExemptionMechanismException if problem(s) encountered in the * process of initializing. */ protected abstract void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException, ExemptionMechanismException; /** * Initializes this exemption mechanism with a key and a set of algorithm * parameters. * *

If this exemption mechanism requires any algorithm parameters * and params is null, the underlying exemption mechanism * implementation is supposed to generate the required parameters * itself (using provider-specific default values); in the case that * algorithm parameters must be specified by the caller, an * InvalidAlgorithmParameterException is raised. * * @param key the key for this exemption mechanism * @param params the algorithm parameters * * @exception InvalidKeyException if the given key is inappropriate for * this exemption mechanism. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this exemption mechanism. * @exception ExemptionMechanismException if problem(s) encountered in the * process of initializing. */ protected abstract void engineInit(Key key, AlgorithmParameters params) throws InvalidKeyException, InvalidAlgorithmParameterException, ExemptionMechanismException; /** * Generates the exemption mechanism key blob. * * @return the new buffer with the result key blob. * * @exception ExemptionMechanismException if problem(s) encountered in the * process of generating. */ protected abstract byte[] engineGenExemptionBlob() throws ExemptionMechanismException; /** * Generates the exemption mechanism key blob, and stores the result in * the output buffer, starting at outputOffset * inclusive. * *

If the output buffer is too small to hold the result, * a ShortBufferException is thrown. In this case, repeat this * call with a larger output buffer. Use * {@link #engineGetOutputSize(int) engineGetOutputSize} to determine * how big the output buffer should be. * * @param output the buffer for the result * @param outputOffset the offset in output where the result * is stored * * @return the number of bytes stored in output * * @exception ShortBufferException if the given output buffer is too small * to hold the result. * @exception ExemptionMechanismException if problem(s) encountered in the * process of generating. */ protected abstract int engineGenExemptionBlob (byte[] output, int outputOffset) throws ShortBufferException, ExemptionMechanismException; } clean-crypto-1/src/main/java/javax/crypto/IllegalBlockSizeException.java0000664000175000017500000000401311370332423026460 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; /** * This exception is thrown when the length of data provided to a block * cipher is incorrect, i.e., does not match the block size of the cipher. * * @author Jan Luehe * * @since 1.4 */ public class IllegalBlockSizeException extends java.security.GeneralSecurityException { private static final long serialVersionUID = -1965144811953540392L; /** * Constructs an IllegalBlockSizeException with no detail message. * A detail message is a String that describes this particular * exception. */ public IllegalBlockSizeException() { super(); } /** * Constructs an IllegalBlockSizeException with the specified * detail message. * * @param msg the detail message. */ public IllegalBlockSizeException(String msg) { super(msg); } } clean-crypto-1/src/main/java/javax/crypto/JceSecurity.java0000664000175000017500000000644511370332423023666 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.*; import java.security.*; import java.security.Provider.Service; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * This class instantiates implementations of JCE engine classes from * providers registered with the java.security.Security object. * * @author Jan Luehe * @author Sharon Liu * @since 1.4 */ final class JceSecurity { // Used in KeyGenerator, Cipher and KeyAgreement. static final SecureRandom RANDOM = new SecureRandom(); /* * Don't let anyone instantiate this. */ private JceSecurity() { } static Instance getInstance(String type, Class clazz, String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Service s = GetInstance.getService(type, algorithm, provider); return GetInstance.getInstance(s, clazz); } static Instance getInstance(String type, Class clazz, String algorithm, Provider provider) throws NoSuchAlgorithmException { Service s = GetInstance.getService(type, algorithm, provider); return GetInstance.getInstance(s, clazz); } static Instance getInstance(String type, Class clazz, String algorithm) throws NoSuchAlgorithmException { List services = GetInstance.getServices(type, algorithm); NoSuchAlgorithmException failure = null; for (Iterator t = services.iterator(); t.hasNext(); ) { Service s = (Service)t.next(); try { Instance instance = GetInstance.getInstance(s, clazz); return instance; } catch (NoSuchAlgorithmException e) { failure = e; } } throw new NoSuchAlgorithmException("Algorithm " + algorithm + " not available", failure); } // Used to return whether this provider is properly signed and // can be used by JCE. These days just returns true. Still used // in SecretKeyFactory, KeyGenerator, Mac and KeyAgreement. static boolean canUseProvider(Provider p) { return true; } } clean-crypto-1/src/main/java/javax/crypto/KeyAgreement.java0000664000175000017500000005771611370332423024024 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.*; import java.security.*; import java.security.Provider.Service; import java.security.spec.*; import sun.security.util.Debug; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * This class provides the functionality of a key agreement (or key * exchange) protocol. *

* The keys involved in establishing a shared secret are created by one of the * key generators (KeyPairGenerator or * KeyGenerator), a KeyFactory, or as a result from * an intermediate phase of the key agreement protocol. * *

For each of the correspondents in the key exchange, doPhase * needs to be called. For example, if this key exchange is with one other * party, doPhase needs to be called once, with the * lastPhase flag set to true. * If this key exchange is * with two other parties, doPhase needs to be called twice, * the first time setting the lastPhase flag to * false, and the second time setting it to true. * There may be any number of parties involved in a key exchange. * * @author Jan Luehe * * @see KeyGenerator * @see SecretKey * @since 1.4 */ public class KeyAgreement { private static final Debug debug = Debug.getInstance("jca", "KeyAgreement"); // The provider private Provider provider; // The provider implementation (delegate) private KeyAgreementSpi spi; // The name of the key agreement algorithm. private final String algorithm; // next service to try in provider selection // null once provider is selected private Service firstService; // remaining services to try in provider selection // null once provider is selected private Iterator serviceIterator; private final Object lock; /** * Creates a KeyAgreement object. * * @param keyAgreeSpi the delegate * @param provider the provider * @param algorithm the algorithm */ protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider, String algorithm) { this.spi = keyAgreeSpi; this.provider = provider; this.algorithm = algorithm; lock = null; } private KeyAgreement(Service s, Iterator t, String algorithm) { firstService = s; serviceIterator = t; this.algorithm = algorithm; lock = new Object(); } /** * Returns the algorithm name of this KeyAgreement object. * *

This is the same name that was specified in one of the * getInstance calls that created this * KeyAgreement object. * * @return the algorithm name of this KeyAgreement object. */ public final String getAlgorithm() { return this.algorithm; } /** * Returns a KeyAgreement object that implements the * specified key agreement algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new KeyAgreement object encapsulating the * KeyAgreementSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested key agreement * algorithm. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @return the new KeyAgreement object. * * @exception NullPointerException if the specified algorithm * is null. * * @exception NoSuchAlgorithmException if no Provider supports a * KeyAgreementSpi implementation for the * specified algorithm. * * @see java.security.Provider */ public static final KeyAgreement getInstance(String algorithm) throws NoSuchAlgorithmException { List services = GetInstance.getServices("KeyAgreement", algorithm); // make sure there is at least one service from a signed provider Iterator t = services.iterator(); while (t.hasNext()) { Service s = (Service)t.next(); if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } return new KeyAgreement(s, t, algorithm); } throw new NoSuchAlgorithmException ("Algorithm " + algorithm + " not available"); } /** * Returns a KeyAgreement object that implements the * specified key agreement algorithm. * *

A new KeyAgreement object encapsulating the * KeyAgreementSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested key agreement * algorithm. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new KeyAgreement object. * * @exception NullPointerException if the specified algorithm * is null. * * @exception NoSuchAlgorithmException if a KeyAgreementSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider * is null or empty. * * @see java.security.Provider */ public static final KeyAgreement getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = JceSecurity.getInstance ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider); return new KeyAgreement((KeyAgreementSpi)instance.impl, instance.provider, algorithm); } /** * Returns a KeyAgreement object that implements the * specified key agreement algorithm. * *

A new KeyAgreement object encapsulating the * KeyAgreementSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the standard name of the requested key agreement * algorithm. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the provider. * * @return the new KeyAgreement object. * * @exception NullPointerException if the specified algorithm * is null. * * @exception NoSuchAlgorithmException if a KeyAgreementSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider * is null. * * @see java.security.Provider */ public static final KeyAgreement getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = JceSecurity.getInstance ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider); return new KeyAgreement((KeyAgreementSpi)instance.impl, instance.provider, algorithm); } // max number of debug warnings to print from chooseFirstProvider() private static int warnCount = 10; /** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because init() * is not the first method called. */ void chooseFirstProvider() { if (spi != null) { return; } synchronized (lock) { if (spi != null) { return; } if (debug != null) { int w = --warnCount; if (w >= 0) { debug.println("KeyAgreement.init() not first method " + "called, disabling delayed provider selection"); if (w == 0) { debug.println("Further warnings of this type will " + "be suppressed"); } new Exception("Call trace").printStackTrace(); } } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; if (firstService != null) { s = firstService; firstService = null; } else { s = (Service)serviceIterator.next(); } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } try { Object obj = s.newInstance(null); if (obj instanceof KeyAgreementSpi == false) { continue; } spi = (KeyAgreementSpi)obj; provider = s.getProvider(); // not needed any more firstService = null; serviceIterator = null; return; } catch (Exception e) { lastException = e; } } ProviderException e = new ProviderException ("Could not construct KeyAgreementSpi instance"); if (lastException != null) { e.initCause(lastException); } throw e; } } private final static int I_NO_PARAMS = 1; private final static int I_PARAMS = 2; private void implInit(KeyAgreementSpi spi, int type, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (type == I_NO_PARAMS) { spi.engineInit(key, random); } else { // I_PARAMS spi.engineInit(key, params, random); } } private void chooseProvider(int initType, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { synchronized (lock) { if (spi != null) { implInit(spi, initType, key, params, random); return; } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; if (firstService != null) { s = firstService; firstService = null; } else { s = (Service)serviceIterator.next(); } // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue; } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } try { KeyAgreementSpi spi = (KeyAgreementSpi)s.newInstance(null); implInit(spi, initType, key, params, random); provider = s.getProvider(); this.spi = spi; firstService = null; serviceIterator = null; return; } catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() if (lastException == null) { lastException = e; } } } // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException; } if (lastException instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)lastException; } if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException; } String kName = (key != null) ? key.getClass().getName() : "(null)"; throw new InvalidKeyException ("No installed provider supports this key: " + kName, lastException); } } /** * Returns the provider of this KeyAgreement object. * * @return the provider of this KeyAgreement object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } /** * Initializes this key agreement with the given key, which is required to * contain all the algorithm parameters required for this key agreement. * *

If this key agreement requires any random bytes, it will get * them using the * {@link SecureRandom SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * @param key the party's private information. For example, in the case * of the Diffie-Hellman key agreement, this would be the party's own * Diffie-Hellman private key. * * @exception InvalidKeyException if the given key is * inappropriate for this key agreement, e.g., is of the wrong type or * has an incompatible algorithm type. */ public final void init(Key key) throws InvalidKeyException { init(key, JceSecurity.RANDOM); } /** * Initializes this key agreement with the given key and source of * randomness. The given key is required to contain all the algorithm * parameters required for this key agreement. * *

If the key agreement algorithm requires random bytes, it gets them * from the given source of randomness, random. * However, if the underlying * algorithm implementation does not require any random bytes, * random is ignored. * * @param key the party's private information. For example, in the case * of the Diffie-Hellman key agreement, this would be the party's own * Diffie-Hellman private key. * @param random the source of randomness * * @exception InvalidKeyException if the given key is * inappropriate for this key agreement, e.g., is of the wrong type or * has an incompatible algorithm type. */ public final void init(Key key, SecureRandom random) throws InvalidKeyException { if (spi != null) { spi.engineInit(key, random); } else { try { chooseProvider(I_NO_PARAMS, key, null, random); } catch (InvalidAlgorithmParameterException e) { // should never occur throw new InvalidKeyException(e); } } } /** * Initializes this key agreement with the given key and set of * algorithm parameters. * *

If this key agreement requires any random bytes, it will get * them using the * {@link SecureRandom SecureRandom} * implementation of the highest-priority * installed provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * @param key the party's private information. For example, in the case * of the Diffie-Hellman key agreement, this would be the party's own * Diffie-Hellman private key. * @param params the key agreement parameters * * @exception InvalidKeyException if the given key is * inappropriate for this key agreement, e.g., is of the wrong type or * has an incompatible algorithm type. * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key agreement. */ public final void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { init(key, params, JceSecurity.RANDOM); } /** * Initializes this key agreement with the given key, set of * algorithm parameters, and source of randomness. * * @param key the party's private information. For example, in the case * of the Diffie-Hellman key agreement, this would be the party's own * Diffie-Hellman private key. * @param params the key agreement parameters * @param random the source of randomness * * @exception InvalidKeyException if the given key is * inappropriate for this key agreement, e.g., is of the wrong type or * has an incompatible algorithm type. * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key agreement. */ public final void init(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (spi != null) { spi.engineInit(key, params, random); } else { chooseProvider(I_PARAMS, key, params, random); } } /** * Executes the next phase of this key agreement with the given * key that was received from one of the other parties involved in this key * agreement. * * @param key the key for this phase. For example, in the case of * Diffie-Hellman between 2 parties, this would be the other party's * Diffie-Hellman public key. * @param lastPhase flag which indicates whether or not this is the last * phase of this key agreement. * * @return the (intermediate) key resulting from this phase, or null * if this phase does not yield a key * * @exception InvalidKeyException if the given key is inappropriate for * this phase. * @exception IllegalStateException if this key agreement has not been * initialized. */ public final Key doPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException { chooseFirstProvider(); return spi.engineDoPhase(key, lastPhase); } /** * Generates the shared secret and returns it in a new buffer. * *

This method resets this KeyAgreement object, so that it * can be reused for further key agreements. Unless this key agreement is * reinitialized with one of the init methods, the same * private information and algorithm parameters will be used for * subsequent key agreements. * * @return the new buffer with the shared secret * * @exception IllegalStateException if this key agreement has not been * completed yet */ public final byte[] generateSecret() throws IllegalStateException { chooseFirstProvider(); return spi.engineGenerateSecret(); } /** * Generates the shared secret, and places it into the buffer * sharedSecret, beginning at offset inclusive. * *

If the sharedSecret buffer is too small to hold the * result, a ShortBufferException is thrown. * In this case, this call should be repeated with a larger output buffer. * *

This method resets this KeyAgreement object, so that it * can be reused for further key agreements. Unless this key agreement is * reinitialized with one of the init methods, the same * private information and algorithm parameters will be used for * subsequent key agreements. * * @param sharedSecret the buffer for the shared secret * @param offset the offset in sharedSecret where the * shared secret will be stored * * @return the number of bytes placed into sharedSecret * * @exception IllegalStateException if this key agreement has not been * completed yet * @exception ShortBufferException if the given output buffer is too small * to hold the secret */ public final int generateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException { chooseFirstProvider(); return spi.engineGenerateSecret(sharedSecret, offset); } /** * Creates the shared secret and returns it as a SecretKey * object of the specified algorithm. * *

This method resets this KeyAgreement object, so that it * can be reused for further key agreements. Unless this key agreement is * reinitialized with one of the init methods, the same * private information and algorithm parameters will be used for * subsequent key agreements. * * @param algorithm the requested secret-key algorithm * * @return the shared secret key * * @exception IllegalStateException if this key agreement has not been * completed yet * @exception NoSuchAlgorithmException if the specified secret-key * algorithm is not available * @exception InvalidKeyException if the shared secret-key material cannot * be used to generate a secret key of the specified algorithm (e.g., * the key material is too short) */ public final SecretKey generateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { chooseFirstProvider(); return spi.engineGenerateSecret(algorithm); } } clean-crypto-1/src/main/java/javax/crypto/KeyAgreementSpi.java0000664000175000017500000002116511370332423024465 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.security.spec.*; /** * This class defines the Service Provider Interface (SPI) * for the KeyAgreement class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a particular key agreement algorithm. * *

The keys involved in establishing a shared secret are created by one * of the * key generators (KeyPairGenerator or * KeyGenerator), a KeyFactory, or as a result from * an intermediate phase of the key agreement protocol * ({@link #engineDoPhase(java.security.Key, boolean) engineDoPhase}). * *

For each of the correspondents in the key exchange, * engineDoPhase * needs to be called. For example, if the key exchange is with one other * party, engineDoPhase needs to be called once, with the * lastPhase flag set to true. * If the key exchange is * with two other parties, engineDoPhase needs to be called twice, * the first time setting the lastPhase flag to * false, and the second time setting it to true. * There may be any number of parties involved in a key exchange. * * @author Jan Luehe * * @see KeyGenerator * @see SecretKey * @since 1.4 */ public abstract class KeyAgreementSpi { /** * Initializes this key agreement with the given key and source of * randomness. The given key is required to contain all the algorithm * parameters required for this key agreement. * *

If the key agreement algorithm requires random bytes, it gets them * from the given source of randomness, random. * However, if the underlying * algorithm implementation does not require any random bytes, * random is ignored. * * @param key the party's private information. For example, in the case * of the Diffie-Hellman key agreement, this would be the party's own * Diffie-Hellman private key. * @param random the source of randomness * * @exception InvalidKeyException if the given key is * inappropriate for this key agreement, e.g., is of the wrong type or * has an incompatible algorithm type. */ protected abstract void engineInit(Key key, SecureRandom random) throws InvalidKeyException; /** * Initializes this key agreement with the given key, set of * algorithm parameters, and source of randomness. * * @param key the party's private information. For example, in the case * of the Diffie-Hellman key agreement, this would be the party's own * Diffie-Hellman private key. * @param params the key agreement parameters * @param random the source of randomness * * @exception InvalidKeyException if the given key is * inappropriate for this key agreement, e.g., is of the wrong type or * has an incompatible algorithm type. * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key agreement. */ protected abstract void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * Executes the next phase of this key agreement with the given * key that was received from one of the other parties involved in this key * agreement. * * @param key the key for this phase. For example, in the case of * Diffie-Hellman between 2 parties, this would be the other party's * Diffie-Hellman public key. * @param lastPhase flag which indicates whether or not this is the last * phase of this key agreement. * * @return the (intermediate) key resulting from this phase, or null if * this phase does not yield a key * * @exception InvalidKeyException if the given key is inappropriate for * this phase. * @exception IllegalStateException if this key agreement has not been * initialized. */ protected abstract Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException; /** * Generates the shared secret and returns it in a new buffer. * *

This method resets this KeyAgreementSpi object, * so that it * can be reused for further key agreements. Unless this key agreement is * reinitialized with one of the engineInit methods, the same * private information and algorithm parameters will be used for * subsequent key agreements. * * @return the new buffer with the shared secret * * @exception IllegalStateException if this key agreement has not been * completed yet */ protected abstract byte[] engineGenerateSecret() throws IllegalStateException; /** * Generates the shared secret, and places it into the buffer * sharedSecret, beginning at offset inclusive. * *

If the sharedSecret buffer is too small to hold the * result, a ShortBufferException is thrown. * In this case, this call should be repeated with a larger output buffer. * *

This method resets this KeyAgreementSpi object, * so that it * can be reused for further key agreements. Unless this key agreement is * reinitialized with one of the engineInit methods, the same * private information and algorithm parameters will be used for * subsequent key agreements. * * @param sharedSecret the buffer for the shared secret * @param offset the offset in sharedSecret where the * shared secret will be stored * * @return the number of bytes placed into sharedSecret * * @exception IllegalStateException if this key agreement has not been * completed yet * @exception ShortBufferException if the given output buffer is too small * to hold the secret */ protected abstract int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException; /** * Creates the shared secret and returns it as a secret key object * of the requested algorithm type. * *

This method resets this KeyAgreementSpi object, * so that it * can be reused for further key agreements. Unless this key agreement is * reinitialized with one of the engineInit methods, the same * private information and algorithm parameters will be used for * subsequent key agreements. * * @param algorithm the requested secret key algorithm * * @return the shared secret key * * @exception IllegalStateException if this key agreement has not been * completed yet * @exception NoSuchAlgorithmException if the requested secret key * algorithm is not available * @exception InvalidKeyException if the shared secret key material cannot * be used to generate a secret key of the requested algorithm type (e.g., * the key material is too short) */ protected abstract SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException; } clean-crypto-1/src/main/java/javax/crypto/KeyGenerator.java0000664000175000017500000004526011370332423024032 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.*; import java.security.*; import java.security.Provider.Service; import java.security.spec.*; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * This class provides the functionality of a secret (symmetric) key generator. * *

Key generators are constructed using one of the getInstance * class methods of this class. * *

KeyGenerator objects are reusable, i.e., after a key has been * generated, the same KeyGenerator object can be re-used to generate further * keys. * *

There are two ways to generate a key: in an algorithm-independent * manner, and in an algorithm-specific manner. * The only difference between the two is the initialization of the object: * *

    *
  • Algorithm-Independent Initialization *

    All key generators share the concepts of a keysize and a * source of randomness. * There is an * {@link #init(int, java.security.SecureRandom) init} * method in this KeyGenerator class that takes these two universally * shared types of arguments. There is also one that takes just a * keysize argument, and uses the SecureRandom implementation * of the highest-priority installed provider as the source of randomness * (or a system-provided source of randomness if none of the installed * providers supply a SecureRandom implementation), and one that takes just a * source of randomness. * *

    Since no other parameters are specified when you call the above * algorithm-independent init methods, it is up to the * provider what to do about the algorithm-specific parameters (if any) to be * associated with each of the keys. *

    * *

  • Algorithm-Specific Initialization *

    For situations where a set of algorithm-specific parameters already * exists, there are two * {@link #init(java.security.spec.AlgorithmParameterSpec) init} * methods that have an AlgorithmParameterSpec * argument. One also has a SecureRandom argument, while the * other uses the SecureRandom implementation * of the highest-priority installed provider as the source of randomness * (or a system-provided source of randomness if none of the installed * providers supply a SecureRandom implementation). *

* *

In case the client does not explicitly initialize the KeyGenerator * (via a call to an init method), each provider must * supply (and document) a default initialization. * * @author Jan Luehe * * @see SecretKey * @since 1.4 */ public class KeyGenerator { // see java.security.KeyPairGenerator for failover notes private final static int I_NONE = 1; private final static int I_RANDOM = 2; private final static int I_PARAMS = 3; private final static int I_SIZE = 4; // The provider private Provider provider; // The provider implementation (delegate) private volatile KeyGeneratorSpi spi; // The algorithm private final String algorithm; private final Object lock = new Object(); private Iterator serviceIterator; private int initType; private int initKeySize; private AlgorithmParameterSpec initParams; private SecureRandom initRandom; /** * Creates a KeyGenerator object. * * @param keyGenSpi the delegate * @param provider the provider * @param algorithm the algorithm */ protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider, String algorithm) { this.spi = keyGenSpi; this.provider = provider; this.algorithm = algorithm; } private KeyGenerator(String algorithm) throws NoSuchAlgorithmException { this.algorithm = algorithm; List list = GetInstance.getServices("KeyGenerator", algorithm); serviceIterator = list.iterator(); initType = I_NONE; // fetch and instantiate initial spi if (nextSpi(null, false) == null) { throw new NoSuchAlgorithmException (algorithm + " KeyGenerator not available"); } } /** * Returns the algorithm name of this KeyGenerator object. * *

This is the same name that was specified in one of the * getInstance calls that created this * KeyGenerator object. * * @return the algorithm name of this KeyGenerator object. */ public final String getAlgorithm() { return this.algorithm; } /** * Returns a KeyGenerator object that generates secret keys * for the specified algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new KeyGenerator object encapsulating the * KeyGeneratorSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested key algorithm. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @return the new KeyGenerator object. * * @exception NullPointerException if the specified algorithm is null. * * @exception NoSuchAlgorithmException if no Provider supports a * KeyGeneratorSpi implementation for the * specified algorithm. * * @see java.security.Provider */ public static final KeyGenerator getInstance(String algorithm) throws NoSuchAlgorithmException { return new KeyGenerator(algorithm); } /** * Returns a KeyGenerator object that generates secret keys * for the specified algorithm. * *

A new KeyGenerator object encapsulating the * KeyGeneratorSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested key algorithm. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new KeyGenerator object. * * @exception NullPointerException if the specified algorithm is null. * * @exception NoSuchAlgorithmException if a KeyGeneratorSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider * is null or empty. * * @see java.security.Provider */ public static final KeyGenerator getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = JceSecurity.getInstance("KeyGenerator", KeyGeneratorSpi.class, algorithm, provider); return new KeyGenerator((KeyGeneratorSpi)instance.impl, instance.provider, algorithm); } /** * Returns a KeyGenerator object that generates secret keys * for the specified algorithm. * *

A new KeyGenerator object encapsulating the * KeyGeneratorSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the standard name of the requested key algorithm. * See Appendix A in the * * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the provider. * * @return the new KeyGenerator object. * * @exception NullPointerException if the specified algorithm is null. * * @exception NoSuchAlgorithmException if a KeyGeneratorSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider * is null. * * @see java.security.Provider */ public static final KeyGenerator getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = JceSecurity.getInstance("KeyGenerator", KeyGeneratorSpi.class, algorithm, provider); return new KeyGenerator((KeyGeneratorSpi)instance.impl, instance.provider, algorithm); } /** * Returns the provider of this KeyGenerator object. * * @return the provider of this KeyGenerator object */ public final Provider getProvider() { synchronized (lock) { disableFailover(); return provider; } } /** * Update the active spi of this class and return the next * implementation for failover. If no more implemenations are * available, this method returns null. However, the active spi of * this class is never set to null. */ private KeyGeneratorSpi nextSpi(KeyGeneratorSpi oldSpi, boolean reinit) { synchronized (lock) { // somebody else did a failover concurrently // try that spi now if ((oldSpi != null) && (oldSpi != spi)) { return spi; } if (serviceIterator == null) { return null; } while (serviceIterator.hasNext()) { Service s = (Service)serviceIterator.next(); if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } try { Object inst = s.newInstance(null); // ignore non-spis if (inst instanceof KeyGeneratorSpi == false) { continue; } KeyGeneratorSpi spi = (KeyGeneratorSpi)inst; if (reinit) { if (initType == I_SIZE) { spi.engineInit(initKeySize, initRandom); } else if (initType == I_PARAMS) { spi.engineInit(initParams, initRandom); } else if (initType == I_RANDOM) { spi.engineInit(initRandom); } else if (initType != I_NONE) { throw new AssertionError ("KeyGenerator initType: " + initType); } } provider = s.getProvider(); this.spi = spi; return spi; } catch (Exception e) { // ignore } } disableFailover(); return null; } } void disableFailover() { serviceIterator = null; initType = 0; initParams = null; initRandom = null; } /** * Initializes this key generator. * * @param random the source of randomness for this generator */ public final void init(SecureRandom random) { if (serviceIterator == null) { spi.engineInit(random); return; } RuntimeException failure = null; KeyGeneratorSpi mySpi = spi; do { try { mySpi.engineInit(random); initType = I_RANDOM; initKeySize = 0; initParams = null; initRandom = random; return; } catch (RuntimeException e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, false); } } while (mySpi != null); throw failure; } /** * Initializes this key generator with the specified parameter set. * *

If this key generator requires any random bytes, it will get them * using the * {@link SecureRandom SecureRandom} * implementation of the highest-priority installed * provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * @param params the key generation parameters * * @exception InvalidAlgorithmParameterException if the given parameters * are inappropriate for this key generator */ public final void init(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { init(params, JceSecurity.RANDOM); } /** * Initializes this key generator with the specified parameter * set and a user-provided source of randomness. * * @param params the key generation parameters * @param random the source of randomness for this key generator * * @exception InvalidAlgorithmParameterException if params is * inappropriate for this key generator */ public final void init(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (serviceIterator == null) { spi.engineInit(params, random); return; } Exception failure = null; KeyGeneratorSpi mySpi = spi; do { try { mySpi.engineInit(params, random); initType = I_PARAMS; initKeySize = 0; initParams = params; initRandom = random; return; } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, false); } } while (mySpi != null); if (failure instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)failure; } if (failure instanceof RuntimeException) { throw (RuntimeException)failure; } throw new InvalidAlgorithmParameterException("init() failed", failure); } /** * Initializes this key generator for a certain keysize. * *

If this key generator requires any random bytes, it will get them * using the * {@link SecureRandom SecureRandom} * implementation of the highest-priority installed * provider as the source of randomness. * (If none of the installed providers supply an implementation of * SecureRandom, a system-provided source of randomness will be used.) * * @param keysize the keysize. This is an algorithm-specific metric, * specified in number of bits. * * @exception InvalidParameterException if the keysize is wrong or not * supported. */ public final void init(int keysize) { init(keysize, JceSecurity.RANDOM); } /** * Initializes this key generator for a certain keysize, using a * user-provided source of randomness. * * @param keysize the keysize. This is an algorithm-specific metric, * specified in number of bits. * @param random the source of randomness for this key generator * * @exception InvalidParameterException if the keysize is wrong or not * supported. */ public final void init(int keysize, SecureRandom random) { if (serviceIterator == null) { spi.engineInit(keysize, random); return; } RuntimeException failure = null; KeyGeneratorSpi mySpi = spi; do { try { mySpi.engineInit(keysize, random); initType = I_SIZE; initKeySize = keysize; initParams = null; initRandom = random; return; } catch (RuntimeException e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, false); } } while (mySpi != null); throw failure; } /** * Generates a secret key. * * @return the new key */ public final SecretKey generateKey() { if (serviceIterator == null) { return spi.engineGenerateKey(); } RuntimeException failure = null; KeyGeneratorSpi mySpi = spi; do { try { return mySpi.engineGenerateKey(); } catch (RuntimeException e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi, true); } } while (mySpi != null); throw failure; } } clean-crypto-1/src/main/java/javax/crypto/KeyGeneratorSpi.java0000664000175000017500000000601511370332423024501 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.security.spec.*; /** * This class defines the Service Provider Interface (SPI) * for the KeyGenerator class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a key generator for a particular algorithm. * * @author Jan Luehe * * @see SecretKey * @since 1.4 */ public abstract class KeyGeneratorSpi { /** * Initializes the key generator. * * @param random the source of randomness for this generator */ protected abstract void engineInit(SecureRandom random); /** * Initializes the key generator with the specified parameter * set and a user-provided source of randomness. * * @param params the key generation parameters * @param random the source of randomness for this key generator * * @exception InvalidAlgorithmParameterException if params is * inappropriate for this key generator */ protected abstract void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException; /** * Initializes this key generator for a certain keysize, using the given * source of randomness. * * @param keysize the keysize. This is an algorithm-specific metric, * specified in number of bits. * @param random the source of randomness for this key generator * * @exception InvalidParameterException if the keysize is wrong or not * supported. */ protected abstract void engineInit(int keysize, SecureRandom random); /** * Generates a secret key. * * @return the new key */ protected abstract SecretKey engineGenerateKey(); } clean-crypto-1/src/main/java/javax/crypto/Mac.java0000664000175000017500000005562411370332423022140 0ustar moellermoeller/* * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.*; import java.security.*; import java.security.Provider.Service; import java.security.spec.AlgorithmParameterSpec; import java.nio.ByteBuffer; import sun.security.util.Debug; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * This class provides the functionality of a "Message Authentication Code" * (MAC) algorithm. * *

A MAC provides a way to check * the integrity of information transmitted over or stored in an unreliable * medium, based on a secret key. Typically, message * authentication codes are used between two parties that share a secret * key in order to validate information transmitted between these * parties. * *

A MAC mechanism that is based on cryptographic hash functions is * referred to as HMAC. HMAC can be used with any cryptographic hash function, * e.g., MD5 or SHA-1, in combination with a secret shared key. HMAC is * specified in RFC 2104. * * @author Jan Luehe * * @since 1.4 */ public class Mac implements Cloneable { private static final Debug debug = Debug.getInstance("jca", "Mac"); // The provider private Provider provider; // The provider implementation (delegate) private MacSpi spi; // The name of the MAC algorithm. private final String algorithm; // Has this object been initialized? private boolean initialized = false; // next service to try in provider selection // null once provider is selected private Service firstService; // remaining services to try in provider selection // null once provider is selected private Iterator serviceIterator; private final Object lock; /** * Creates a MAC object. * * @param macSpi the delegate * @param provider the provider * @param algorithm the algorithm */ protected Mac(MacSpi macSpi, Provider provider, String algorithm) { this.spi = macSpi; this.provider = provider; this.algorithm = algorithm; serviceIterator = null; lock = null; } private Mac(Service s, Iterator t, String algorithm) { firstService = s; serviceIterator = t; this.algorithm = algorithm; lock = new Object(); } /** * Returns the algorithm name of this Mac object. * *

This is the same name that was specified in one of the * getInstance calls that created this * Mac object. * * @return the algorithm name of this Mac object. */ public final String getAlgorithm() { return this.algorithm; } /** * Returns a Mac object that implements the * specified MAC algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new Mac object encapsulating the * MacSpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested MAC algorithm. * See Appendix A in the * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @return the new Mac object. * * @exception NoSuchAlgorithmException if no Provider supports a * MacSpi implementation for the * specified algorithm. * * @see java.security.Provider */ public static final Mac getInstance(String algorithm) throws NoSuchAlgorithmException { List services = GetInstance.getServices("Mac", algorithm); // make sure there is at least one service from a signed provider Iterator t = services.iterator(); while (t.hasNext()) { Service s = (Service)t.next(); if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } return new Mac(s, t, algorithm); } throw new NoSuchAlgorithmException ("Algorithm " + algorithm + " not available"); } /** * Returns a Mac object that implements the * specified MAC algorithm. * *

A new Mac object encapsulating the * MacSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested MAC algorithm. * See Appendix A in the * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new Mac object. * * @exception NoSuchAlgorithmException if a MacSpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider * is null or empty. * * @see java.security.Provider */ public static final Mac getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = JceSecurity.getInstance ("Mac", MacSpi.class, algorithm, provider); return new Mac((MacSpi)instance.impl, instance.provider, algorithm); } /** * Returns a Mac object that implements the * specified MAC algorithm. * *

A new Mac object encapsulating the * MacSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the standard name of the requested MAC algorithm. * See Appendix A in the * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the provider. * * @return the new Mac object. * * @exception NoSuchAlgorithmException if a MacSpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider * is null. * * @see java.security.Provider */ public static final Mac getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = JceSecurity.getInstance ("Mac", MacSpi.class, algorithm, provider); return new Mac((MacSpi)instance.impl, instance.provider, algorithm); } // max number of debug warnings to print from chooseFirstProvider() private static int warnCount = 10; /** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because init() * is not the first method called. */ void chooseFirstProvider() { if ((spi != null) || (serviceIterator == null)) { return; } synchronized (lock) { if (spi != null) { return; } if (debug != null) { int w = --warnCount; if (w >= 0) { debug.println("Mac.init() not first method " + "called, disabling delayed provider selection"); if (w == 0) { debug.println("Further warnings of this type will " + "be suppressed"); } new Exception("Call trace").printStackTrace(); } } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; if (firstService != null) { s = firstService; firstService = null; } else { s = (Service)serviceIterator.next(); } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } try { Object obj = s.newInstance(null); if (obj instanceof MacSpi == false) { continue; } spi = (MacSpi)obj; provider = s.getProvider(); // not needed any more firstService = null; serviceIterator = null; return; } catch (NoSuchAlgorithmException e) { lastException = e; } } ProviderException e = new ProviderException ("Could not construct MacSpi instance"); if (lastException != null) { e.initCause(lastException); } throw e; } } private void chooseProvider(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { synchronized (lock) { if (spi != null) { spi.engineInit(key, params); return; } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; if (firstService != null) { s = firstService; firstService = null; } else { s = (Service)serviceIterator.next(); } // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue; } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } try { MacSpi spi = (MacSpi)s.newInstance(null); spi.engineInit(key, params); provider = s.getProvider(); this.spi = spi; firstService = null; serviceIterator = null; return; } catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() if (lastException == null) { lastException = e; } } } // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException; } if (lastException instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)lastException; } if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException; } String kName = (key != null) ? key.getClass().getName() : "(null)"; throw new InvalidKeyException ("No installed provider supports this key: " + kName, lastException); } } /** * Returns the provider of this Mac object. * * @return the provider of this Mac object. */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } /** * Returns the length of the MAC in bytes. * * @return the MAC length in bytes. */ public final int getMacLength() { chooseFirstProvider(); return spi.engineGetMacLength(); } /** * Initializes this Mac object with the given key. * * @param key the key. * * @exception InvalidKeyException if the given key is inappropriate for * initializing this MAC. */ public final void init(Key key) throws InvalidKeyException { try { if (spi != null) { spi.engineInit(key, null); } else { chooseProvider(key, null); } } catch (InvalidAlgorithmParameterException e) { throw new InvalidKeyException("init() failed", e); } initialized = true; } /** * Initializes this Mac object with the given key and * algorithm parameters. * * @param key the key. * @param params the algorithm parameters. * * @exception InvalidKeyException if the given key is inappropriate for * initializing this MAC. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this MAC. */ public final void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { if (spi != null) { spi.engineInit(key, params); } else { chooseProvider(key, params); } initialized = true; } /** * Processes the given byte. * * @param input the input byte to be processed. * * @exception IllegalStateException if this Mac has not been * initialized. */ public final void update(byte input) throws IllegalStateException { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } spi.engineUpdate(input); } /** * Processes the given array of bytes. * * @param input the array of bytes to be processed. * * @exception IllegalStateException if this Mac has not been * initialized. */ public final void update(byte[] input) throws IllegalStateException { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } if (input != null) { spi.engineUpdate(input, 0, input.length); } } /** * Processes the first len bytes in input, * starting at offset inclusive. * * @param input the input buffer. * @param offset the offset in input where the input starts. * @param len the number of bytes to process. * * @exception IllegalStateException if this Mac has not been * initialized. */ public final void update(byte[] input, int offset, int len) throws IllegalStateException { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } if (input != null) { if ((offset < 0) || (len > (input.length - offset)) || (len < 0)) throw new IllegalArgumentException("Bad arguments"); spi.engineUpdate(input, offset, len); } } /** * Processes input.remaining() bytes in the ByteBuffer * input, starting at input.position(). * Upon return, the buffer's position will be equal to its limit; * its limit will not have changed. * * @param input the ByteBuffer * * @exception IllegalStateException if this Mac has not been * initialized. * @since 1.5 */ public final void update(ByteBuffer input) { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } if (input == null) { throw new IllegalArgumentException("Buffer must not be null"); } spi.engineUpdate(input); } /** * Finishes the MAC operation. * *

A call to this method resets this Mac object to the * state it was in when previously initialized via a call to * init(Key) or * init(Key, AlgorithmParameterSpec). * That is, the object is reset and available to generate another MAC from * the same key, if desired, via new calls to update and * doFinal. * (In order to reuse this Mac object with a different key, * it must be reinitialized via a call to init(Key) or * init(Key, AlgorithmParameterSpec). * * @return the MAC result. * * @exception IllegalStateException if this Mac has not been * initialized. */ public final byte[] doFinal() throws IllegalStateException { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } byte[] mac = spi.engineDoFinal(); spi.engineReset(); return mac; } /** * Finishes the MAC operation. * *

A call to this method resets this Mac object to the * state it was in when previously initialized via a call to * init(Key) or * init(Key, AlgorithmParameterSpec). * That is, the object is reset and available to generate another MAC from * the same key, if desired, via new calls to update and * doFinal. * (In order to reuse this Mac object with a different key, * it must be reinitialized via a call to init(Key) or * init(Key, AlgorithmParameterSpec). * *

The MAC result is stored in output, starting at * outOffset inclusive. * * @param output the buffer where the MAC result is stored * @param outOffset the offset in output where the MAC is * stored * * @exception ShortBufferException if the given output buffer is too small * to hold the result * @exception IllegalStateException if this Mac has not been * initialized. */ public final void doFinal(byte[] output, int outOffset) throws ShortBufferException, IllegalStateException { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } int macLen = getMacLength(); if (output == null || output.length-outOffset < macLen) { throw new ShortBufferException ("Cannot store MAC in output buffer"); } byte[] mac = doFinal(); System.arraycopy(mac, 0, output, outOffset, macLen); return; } /** * Processes the given array of bytes and finishes the MAC operation. * *

A call to this method resets this Mac object to the * state it was in when previously initialized via a call to * init(Key) or * init(Key, AlgorithmParameterSpec). * That is, the object is reset and available to generate another MAC from * the same key, if desired, via new calls to update and * doFinal. * (In order to reuse this Mac object with a different key, * it must be reinitialized via a call to init(Key) or * init(Key, AlgorithmParameterSpec). * * @param input data in bytes * @return the MAC result. * * @exception IllegalStateException if this Mac has not been * initialized. */ public final byte[] doFinal(byte[] input) throws IllegalStateException { chooseFirstProvider(); if (initialized == false) { throw new IllegalStateException("MAC not initialized"); } update(input); return doFinal(); } /** * Resets this Mac object. * *

A call to this method resets this Mac object to the * state it was in when previously initialized via a call to * init(Key) or * init(Key, AlgorithmParameterSpec). * That is, the object is reset and available to generate another MAC from * the same key, if desired, via new calls to update and * doFinal. * (In order to reuse this Mac object with a different key, * it must be reinitialized via a call to init(Key) or * init(Key, AlgorithmParameterSpec). */ public final void reset() { chooseFirstProvider(); spi.engineReset(); } /** * Returns a clone if the provider implementation is cloneable. * * @return a clone if the provider implementation is cloneable. * * @exception CloneNotSupportedException if this is called on a * delegate that does not support Cloneable. */ public final Object clone() throws CloneNotSupportedException { chooseFirstProvider(); Mac that = (Mac)super.clone(); that.spi = (MacSpi)this.spi.clone(); return that; } } clean-crypto-1/src/main/java/javax/crypto/MacSpi.java0000664000175000017500000001216211370332423022602 0ustar moellermoeller/* * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.security.spec.*; import java.nio.ByteBuffer; /** * This class defines the Service Provider Interface (SPI) * for the Mac class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a particular MAC algorithm. * *

Implementations are free to implement the Cloneable interface. * * @author Jan Luehe * * @since 1.4 */ public abstract class MacSpi { /** * Returns the length of the MAC in bytes. * * @return the MAC length in bytes. */ protected abstract int engineGetMacLength(); /** * Initializes the MAC with the given (secret) key and algorithm * parameters. * * @param key the (secret) key. * @param params the algorithm parameters. * * @exception InvalidKeyException if the given key is inappropriate for * initializing this MAC. * @exception InvalidAlgorithmParameterException if the given algorithm * parameters are inappropriate for this MAC. */ protected abstract void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException ; /** * Processes the given byte. * * @param input the input byte to be processed. */ protected abstract void engineUpdate(byte input); /** * Processes the first len bytes in input, * starting at offset inclusive. * * @param input the input buffer. * @param offset the offset in input where the input starts. * @param len the number of bytes to process. */ protected abstract void engineUpdate(byte[] input, int offset, int len); /** * Processes input.remaining() bytes in the ByteBuffer * input, starting at input.position(). * Upon return, the buffer's position will be equal to its limit; * its limit will not have changed. * *

Subclasses should consider overriding this method if they can * process ByteBuffers more efficiently than byte arrays. * * @param input the ByteBuffer * @since 1.5 */ protected void engineUpdate(ByteBuffer input) { if (input.hasRemaining() == false) { return; } if (input.hasArray()) { byte[] b = input.array(); int ofs = input.arrayOffset(); int pos = input.position(); int lim = input.limit(); engineUpdate(b, ofs + pos, lim - pos); input.position(lim); } else { int len = input.remaining(); byte[] b = new byte[CipherSpi.getTempArraySize(len)]; while (len > 0) { int chunk = Math.min(len, b.length); input.get(b, 0, chunk); engineUpdate(b, 0, chunk); len -= chunk; } } } /** * Completes the MAC computation and resets the MAC for further use, * maintaining the secret key that the MAC was initialized with. * * @return the MAC result. */ protected abstract byte[] engineDoFinal(); /** * Resets the MAC for further use, maintaining the secret key that the * MAC was initialized with. */ protected abstract void engineReset(); /** * Returns a clone if the implementation is cloneable. * * @return a clone if the implementation is cloneable. * * @exception CloneNotSupportedException if this is called * on an implementation that does not support Cloneable. */ public Object clone() throws CloneNotSupportedException { if (this instanceof Cloneable) { return super.clone(); } else { throw new CloneNotSupportedException(); } } } clean-crypto-1/src/main/java/javax/crypto/NoSuchPaddingException.java0000664000175000017500000000377611370332423026006 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.GeneralSecurityException; /** * This exception is thrown when a particular padding mechanism is * requested but is not available in the environment. * * @author Jan Luehe * * @since 1.4 */ public class NoSuchPaddingException extends GeneralSecurityException { private static final long serialVersionUID = -4572885201200175466L; /** * Constructs a NoSuchPaddingException with no detail * message. A detail message is a String that describes this * particular exception. */ public NoSuchPaddingException() { super(); } /** * Constructs a NoSuchPaddingException with the specified * detail message. * * @param msg the detail message. */ public NoSuchPaddingException(String msg) { super(msg); } } clean-crypto-1/src/main/java/javax/crypto/NullCipher.java0000664000175000017500000000320011370332423023464 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; /** * The NullCipher class is a class that provides an * "identity cipher" -- one that does not tranform the plaintext. As * a consequence, the ciphertext is identical to the plaintext. All * initialization methods do nothing, while the blocksize is set to 1 * byte. * * @author Li Gong * @since 1.4 */ public class NullCipher extends Cipher { public NullCipher() { super(new NullCipherSpi(), null); } } clean-crypto-1/src/main/java/javax/crypto/NullCipherSpi.java0000664000175000017500000000703311370332423024150 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.security.spec.*; /** * This class provides a delegate for the identity cipher - one that does not * tranform the plaintext. * * @author Li Gong * @see Nullcipher * * @since 1.4 */ final class NullCipherSpi extends CipherSpi { /* * Do not let anybody instantiate this directly (protected). */ protected NullCipherSpi() {} public void engineSetMode(String mode) {} public void engineSetPadding(String padding) {} protected int engineGetBlockSize() { return 1; } protected int engineGetOutputSize(int inputLen) { return inputLen; } protected byte[] engineGetIV() { byte[] x = new byte[8]; return x; } protected AlgorithmParameters engineGetParameters() { return null; } protected void engineInit(int mode, Key key, SecureRandom random) {} protected void engineInit(int mode, Key key, AlgorithmParameterSpec params, 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 null; byte[] x = new byte[inputLen]; System.arraycopy(input, inputOffset, x, 0, inputLen); return x; } protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) { if (input == null) return 0; 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) { return engineUpdate(input, inputOffset, inputLen, output, outputOffset); } protected int engineGetKeySize(Key key) { return 0; } } clean-crypto-1/src/main/java/javax/crypto/SealedObject.java0000664000175000017500000004273111370332423023757 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.io.*; import java.security.AlgorithmParameters; import java.security.Key; import java.security.InvalidKeyException; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; /** * This class enables a programmer to create an object and protect its * confidentiality with a cryptographic algorithm. * *

Given any Serializable object, one can create a SealedObject * that encapsulates the original object, in serialized * format (i.e., a "deep copy"), and seals (encrypts) its serialized contents, * using a cryptographic algorithm such as DES, to protect its * confidentiality. The encrypted content can later be decrypted (with * the corresponding algorithm using the correct decryption key) and * de-serialized, yielding the original object. * *

Note that the Cipher object must be fully initialized with the * correct algorithm, key, padding scheme, etc., before being applied * to a SealedObject. * *

The original object that was sealed can be recovered in two different * ways:

* *

    * *
  • by using the {@link #getObject(javax.crypto.Cipher) getObject} * method that takes a Cipher object. * *

    This method requires a fully initialized Cipher object, * initialized with the * exact same algorithm, key, padding scheme, etc., that were used to seal the * object. * *

    This approach has the advantage that the party who unseals the * sealed object does not require knowledge of the decryption key. For example, * after one party has initialized the cipher object with the required * decryption key, it could hand over the cipher object to * another party who then unseals the sealed object. * *

    * *

  • by using one of the * {@link #getObject(java.security.Key) getObject} methods * that take a Key object. * *

    In this approach, the getObject method creates a cipher * object for the appropriate decryption algorithm and initializes it with the * given decryption key and the algorithm parameters (if any) that were stored * in the sealed object. * *

    This approach has the advantage that the party who * unseals the object does not need to keep track of the parameters (e.g., an * IV) that were used to seal the object. * *

* * @author Li Gong * @author Jan Luehe * @see Cipher * @since 1.4 */ public class SealedObject implements Serializable { static final long serialVersionUID = 4482838265551344752L; /** * The serialized object contents in encrypted format. * * @serial */ private byte[] encryptedContent = null; /** * The algorithm that was used to seal this object. * * @serial */ private String sealAlg = null; /** * The algorithm of the parameters used. * * @serial */ private String paramsAlg = null; /** * The cryptographic parameters used by the sealing Cipher, * encoded in the default format. *

* That is, cipher.getParameters().getEncoded(). * * @serial */ protected byte[] encodedParams = null; /** * Constructs a SealedObject from any Serializable object. * *

The given object is serialized, and its serialized contents are * encrypted using the given Cipher, which must be fully initialized. * *

Any algorithm parameters that may be used in the encryption * operation are stored inside of the new SealedObject. * * @param object the object to be sealed; can be null. * @param c the cipher used to seal the object. * * @exception NullPointerException if the given cipher is null. * @exception IOException if an error occurs during serialization * @exception IllegalBlockSizeException if the given cipher is a block * cipher, no padding has been requested, and the total input length * (i.e., the length of the serialized object contents) is not a multiple * of the cipher's block size */ public SealedObject(Serializable object, Cipher c) throws IOException, IllegalBlockSizeException { /* * Serialize the object */ // creating a stream pipe-line, from a to b ByteArrayOutputStream b = new ByteArrayOutputStream(); ObjectOutput a = new ObjectOutputStream(b); byte[] content; try { // write and flush the object content to byte array a.writeObject(object); a.flush(); content = b.toByteArray(); } finally { a.close(); } /* * Seal the object */ try { this.encryptedContent = c.doFinal(content); } catch (BadPaddingException ex) { // if sealing is encryption only // Should never happen?? } // Save the parameters if (c.getParameters() != null) { this.encodedParams = c.getParameters().getEncoded(); this.paramsAlg = c.getParameters().getAlgorithm(); } // Save the encryption algorithm this.sealAlg = c.getAlgorithm(); } /** * Constructs a SealedObject object from the passed-in SealedObject. * * @param so a SealedObject object * @exception NullPointerException if the given sealed object is null. */ protected SealedObject(SealedObject so) { this.encryptedContent = (byte[]) so.encryptedContent.clone(); this.sealAlg = so.sealAlg; this.paramsAlg = so.paramsAlg; if (so.encodedParams != null) { this.encodedParams = (byte[]) so.encodedParams.clone(); } else { this.encodedParams = null; } } /** * Returns the algorithm that was used to seal this object. * * @return the algorithm that was used to seal this object. */ public final String getAlgorithm() { return this.sealAlg; } /** * Retrieves the original (encapsulated) object. * *

This method creates a cipher for the algorithm that had been used in * the sealing operation. * If the default provider package provides an implementation of that * algorithm, an instance of Cipher containing that implementation is used. * If the algorithm is not available in the default package, other * packages are searched. * The Cipher object is initialized for decryption, using the given * key and the parameters (if any) that had been used in the * sealing operation. * *

The encapsulated object is unsealed and de-serialized, before it is * returned. * * @param key the key used to unseal the object. * * @return the original object. * * @exception IOException if an error occurs during de-serialiazation. * @exception ClassNotFoundException if an error occurs during * de-serialiazation. * @exception NoSuchAlgorithmException if the algorithm to unseal the * object is not available. * @exception InvalidKeyException if the given key cannot be used to unseal * the object (e.g., it has the wrong algorithm). * @exception NullPointerException if key is null. */ public final Object getObject(Key key) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeyException { if (key == null) { throw new NullPointerException("key is null"); } try { return unseal(key, null); } catch (NoSuchProviderException nspe) { // we've already caught NoSuchProviderException's and converted // them into NoSuchAlgorithmException's with details about // the failing algorithm throw new NoSuchAlgorithmException("algorithm not found"); } catch (IllegalBlockSizeException ibse) { throw new InvalidKeyException(ibse.getMessage()); } catch (BadPaddingException bpe) { throw new InvalidKeyException(bpe.getMessage()); } } /** * Retrieves the original (encapsulated) object. * *

The encapsulated object is unsealed (using the given Cipher, * assuming that the Cipher is already properly initialized) and * de-serialized, before it is returned. * * @param c the cipher used to unseal the object * * @return the original object. * * @exception NullPointerException if the given cipher is null. * @exception IOException if an error occurs during de-serialiazation * @exception ClassNotFoundException if an error occurs during * de-serialiazation * @exception IllegalBlockSizeException if the given cipher is a block * cipher, no padding has been requested, and the total input length is * not a multiple of the cipher's block size * @exception BadPaddingException if the given cipher has been * initialized for decryption, and padding has been specified, but * the input data does not have proper expected padding bytes */ public final Object getObject(Cipher c) throws IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException { /* * Unseal the object */ byte[] content = c.doFinal(this.encryptedContent); /* * De-serialize it */ // creating a stream pipe-line, from b to a ByteArrayInputStream b = new ByteArrayInputStream(content); ObjectInput a = new extObjectInputStream(b); try { Object obj = a.readObject(); return obj; } finally { a.close(); } } /** * Retrieves the original (encapsulated) object. * *

This method creates a cipher for the algorithm that had been used in * the sealing operation, using an implementation of that algorithm from * the given provider. * The Cipher object is initialized for decryption, using the given * key and the parameters (if any) that had been used in the * sealing operation. * *

The encapsulated object is unsealed and de-serialized, before it is * returned. * * @param key the key used to unseal the object. * @param provider the name of the provider of the algorithm to unseal * the object. * * @return the original object. * * @exception IllegalArgumentException if the given provider is null * or empty. * @exception IOException if an error occurs during de-serialiazation. * @exception ClassNotFoundException if an error occurs during * de-serialiazation. * @exception NoSuchAlgorithmException if the algorithm to unseal the * object is not available. * @exception NoSuchProviderException if the given provider is not * configured. * @exception InvalidKeyException if the given key cannot be used to unseal * the object (e.g., it has the wrong algorithm). * @exception NullPointerException if key is null. */ public final Object getObject(Key key, String provider) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException { if (key == null) { throw new NullPointerException("key is null"); } if (provider == null || provider.length() == 0) { throw new IllegalArgumentException("missing provider"); } try { return unseal(key, provider); } catch (IllegalBlockSizeException ibse) { throw new InvalidKeyException(ibse.getMessage()); } catch (BadPaddingException bpe) { throw new InvalidKeyException(bpe.getMessage()); } } private Object unseal(Key key, String provider) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { /* * Create the parameter object. */ AlgorithmParameters params = null; if (this.encodedParams != null) { try { if (provider != null) params = AlgorithmParameters.getInstance(this.paramsAlg, provider); else params = AlgorithmParameters.getInstance(this.paramsAlg); } catch (NoSuchProviderException nspe) { if (provider == null) { throw new NoSuchAlgorithmException(this.paramsAlg + " not found"); } else { throw new NoSuchProviderException(nspe.getMessage()); } } params.init(this.encodedParams); } /* * Create and initialize the cipher. */ Cipher c; try { if (provider != null) c = Cipher.getInstance(this.sealAlg, provider); else c = Cipher.getInstance(this.sealAlg); } catch (NoSuchPaddingException nspe) { throw new NoSuchAlgorithmException("Padding that was used in " + "sealing operation not " + "available"); } catch (NoSuchProviderException nspe) { if (provider == null) { throw new NoSuchAlgorithmException(this.sealAlg+" not found"); } else { throw new NoSuchProviderException(nspe.getMessage()); } } try { if (params != null) c.init(Cipher.DECRYPT_MODE, key, params); else c.init(Cipher.DECRYPT_MODE, key); } catch (InvalidAlgorithmParameterException iape) { // this should never happen, because we use the exact same // parameters that were used in the sealing operation throw new RuntimeException(iape.getMessage()); } /* * Unseal the object */ byte[] content = c.doFinal(this.encryptedContent); /* * De-serialize it */ // creating a stream pipe-line, from b to a ByteArrayInputStream b = new ByteArrayInputStream(content); ObjectInput a = new extObjectInputStream(b); try { Object obj = a.readObject(); return obj; } finally { a.close(); } } /** * Restores the state of the SealedObject from a stream. * @param s the object input stream. * @exception NullPointerException if s is null. */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); if (encryptedContent != null) encryptedContent = (byte[])encryptedContent.clone(); if (encodedParams != null) encodedParams = (byte[])encodedParams.clone(); } } final class extObjectInputStream extends ObjectInputStream { private static ClassLoader systemClassLoader = null; extObjectInputStream(InputStream in) throws IOException, StreamCorruptedException { super(in); } protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException { try { /* * Calling the super.resolveClass() first * will let us pick up bug fixes in the super * class (e.g., 4171142). */ return super.resolveClass(v); } catch (ClassNotFoundException cnfe) { /* * This is a workaround for bug 4224921. */ ClassLoader loader = Thread.currentThread().getContextClassLoader(); if (loader == null) { if (systemClassLoader == null) { systemClassLoader = ClassLoader.getSystemClassLoader(); } loader = systemClassLoader; if (loader == null) { throw new ClassNotFoundException(v.getName()); } } return Class.forName(v.getName(), false, loader); } } } clean-crypto-1/src/main/java/javax/crypto/SecretKey.java0000664000175000017500000000450311370332423023324 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; /** * A secret (symmetric) key. * *

This interface contains no methods or constants. * Its only purpose is to group (and provide type safety for) secret keys. * *

Provider implementations of this interface must overwrite the * equals and hashCode methods inherited from * java.lang.Object, so that secret keys are compared based on * their underlying key material and not based on reference. * *

Keys that implement this interface return the string RAW * as their encoding format (see getFormat), and return the * raw key bytes as the result of a getEncoded method call. (The * getFormat and getEncoded methods are inherited * from the java.security.Key parent interface.) * * @author Jan Luehe * * @see SecretKeyFactory * @see Cipher * @since 1.4 */ public interface SecretKey extends java.security.Key { /** * The class fingerprint that is set to indicate serialization * compatibility since J2SE 1.4. */ static final long serialVersionUID = -4795878709595146952L; } clean-crypto-1/src/main/java/javax/crypto/SecretKeyFactory.java0000664000175000017500000003645011370332423024662 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.util.*; import java.security.*; import java.security.Provider.Service; import java.security.spec.*; import sun.security.jca.*; import sun.security.jca.GetInstance.Instance; /** * This class represents a factory for secret keys. * *

Key factories are used to convert keys (opaque * cryptographic keys of type Key) into key specifications * (transparent representations of the underlying key material), and vice * versa. * Secret key factories operate only on secret (symmetric) keys. * *

Key factories are bi-directional, i.e., they allow to build an opaque * key object from a given key specification (key material), or to retrieve * the underlying key material of a key object in a suitable format. * *

Application developers should refer to their provider's documentation * to find out which key specifications are supported by the * {@link #generateSecret(java.security.spec.KeySpec) generateSecret} and * {@link #getKeySpec(javax.crypto.SecretKey, java.lang.Class) getKeySpec} * methods. * For example, the DES secret-key factory supplied by the "SunJCE" provider * supports DESKeySpec as a transparent representation of DES * keys, and that provider's secret-key factory for Triple DES keys supports * DESedeKeySpec as a transparent representation of Triple DES * keys. * * @author Jan Luehe * * @see SecretKey * @see javax.crypto.spec.DESKeySpec * @see javax.crypto.spec.DESedeKeySpec * @see javax.crypto.spec.PBEKeySpec * @since 1.4 */ public class SecretKeyFactory { // The provider private Provider provider; // The algorithm associated with this factory private final String algorithm; // The provider implementation (delegate) private volatile SecretKeyFactorySpi spi; // lock for mutex during provider selection private final Object lock = new Object(); // remaining services to try in provider selection // null once provider is selected private Iterator serviceIterator; /** * Creates a SecretKeyFactory object. * * @param keyFacSpi the delegate * @param provider the provider * @param algorithm the secret-key algorithm */ protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi, Provider provider, String algorithm) { this.spi = keyFacSpi; this.provider = provider; this.algorithm = algorithm; } private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException { this.algorithm = algorithm; List list = GetInstance.getServices("SecretKeyFactory", algorithm); serviceIterator = list.iterator(); // fetch and instantiate initial spi if (nextSpi(null) == null) { throw new NoSuchAlgorithmException (algorithm + " SecretKeyFactory not available"); } } /** * Returns a SecretKeyFactory object that converts * secret keys of the specified algorithm. * *

This method traverses the list of registered security Providers, * starting with the most preferred Provider. * A new SecretKeyFactory object encapsulating the * SecretKeyFactorySpi implementation from the first * Provider that supports the specified algorithm is returned. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested secret-key * algorithm. * See Appendix A in the * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @return the new SecretKeyFactory object. * * @exception NullPointerException if the specified algorithm * is null. * * @exception NoSuchAlgorithmException if no Provider supports a * SecretKeyFactorySpi implementation for the * specified algorithm. * * @see java.security.Provider */ public static final SecretKeyFactory getInstance(String algorithm) throws NoSuchAlgorithmException { return new SecretKeyFactory(algorithm); } /** * Returns a SecretKeyFactory object that converts * secret keys of the specified algorithm. * *

A new SecretKeyFactory object encapsulating the * SecretKeyFactorySpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * *

Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param algorithm the standard name of the requested secret-key * algorithm. * See Appendix A in the * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the name of the provider. * * @return the new SecretKeyFactory object. * * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi * implementation for the specified algorithm is not * available from the specified provider. * * @exception NullPointerException if the specified algorithm * is null. * * @throws NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception IllegalArgumentException if the provider * is null or empty. * * @see java.security.Provider */ public static final SecretKeyFactory getInstance(String algorithm, String provider) throws NoSuchAlgorithmException, NoSuchProviderException { Instance instance = JceSecurity.getInstance("SecretKeyFactory", SecretKeyFactorySpi.class, algorithm, provider); return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl, instance.provider, algorithm); } /** * Returns a SecretKeyFactory object that converts * secret keys of the specified algorithm. * *

A new SecretKeyFactory object encapsulating the * SecretKeyFactorySpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param algorithm the standard name of the requested secret-key * algorithm. * See Appendix A in the * Java Cryptography Architecture Reference Guide * for information about standard algorithm names. * * @param provider the provider. * * @return the new SecretKeyFactory object. * * @exception NullPointerException if the specified algorithm * is null. * * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi * implementation for the specified algorithm is not available * from the specified Provider object. * * @exception IllegalArgumentException if the provider * is null. * * @see java.security.Provider */ public static final SecretKeyFactory getInstance(String algorithm, Provider provider) throws NoSuchAlgorithmException { Instance instance = JceSecurity.getInstance("SecretKeyFactory", SecretKeyFactorySpi.class, algorithm, provider); return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl, instance.provider, algorithm); } /** * Returns the provider of this SecretKeyFactory object. * * @return the provider of this SecretKeyFactory object */ public final Provider getProvider() { synchronized (lock) { // disable further failover after this call serviceIterator = null; return provider; } } /** * Returns the algorithm name of this SecretKeyFactory object. * *

This is the same name that was specified in one of the * getInstance calls that created this * SecretKeyFactory object. * * @return the algorithm name of this SecretKeyFactory * object. */ public final String getAlgorithm() { return this.algorithm; } /** * Update the active spi of this class and return the next * implementation for failover. If no more implemenations are * available, this method returns null. However, the active spi of * this class is never set to null. */ private SecretKeyFactorySpi nextSpi(SecretKeyFactorySpi oldSpi) { synchronized (lock) { // somebody else did a failover concurrently // try that spi now if ((oldSpi != null) && (oldSpi != spi)) { return spi; } if (serviceIterator == null) { return null; } while (serviceIterator.hasNext()) { Service s = (Service)serviceIterator.next(); if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } try { Object obj = s.newInstance(null); if (obj instanceof SecretKeyFactorySpi == false) { continue; } SecretKeyFactorySpi spi = (SecretKeyFactorySpi)obj; provider = s.getProvider(); this.spi = spi; return spi; } catch (NoSuchAlgorithmException e) { // ignore } } serviceIterator = null; return null; } } /** * Generates a SecretKey object from the provided key * specification (key material). * * @param keySpec the specification (key material) of the secret key * * @return the secret key * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this secret-key factory to produce a secret key. */ public final SecretKey generateSecret(KeySpec keySpec) throws InvalidKeySpecException { if (serviceIterator == null) { return spi.engineGenerateSecret(keySpec); } Exception failure = null; SecretKeyFactorySpi mySpi = spi; do { try { return mySpi.engineGenerateSecret(keySpec); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof InvalidKeySpecException) { throw (InvalidKeySpecException)failure; } throw new InvalidKeySpecException ("Could not generate secret key", failure); } /** * Returns a specification (key material) of the given key object * in the requested format. * * @param key the key * @param keySpec the requested format in which the key material shall be * returned * * @return the underlying key specification (key material) in the * requested format * * @exception InvalidKeySpecException if the requested key specification is * inappropriate for the given key (e.g., the algorithms associated with * key and keySpec do not match, or * key references a key on a cryptographic hardware device * whereas keySpec is the specification of a software-based * key), or the given key cannot be dealt with * (e.g., the given key has an algorithm or format not supported by this * secret-key factory). */ public final KeySpec getKeySpec(SecretKey key, Class keySpec) throws InvalidKeySpecException { if (serviceIterator == null) { return spi.engineGetKeySpec(key, keySpec); } Exception failure = null; SecretKeyFactorySpi mySpi = spi; do { try { return mySpi.engineGetKeySpec(key, keySpec); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof InvalidKeySpecException) { throw (InvalidKeySpecException)failure; } throw new InvalidKeySpecException ("Could not get key spec", failure); } /** * Translates a key object, whose provider may be unknown or potentially * untrusted, into a corresponding key object of this secret-key factory. * * @param key the key whose provider is unknown or untrusted * * @return the translated key * * @exception InvalidKeyException if the given key cannot be processed * by this secret-key factory. */ public final SecretKey translateKey(SecretKey key) throws InvalidKeyException { if (serviceIterator == null) { return spi.engineTranslateKey(key); } Exception failure = null; SecretKeyFactorySpi mySpi = spi; do { try { return mySpi.engineTranslateKey(key); } catch (Exception e) { if (failure == null) { failure = e; } mySpi = nextSpi(mySpi); } } while (mySpi != null); if (failure instanceof InvalidKeyException) { throw (InvalidKeyException)failure; } throw new InvalidKeyException ("Could not translate key", failure); } } clean-crypto-1/src/main/java/javax/crypto/SecretKeyFactorySpi.java0000664000175000017500000001022611370332423025327 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.*; import java.security.spec.*; /** * This class defines the Service Provider Interface (SPI) * for the SecretKeyFactory class. * All the abstract methods in this class must be implemented by each * cryptographic service provider who wishes to supply the implementation * of a secret-key factory for a particular algorithm. * *

A provider should document all the key specifications supported by its * secret key factory. * For example, the DES secret-key factory supplied by the "SunJCE" provider * supports DESKeySpec as a transparent representation of DES * keys, and that provider's secret-key factory for Triple DES keys supports * DESedeKeySpec as a transparent representation of Triple DES * keys. * * @author Jan Luehe * * @see SecretKey * @see javax.crypto.spec.DESKeySpec * @see javax.crypto.spec.DESedeKeySpec * @since 1.4 */ public abstract class SecretKeyFactorySpi { /** * Generates a SecretKey object from the * provided key specification (key material). * * @param keySpec the specification (key material) of the secret key * * @return the secret key * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this secret-key factory to produce a secret key. */ protected abstract SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException; /** * Returns a specification (key material) of the given key * object in the requested format. * * @param key the key * * @param keySpec the requested format in which the key material shall be * returned * * @return the underlying key specification (key material) in the * requested format * * @exception InvalidKeySpecException if the requested key specification is * inappropriate for the given key (e.g., the algorithms associated with * key and keySpec do not match, or * key references a key on a cryptographic hardware device * whereas keySpec is the specification of a software-based * key), or the given key cannot be dealt with * (e.g., the given key has an algorithm or format not supported by this * secret-key factory). */ protected abstract KeySpec engineGetKeySpec(SecretKey key, Class keySpec) throws InvalidKeySpecException; /** * Translates a key object, whose provider may be unknown or * potentially untrusted, into a corresponding key object of this * secret-key factory. * * @param key the key whose provider is unknown or untrusted * * @return the translated key * * @exception InvalidKeyException if the given key cannot be processed * by this secret-key factory. */ protected abstract SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException; } clean-crypto-1/src/main/java/javax/crypto/ShortBufferException.java0000664000175000017500000000375711370332423025550 0ustar moellermoeller/* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package javax.crypto; import java.security.GeneralSecurityException; /** * This exception is thrown when an output buffer provided by the user * is too short to hold the operation result. * * @author Jan Luehe * * @since 1.4 */ public class ShortBufferException extends GeneralSecurityException { private static final long serialVersionUID = 8427718640832943747L; /** * Constructs a ShortBufferException with no detail * message. A detail message is a String that describes this * particular exception. */ public ShortBufferException() { super(); } /** * Constructs a ShortBufferException with the specified * detail message. * * @param msg the detail message. */ public ShortBufferException(String msg) { super(msg); } } clean-crypto-1/src/main/resources/0000775000175000017500000000000011370332422017220 5ustar moellermoellerclean-crypto-1/COPYING0000664000175000017500000000463611370332423014540 0ustar moellermoellerCopyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. This code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 only, as published by the Free Software Foundation. Sun designates this particular file as subject to the "Classpath" exception as provided by Sun in the LICENSE file that accompanied this code. This code 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 version 2 for more details (a copy is included in the LICENSE file that accompanied this code). You should have received a copy of the GNU General Public License version 2 along with this work; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, CA 95054 USA or visit www.sun.com if you need additional information or have any questions. "CLASSPATH" EXCEPTION TO THE GPL Certain source files distributed by Sun Microsystems, Inc. are subject to the following clarification and special exception to the GPL, but only where Sun has expressly included in the particular source file's header the words "Sun designates this particular file as subject to the "Classpath" exception as provided by Sun in the LICENSE file that accompanied this code." 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.