Import Android SDK Platform PI [4335822]
/google/data/ro/projects/android/fetch_artifact \
--bid 4335822 \
--target sdk_phone_armv7-win_sdk \
sdk-repo-linux-sources-4335822.zip
AndroidVersion.ApiLevel has been modified to appear as 28
Change-Id: Ic8f04be005a71c2b9abeaac754d8da8d6f9a2c32
diff --git a/java/security/AccessControlContext.java b/java/security/AccessControlContext.java
new file mode 100644
index 0000000..506898f
--- /dev/null
+++ b/java/security/AccessControlContext.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public final class AccessControlContext {
+ public AccessControlContext(ProtectionDomain context[]) {
+ }
+
+ public AccessControlContext(AccessControlContext acc,
+ DomainCombiner combiner) {
+ }
+
+
+ public DomainCombiner getDomainCombiner() {
+ return null;
+ }
+
+ public void checkPermission(Permission perm)
+ throws AccessControlException {
+ }
+
+}
diff --git a/java/security/AccessControlException.java b/java/security/AccessControlException.java
new file mode 100644
index 0000000..a4f2a78
--- /dev/null
+++ b/java/security/AccessControlException.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * <p> This exception is thrown by the AccessController to indicate
+ * that a requested access (to a critical system resource such as the
+ * file system or the network) is denied.
+ *
+ * <p> The reason to deny access can vary. For example, the requested
+ * permission might be of an incorrect type, contain an invalid
+ * value, or request access that is not allowed according to the
+ * security policy. Such information should be given whenever
+ * possible at the time the exception is thrown.
+ *
+ * @author Li Gong
+ * @author Roland Schemers
+ */
+
+public class AccessControlException extends SecurityException {
+
+ private static final long serialVersionUID = 5138225684096988535L;
+
+ // the permission that caused the exception to be thrown.
+ private Permission perm;
+
+ /**
+ * Constructs an {@code AccessControlException} with the
+ * specified, detailed message.
+ *
+ * @param s the detail message.
+ */
+ public AccessControlException(String s) {
+ super(s);
+ }
+
+ /**
+ * Constructs an {@code AccessControlException} with the
+ * specified, detailed message, and the requested permission that caused
+ * the exception.
+ *
+ * @param s the detail message.
+ * @param p the permission that caused the exception.
+ */
+ public AccessControlException(String s, Permission p) {
+ super(s);
+ perm = p;
+ }
+
+ /**
+ * Gets the Permission object associated with this exception, or
+ * null if there was no corresponding Permission object.
+ *
+ * @return the Permission object.
+ */
+ public Permission getPermission() {
+ return perm;
+ }
+}
diff --git a/java/security/AccessController.java b/java/security/AccessController.java
new file mode 100644
index 0000000..ad844ba
--- /dev/null
+++ b/java/security/AccessController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public final class AccessController {
+
+ private AccessController() { }
+
+ /**
+ * Calls {@code action.run()}.
+ */
+ public static <T> T doPrivileged(PrivilegedAction<T> action) {
+ return action.run();
+ }
+
+ /**
+ * Calls {@code action.run()}.
+ */
+ public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
+ return action.run();
+ }
+
+
+ /**
+ * Calls {@code action.run()}.
+ */
+ public static <T> T doPrivileged(PrivilegedAction<T> action,
+ AccessControlContext context) {
+ return action.run();
+ }
+
+ /**
+ * Calls {@code action.run()}.
+ */
+ public static <T> T
+ doPrivileged(PrivilegedExceptionAction<T> action)
+ throws PrivilegedActionException {
+ try {
+ return action.run();
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new PrivilegedActionException(e);
+ }
+ }
+
+
+ /**
+ * Calls {@code action.run()}.
+ */
+ public static <T> T doPrivilegedWithCombiner
+ (PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
+ return doPrivileged(action);
+ }
+
+
+ /**
+ * Calls {@code action.run()}.
+ */
+ public static <T> T
+ doPrivileged(PrivilegedExceptionAction<T> action,
+ AccessControlContext context)
+ throws PrivilegedActionException {
+ return doPrivileged(action);
+ }
+
+ public static AccessControlContext getContext() {
+ return new AccessControlContext(null);
+ }
+
+ public static void checkPermission(Permission perm)
+ throws AccessControlException {
+ }
+}
diff --git a/java/security/AlgorithmConstraints.java b/java/security/AlgorithmConstraints.java
new file mode 100644
index 0000000..7341603
--- /dev/null
+++ b/java/security/AlgorithmConstraints.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.Set;
+
+/**
+ * This interface specifies constraints for cryptographic algorithms,
+ * keys (key sizes), and other algorithm parameters.
+ * <p>
+ * {@code AlgorithmConstraints} objects are immutable. An implementation
+ * of this interface should not provide methods that can change the state
+ * of an instance once it has been created.
+ * <p>
+ * Note that {@code AlgorithmConstraints} can be used to represent the
+ * restrictions described by the security properties
+ * {@code jdk.certpath.disabledAlgorithms} and
+ * {@code jdk.tls.disabledAlgorithms}, or could be used by a
+ * concrete {@code PKIXCertPathChecker} to check whether a specified
+ * certificate in the certification path contains the required algorithm
+ * constraints.
+ *
+ * @see javax.net.ssl.SSLParameters#getAlgorithmConstraints
+ * @see javax.net.ssl.SSLParameters#setAlgorithmConstraints(AlgorithmConstraints)
+ *
+ * @since 1.7
+ */
+
+public interface AlgorithmConstraints {
+
+ /**
+ * Determines whether an algorithm is granted permission for the
+ * specified cryptographic primitives.
+ *
+ * @param primitives a set of cryptographic primitives
+ * @param algorithm the algorithm name
+ * @param parameters the algorithm parameters, or null if no additional
+ * parameters
+ *
+ * @return true if the algorithm is permitted and can be used for all
+ * of the specified cryptographic primitives
+ *
+ * @throws IllegalArgumentException if primitives or algorithm is null
+ * or empty
+ */
+ public boolean permits(Set<CryptoPrimitive> primitives,
+ String algorithm, AlgorithmParameters parameters);
+
+ /**
+ * Determines whether a key is granted permission for the specified
+ * cryptographic primitives.
+ * <p>
+ * This method is usually used to check key size and key usage.
+ *
+ * @param primitives a set of cryptographic primitives
+ * @param key the key
+ *
+ * @return true if the key can be used for all of the specified
+ * cryptographic primitives
+ *
+ * @throws IllegalArgumentException if primitives is null or empty,
+ * or the key is null
+ */
+ public boolean permits(Set<CryptoPrimitive> primitives, Key key);
+
+ /**
+ * Determines whether an algorithm and the corresponding key are granted
+ * permission for the specified cryptographic primitives.
+ *
+ * @param primitives a set of cryptographic primitives
+ * @param algorithm the algorithm name
+ * @param key the key
+ * @param parameters the algorithm parameters, or null if no additional
+ * parameters
+ *
+ * @return true if the key and the algorithm can be used for all of the
+ * specified cryptographic primitives
+ *
+ * @throws IllegalArgumentException if primitives or algorithm is null
+ * or empty, or the key is null
+ */
+ public boolean permits(Set<CryptoPrimitive> primitives,
+ String algorithm, Key key, AlgorithmParameters parameters);
+
+}
diff --git a/java/security/AlgorithmParameterGenerator.java b/java/security/AlgorithmParameterGenerator.java
new file mode 100644
index 0000000..7355405
--- /dev/null
+++ b/java/security/AlgorithmParameterGenerator.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * The {@code AlgorithmParameterGenerator} class is used to generate a
+ * set of
+ * parameters to be used with a certain algorithm. Parameter generators
+ * are constructed using the {@code getInstance} factory methods
+ * (static methods that return instances of a given class).
+ *
+ * <P>The object that will generate the parameters can be initialized
+ * in two different ways: in an algorithm-independent manner, or in an
+ * algorithm-specific manner:
+ *
+ * <ul>
+ * <li>The algorithm-independent approach uses the fact that all parameter
+ * generators share the concept of a "size" and a
+ * source of randomness. The measure of size is universally shared
+ * by all algorithm parameters, though it is interpreted differently
+ * for different algorithms. For example, in the case of parameters for
+ * the <i>DSA</i> algorithm, "size" corresponds to the size
+ * of the prime modulus (in bits).
+ * When using this approach, algorithm-specific parameter generation
+ * values - if any - default to some standard values, unless they can be
+ * derived from the specified size.
+ *
+ * <li>The other approach initializes a parameter generator object
+ * using algorithm-specific semantics, which are represented by a set of
+ * algorithm-specific parameter generation values. To generate
+ * Diffie-Hellman system parameters, for example, the parameter generation
+ * values usually
+ * consist of the size of the prime modulus and the size of the
+ * random exponent, both specified in number of bits.
+ * </ul>
+ *
+ * <P>In case the client does not explicitly initialize the
+ * AlgorithmParameterGenerator
+ * (via a call to an {@code init} method), each provider must supply (and
+ * document) a default initialization. For example, the Sun provider uses a
+ * default modulus prime size of 1024 bits for the generation of DSA
+ * parameters.
+ *
+ * <p> Android provides the following <code>AlgorithmParameterGenerator</code> algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="deprecated">
+ * <td>AES</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>DES</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>DESede</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>DH</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DSA</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These algorithms are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+ * AlgorithmParameterGenerator section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see AlgorithmParameters
+ * @see java.security.spec.AlgorithmParameterSpec
+ *
+ * @since 1.2
+ */
+
+public class AlgorithmParameterGenerator {
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private AlgorithmParameterGeneratorSpi paramGenSpi;
+
+ // The algorithm
+ private String algorithm;
+
+ /**
+ * Creates an AlgorithmParameterGenerator object.
+ *
+ * @param paramGenSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected AlgorithmParameterGenerator
+ (AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider,
+ String algorithm) {
+ this.paramGenSpi = paramGenSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the standard name of the algorithm this parameter
+ * generator is associated with.
+ *
+ * @return the string name of the algorithm.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns an AlgorithmParameterGenerator object for generating
+ * a set of parameters to be used with the specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new AlgorithmParameterGenerator object encapsulating the
+ * AlgorithmParameterGeneratorSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the algorithm this
+ * parameter generator is associated with.
+ * See the AlgorithmParameterGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new AlgorithmParameterGenerator object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports an
+ * AlgorithmParameterGeneratorSpi implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ */
+ public static AlgorithmParameterGenerator getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ try {
+ Object[] objs = Security.getImpl(algorithm,
+ "AlgorithmParameterGenerator",
+ (String)null);
+ return new AlgorithmParameterGenerator
+ ((AlgorithmParameterGeneratorSpi)objs[0],
+ (Provider)objs[1],
+ algorithm);
+ } catch(NoSuchProviderException e) {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Returns an AlgorithmParameterGenerator object for generating
+ * a set of parameters to be used with the specified algorithm.
+ *
+ * <p> A new AlgorithmParameterGenerator object encapsulating the
+ * AlgorithmParameterGeneratorSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the algorithm this
+ * parameter generator is associated with.
+ * See the AlgorithmParameterGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the string name of the Provider.
+ *
+ * @return the new AlgorithmParameterGenerator object.
+ *
+ * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static AlgorithmParameterGenerator getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("missing provider");
+ Object[] objs = Security.getImpl(algorithm,
+ "AlgorithmParameterGenerator",
+ provider);
+ return new AlgorithmParameterGenerator
+ ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1],
+ algorithm);
+ }
+
+ /**
+ * Returns an AlgorithmParameterGenerator object for generating
+ * a set of parameters to be used with the specified algorithm.
+ *
+ * <p> A new AlgorithmParameterGenerator object encapsulating the
+ * AlgorithmParameterGeneratorSpi 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 string name of the algorithm this
+ * parameter generator is associated with.
+ * See the AlgorithmParameterGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the Provider object.
+ *
+ * @return the new AlgorithmParameterGenerator object.
+ *
+ * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the specified provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static AlgorithmParameterGenerator getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("missing provider");
+ Object[] objs = Security.getImpl(algorithm,
+ "AlgorithmParameterGenerator",
+ provider);
+ return new AlgorithmParameterGenerator
+ ((AlgorithmParameterGeneratorSpi)objs[0], (Provider)objs[1],
+ algorithm);
+ }
+
+ /**
+ * Returns the provider of this algorithm parameter generator object.
+ *
+ * @return the provider of this algorithm parameter generator object
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Initializes this parameter generator for a certain size.
+ * To create the parameters, the {@code SecureRandom}
+ * implementation of the highest-priority installed provider is used as
+ * the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * {@code SecureRandom}, a system-provided source of randomness is
+ * used.)
+ *
+ * @param size the size (number of bits).
+ */
+ public final void init(int size) {
+ paramGenSpi.engineInit(size, new SecureRandom());
+ }
+
+ /**
+ * Initializes this parameter generator for a certain size and source
+ * of randomness.
+ *
+ * @param size the size (number of bits).
+ * @param random the source of randomness.
+ */
+ public final void init(int size, SecureRandom random) {
+ paramGenSpi.engineInit(size, random);
+ }
+
+ /**
+ * Initializes this parameter generator with a set of algorithm-specific
+ * parameter generation values.
+ * To generate the parameters, the {@code SecureRandom}
+ * implementation of the highest-priority installed provider is used as
+ * the source of randomness.
+ * (If none of the installed providers supply an implementation of
+ * {@code SecureRandom}, a system-provided source of randomness is
+ * used.)
+ *
+ * @param genParamSpec the set of algorithm-specific parameter generation values.
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameter
+ * generation values are inappropriate for this parameter generator.
+ */
+ public final void init(AlgorithmParameterSpec genParamSpec)
+ throws InvalidAlgorithmParameterException {
+ paramGenSpi.engineInit(genParamSpec, new SecureRandom());
+ }
+
+ /**
+ * Initializes this parameter generator with a set of algorithm-specific
+ * parameter generation values.
+ *
+ * @param genParamSpec the set of algorithm-specific parameter generation values.
+ * @param random the source of randomness.
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameter
+ * generation values are inappropriate for this parameter generator.
+ */
+ public final void init(AlgorithmParameterSpec genParamSpec,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException {
+ paramGenSpi.engineInit(genParamSpec, random);
+ }
+
+ /**
+ * Generates the parameters.
+ *
+ * @return the new AlgorithmParameters object.
+ */
+ public final AlgorithmParameters generateParameters() {
+ return paramGenSpi.engineGenerateParameters();
+ }
+}
diff --git a/java/security/AlgorithmParameterGeneratorSpi.java b/java/security/AlgorithmParameterGeneratorSpi.java
new file mode 100644
index 0000000..721fb52
--- /dev/null
+++ b/java/security/AlgorithmParameterGeneratorSpi.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code AlgorithmParameterGenerator} class, which
+ * is used to generate a set of parameters to be used with a certain algorithm.
+ *
+ * <p> All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a parameter generator for a particular algorithm.
+ *
+ * <p> In case the client does not explicitly initialize the
+ * AlgorithmParameterGenerator (via a call to an {@code engineInit}
+ * method), each provider must supply (and document) a default initialization.
+ * For example, the Sun provider uses a default modulus prime size of 1024
+ * bits for the generation of DSA parameters.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see AlgorithmParameterGenerator
+ * @see AlgorithmParameters
+ * @see java.security.spec.AlgorithmParameterSpec
+ *
+ * @since 1.2
+ */
+
+public abstract class AlgorithmParameterGeneratorSpi {
+
+ /**
+ * Initializes this parameter generator for a certain size
+ * and source of randomness.
+ *
+ * @param size the size (number of bits).
+ * @param random the source of randomness.
+ */
+ protected abstract void engineInit(int size, SecureRandom random);
+
+ /**
+ * Initializes this parameter generator with a set of
+ * algorithm-specific parameter generation values.
+ *
+ * @param genParamSpec the set of algorithm-specific parameter generation values.
+ * @param random the source of randomness.
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameter
+ * generation values are inappropriate for this parameter generator.
+ */
+ protected abstract void engineInit(AlgorithmParameterSpec genParamSpec,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException;
+
+ /**
+ * Generates the parameters.
+ *
+ * @return the new AlgorithmParameters object.
+ */
+ protected abstract AlgorithmParameters engineGenerateParameters();
+}
diff --git a/java/security/AlgorithmParameters.java b/java/security/AlgorithmParameters.java
new file mode 100644
index 0000000..36bb3ee
--- /dev/null
+++ b/java/security/AlgorithmParameters.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * This class is used as an opaque representation of cryptographic parameters.
+ *
+ * <p>An {@code AlgorithmParameters} object for managing the parameters
+ * for a particular algorithm can be obtained by
+ * calling one of the {@code getInstance} factory methods
+ * (static methods that return instances of a given class).
+ *
+ * <p>Once an {@code AlgorithmParameters} object is obtained, it must be
+ * initialized via a call to {@code init}, using an appropriate parameter
+ * specification or parameter encoding.
+ *
+ * <p>A transparent parameter specification is obtained from an
+ * {@code AlgorithmParameters} object via a call to
+ * {@code getParameterSpec}, and a byte encoding of the parameters is
+ * obtained via a call to {@code getEncoded}.
+ *
+ * <p> Android provides the following <code>AlgorithmParameters</code> algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>AES</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>BLOWFISH</td>
+ * <td>10+</td>
+ * </tr>
+ * <tr>
+ * <td>DES</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DESede</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DH</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>EC</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>GCM</td>
+ * <td>22+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>IES</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>OAEP</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA1AndAES_128</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA1AndAES_256</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA224AndAES_128</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA224AndAES_256</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA256AndAES_128</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA256AndAES_256</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA384AndAES_128</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA384AndAES_256</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA512AndAES_128</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PBEwithHmacSHA512AndAES_256</td>
+ * <td>26+</td>
+ * </tr>
+ * <tr>
+ * <td>PKCS12PBE</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>PSS</td>
+ * <td>1-8,24+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These algorithms are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+ * AlgorithmParameters section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.spec.AlgorithmParameterSpec
+ * @see java.security.spec.DSAParameterSpec
+ * @see KeyPairGenerator
+ *
+ * @since 1.2
+ */
+
+public class AlgorithmParameters {
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private AlgorithmParametersSpi paramSpi;
+
+ // The algorithm
+ private String algorithm;
+
+ // Has this object been initialized?
+ private boolean initialized = false;
+
+ /**
+ * Creates an AlgorithmParameters object.
+ *
+ * @param paramSpi the delegate
+ * @param provider the provider
+ * @param algorithm the algorithm
+ */
+ protected AlgorithmParameters(AlgorithmParametersSpi paramSpi,
+ Provider provider, String algorithm)
+ {
+ this.paramSpi = paramSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the name of the algorithm associated with this parameter object.
+ *
+ * @return the algorithm name.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns a parameter object for the specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new AlgorithmParameters object encapsulating the
+ * AlgorithmParametersSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p> The returned parameter object must be initialized via a call to
+ * {@code init}, using an appropriate parameter specification or
+ * parameter encoding.
+ *
+ * @param algorithm the name of the algorithm requested.
+ * See the AlgorithmParameters section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new parameter object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports an
+ * AlgorithmParametersSpi implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ */
+ public static AlgorithmParameters getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ try {
+ Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
+ (String)null);
+ return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
+ (Provider)objs[1],
+ algorithm);
+ } catch(NoSuchProviderException e) {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Returns a parameter object for the specified algorithm.
+ *
+ * <p> A new AlgorithmParameters object encapsulating the
+ * AlgorithmParametersSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p>The returned parameter object must be initialized via a call to
+ * {@code init}, using an appropriate parameter specification or
+ * parameter encoding.
+ *
+ * @param algorithm the name of the algorithm requested.
+ * See the AlgorithmParameters section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new parameter object.
+ *
+ * @exception NoSuchAlgorithmException if an AlgorithmParametersSpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static AlgorithmParameters getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("missing provider");
+ Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
+ provider);
+ return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
+ (Provider)objs[1],
+ algorithm);
+ }
+
+ /**
+ * Returns a parameter object for the specified algorithm.
+ *
+ * <p> A new AlgorithmParameters object encapsulating the
+ * AlgorithmParametersSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * <p>The returned parameter object must be initialized via a call to
+ * {@code init}, using an appropriate parameter specification or
+ * parameter encoding.
+ *
+ * @param algorithm the name of the algorithm requested.
+ * See the AlgorithmParameters section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new parameter object.
+ *
+ * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static AlgorithmParameters getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("missing provider");
+ Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
+ provider);
+ return new AlgorithmParameters((AlgorithmParametersSpi)objs[0],
+ (Provider)objs[1],
+ algorithm);
+ }
+
+ /**
+ * Returns the provider of this parameter object.
+ *
+ * @return the provider of this parameter object
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Initializes this parameter object using the parameters
+ * specified in {@code paramSpec}.
+ *
+ * @param paramSpec the parameter specification.
+ *
+ * @exception InvalidParameterSpecException if the given parameter
+ * specification is inappropriate for the initialization of this parameter
+ * object, or if this parameter object has already been initialized.
+ */
+ public final void init(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (this.initialized)
+ throw new InvalidParameterSpecException("already initialized");
+ paramSpi.engineInit(paramSpec);
+ this.initialized = true;
+ }
+
+ /**
+ * Imports the specified parameters and decodes them according to the
+ * primary decoding format for parameters. The primary decoding
+ * format for parameters is ASN.1, if an ASN.1 specification for this type
+ * of parameters exists.
+ *
+ * @param params the encoded parameters.
+ *
+ * @exception IOException on decoding errors, or if this parameter object
+ * has already been initialized.
+ */
+ public final void init(byte[] params) throws IOException {
+ if (this.initialized)
+ throw new IOException("already initialized");
+ paramSpi.engineInit(params);
+ this.initialized = true;
+ }
+
+ /**
+ * Imports the parameters from {@code params} and decodes them
+ * according to the specified decoding scheme.
+ * If {@code format} is null, the
+ * primary decoding format for parameters is used. The primary decoding
+ * format is ASN.1, if an ASN.1 specification for these parameters
+ * exists.
+ *
+ * @param params the encoded parameters.
+ *
+ * @param format the name of the decoding scheme.
+ *
+ * @exception IOException on decoding errors, or if this parameter object
+ * has already been initialized.
+ */
+ public final void init(byte[] params, String format) throws IOException {
+ if (this.initialized)
+ throw new IOException("already initialized");
+ paramSpi.engineInit(params, format);
+ this.initialized = true;
+ }
+
+ /**
+ * Returns a (transparent) specification of this parameter object.
+ * {@code paramSpec} identifies the specification class in which
+ * the parameters should be returned. It could, for example, be
+ * {@code DSAParameterSpec.class}, to indicate that the
+ * parameters should be returned in an instance of the
+ * {@code DSAParameterSpec} class.
+ *
+ * @param <T> the type of the parameter specification to be returrned
+ * @param paramSpec the specification class in which
+ * the parameters should be returned.
+ *
+ * @return the parameter specification.
+ *
+ * @exception InvalidParameterSpecException if the requested parameter
+ * specification is inappropriate for this parameter object, or if this
+ * parameter object has not been initialized.
+ */
+ public final <T extends AlgorithmParameterSpec>
+ T getParameterSpec(Class<T> paramSpec)
+ throws InvalidParameterSpecException
+ {
+ if (this.initialized == false) {
+ throw new InvalidParameterSpecException("not initialized");
+ }
+ return paramSpi.engineGetParameterSpec(paramSpec);
+ }
+
+ /**
+ * Returns the parameters in their primary encoding format.
+ * The primary encoding format for parameters is ASN.1, if an ASN.1
+ * specification for this type of parameters exists.
+ *
+ * @return the parameters encoded using their primary encoding format.
+ *
+ * @exception IOException on encoding errors, or if this parameter object
+ * has not been initialized.
+ */
+ public final byte[] getEncoded() throws IOException
+ {
+ if (this.initialized == false) {
+ throw new IOException("not initialized");
+ }
+ return paramSpi.engineGetEncoded();
+ }
+
+ /**
+ * Returns the parameters encoded in the specified scheme.
+ * If {@code format} is null, the
+ * primary encoding format for parameters is used. The primary encoding
+ * format is ASN.1, if an ASN.1 specification for these parameters
+ * exists.
+ *
+ * @param format the name of the encoding format.
+ *
+ * @return the parameters encoded using the specified encoding scheme.
+ *
+ * @exception IOException on encoding errors, or if this parameter object
+ * has not been initialized.
+ */
+ public final byte[] getEncoded(String format) throws IOException
+ {
+ if (this.initialized == false) {
+ throw new IOException("not initialized");
+ }
+ return paramSpi.engineGetEncoded(format);
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters, or null if this
+ * parameter object has not been initialized.
+ */
+ public final String toString() {
+ if (this.initialized == false) {
+ return null;
+ }
+ return paramSpi.engineToString();
+ }
+}
diff --git a/java/security/AlgorithmParametersSpi.java b/java/security/AlgorithmParametersSpi.java
new file mode 100644
index 0000000..282493b
--- /dev/null
+++ b/java/security/AlgorithmParametersSpi.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code AlgorithmParameters} class, which is used to manage
+ * algorithm parameters.
+ *
+ * <p> All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply parameter management
+ * for a particular algorithm.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see AlgorithmParameters
+ * @see java.security.spec.AlgorithmParameterSpec
+ * @see java.security.spec.DSAParameterSpec
+ *
+ * @since 1.2
+ */
+
+public abstract class AlgorithmParametersSpi {
+
+ /**
+ * Initializes this parameters object using the parameters
+ * specified in {@code paramSpec}.
+ *
+ * @param paramSpec the parameter specification.
+ *
+ * @exception InvalidParameterSpecException if the given parameter
+ * specification is inappropriate for the initialization of this parameter
+ * object.
+ */
+ protected abstract void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException;
+
+ /**
+ * Imports the specified parameters and decodes them
+ * according to the primary decoding format for parameters.
+ * The primary decoding format for parameters is ASN.1, if an ASN.1
+ * specification for this type of parameters exists.
+ *
+ * @param params the encoded parameters.
+ *
+ * @exception IOException on decoding errors
+ */
+ protected abstract void engineInit(byte[] params)
+ throws IOException;
+
+ /**
+ * Imports the parameters from {@code params} and
+ * decodes them according to the specified decoding format.
+ * If {@code format} is null, the
+ * primary decoding format for parameters is used. The primary decoding
+ * format is ASN.1, if an ASN.1 specification for these parameters
+ * exists.
+ *
+ * @param params the encoded parameters.
+ *
+ * @param format the name of the decoding format.
+ *
+ * @exception IOException on decoding errors
+ */
+ protected abstract void engineInit(byte[] params, String format)
+ throws IOException;
+
+ /**
+ * Returns a (transparent) specification of this parameters
+ * object.
+ * {@code paramSpec} identifies the specification class in which
+ * the parameters should be returned. It could, for example, be
+ * {@code DSAParameterSpec.class}, to indicate that the
+ * parameters should be returned in an instance of the
+ * {@code DSAParameterSpec} class.
+ *
+ * @param <T> the type of the parameter specification to be returned
+ *
+ * @param paramSpec the specification class in which
+ * the parameters should be returned.
+ *
+ * @return the parameter specification.
+ *
+ * @exception InvalidParameterSpecException if the requested parameter
+ * specification is inappropriate for this parameter object.
+ */
+ protected abstract
+ <T extends AlgorithmParameterSpec>
+ T engineGetParameterSpec(Class<T> paramSpec)
+ throws InvalidParameterSpecException;
+
+ /**
+ * Returns the parameters in their primary encoding format.
+ * The primary encoding format for parameters is ASN.1, if an ASN.1
+ * specification for this type of parameters exists.
+ *
+ * @return the parameters encoded using their primary encoding format.
+ *
+ * @exception IOException on encoding errors.
+ */
+ protected abstract byte[] engineGetEncoded() throws IOException;
+
+ /**
+ * Returns the parameters encoded in the specified format.
+ * If {@code format} is null, the
+ * primary encoding format for parameters is used. The primary encoding
+ * format is ASN.1, if an ASN.1 specification for these parameters
+ * exists.
+ *
+ * @param format the name of the encoding format.
+ *
+ * @return the parameters encoded using the specified encoding scheme.
+ *
+ * @exception IOException on encoding errors.
+ */
+ protected abstract byte[] engineGetEncoded(String format)
+ throws IOException;
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters.
+ */
+ protected abstract String engineToString();
+}
diff --git a/java/security/AllPermission.java b/java/security/AllPermission.java
new file mode 100644
index 0000000..61bcaea
--- /dev/null
+++ b/java/security/AllPermission.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1998, 2006, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public final class AllPermission extends Permission {
+
+ public AllPermission() { super(""); }
+
+ public AllPermission(String name, String actions) { super(""); }
+
+ public boolean implies(Permission p) { return true; }
+
+ public String getActions() { return null; }
+}
diff --git a/java/security/AuthProvider.java b/java/security/AuthProvider.java
new file mode 100644
index 0000000..e87daa9
--- /dev/null
+++ b/java/security/AuthProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.callback.CallbackHandler;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public abstract class AuthProvider extends Provider {
+
+ protected AuthProvider(String name, double version, String info) {
+ super("", 0d, "");
+ }
+
+ public abstract void login(Subject subject, CallbackHandler handler)
+ throws LoginException;
+
+ public abstract void logout() throws LoginException;
+
+ public abstract void setCallbackHandler(CallbackHandler handler);
+}
diff --git a/java/security/BasicPermission.java b/java/security/BasicPermission.java
new file mode 100644
index 0000000..1836b10
--- /dev/null
+++ b/java/security/BasicPermission.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public abstract class BasicPermission extends Permission
+implements java.io.Serializable
+{
+
+ public BasicPermission(String name) { super(""); }
+
+ public BasicPermission(String name, String actions) { super(""); }
+
+ public boolean implies(Permission p) { return true; }
+
+ public String getActions()
+ {
+ return "";
+ }
+}
diff --git a/java/security/Certificate.java b/java/security/Certificate.java
new file mode 100644
index 0000000..489c6d6
--- /dev/null
+++ b/java/security/Certificate.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.util.Date;
+
+/**
+ * <p>This is an interface of abstract methods for managing a
+ * variety of identity certificates.
+ * An identity certificate is a guarantee by a principal that
+ * a public key is that of another principal. (A principal represents
+ * an entity such as an individual user, a group, or a corporation.)
+ *
+ * <p>In particular, this interface is intended to be a common
+ * abstraction for constructs that have different formats but
+ * important common uses. For example, different types of
+ * certificates, such as X.509 certificates and PGP certificates,
+ * share general certificate functionality (the need to encode and
+ * decode certificates) and some types of information, such as a
+ * public key, the principal whose key it is, and the guarantor
+ * guaranteeing that the public key is that of the specified
+ * principal. So an implementation of X.509 certificates and an
+ * implementation of PGP certificates can both utilize the Certificate
+ * interface, even though their formats and additional types and
+ * amounts of information stored are different.
+ *
+ * <p><b>Important</b>: This interface is useful for cataloging and
+ * grouping objects sharing certain common uses. It does not have any
+ * semantics of its own. In particular, a Certificate object does not
+ * make any statement as to the <i>validity</i> of the binding. It is
+ * the duty of the application implementing this interface to verify
+ * the certificate and satisfy itself of its validity.
+ *
+ * @author Benjamin Renaud
+ * @deprecated A new certificate handling package is created in the Java platform.
+ * This Certificate interface is entirely deprecated and
+ * is here to allow for a smooth transition to the new
+ * package.
+ * @see java.security.cert.Certificate
+ */
+@Deprecated
+public interface Certificate {
+
+ /**
+ * Returns the guarantor of the certificate, that is, the principal
+ * guaranteeing that the public key associated with this certificate
+ * is that of the principal associated with this certificate. For X.509
+ * certificates, the guarantor will typically be a Certificate Authority
+ * (such as the United States Postal Service or Verisign, Inc.).
+ *
+ * @return the guarantor which guaranteed the principal-key
+ * binding.
+ */
+ public abstract Principal getGuarantor();
+
+ /**
+ * Returns the principal of the principal-key pair being guaranteed by
+ * the guarantor.
+ *
+ * @return the principal to which this certificate is bound.
+ */
+ public abstract Principal getPrincipal();
+
+ /**
+ * Returns the key of the principal-key pair being guaranteed by
+ * the guarantor.
+ *
+ * @return the public key that this certificate certifies belongs
+ * to a particular principal.
+ */
+ public abstract PublicKey getPublicKey();
+
+ /**
+ * Encodes the certificate to an output stream in a format that can
+ * be decoded by the {@code decode} method.
+ *
+ * @param stream the output stream to which to encode the
+ * certificate.
+ *
+ * @exception KeyException if the certificate is not
+ * properly initialized, or data is missing, etc.
+ *
+ * @exception IOException if a stream exception occurs while
+ * trying to output the encoded certificate to the output stream.
+ *
+ * @see #decode
+ * @see #getFormat
+ */
+ public abstract void encode(OutputStream stream)
+ throws KeyException, IOException;
+
+ /**
+ * Decodes a certificate from an input stream. The format should be
+ * that returned by {@code getFormat} and produced by
+ * {@code encode}.
+ *
+ * @param stream the input stream from which to fetch the data
+ * being decoded.
+ *
+ * @exception KeyException if the certificate is not properly initialized,
+ * or data is missing, etc.
+ *
+ * @exception IOException if an exception occurs while trying to input
+ * the encoded certificate from the input stream.
+ *
+ * @see #encode
+ * @see #getFormat
+ */
+ public abstract void decode(InputStream stream)
+ throws KeyException, IOException;
+
+
+ /**
+ * Returns the name of the coding format. This is used as a hint to find
+ * an appropriate parser. It could be "X.509", "PGP", etc. This is
+ * the format produced and understood by the {@code encode}
+ * and {@code decode} methods.
+ *
+ * @return the name of the coding format.
+ */
+ public abstract String getFormat();
+
+ /**
+ * Returns a string that represents the contents of the certificate.
+ *
+ * @param detailed whether or not to give detailed information
+ * about the certificate
+ *
+ * @return a string representing the contents of the certificate
+ */
+ public String toString(boolean detailed);
+}
diff --git a/java/security/CodeSigner.java b/java/security/CodeSigner.java
new file mode 100644
index 0000000..37c12b1
--- /dev/null
+++ b/java/security/CodeSigner.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.security.cert.CertPath;
+
+/**
+ * This class encapsulates information about a code signer.
+ * It is immutable.
+ *
+ * @since 1.5
+ * @author Vincent Ryan
+ */
+
+public final class CodeSigner implements Serializable {
+
+ private static final long serialVersionUID = 6819288105193937581L;
+
+ /**
+ * The signer's certificate path.
+ *
+ * @serial
+ */
+ private CertPath signerCertPath;
+
+ /*
+ * The signature timestamp.
+ *
+ * @serial
+ */
+ private Timestamp timestamp;
+
+ /*
+ * Hash code for this code signer.
+ */
+ private transient int myhash = -1;
+
+ /**
+ * Constructs a CodeSigner object.
+ *
+ * @param signerCertPath The signer's certificate path.
+ * It must not be {@code null}.
+ * @param timestamp A signature timestamp.
+ * If {@code null} then no timestamp was generated
+ * for the signature.
+ * @throws NullPointerException if {@code signerCertPath} is
+ * {@code null}.
+ */
+ public CodeSigner(CertPath signerCertPath, Timestamp timestamp) {
+ if (signerCertPath == null) {
+ throw new NullPointerException();
+ }
+ this.signerCertPath = signerCertPath;
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * Returns the signer's certificate path.
+ *
+ * @return A certificate path.
+ */
+ public CertPath getSignerCertPath() {
+ return signerCertPath;
+ }
+
+ /**
+ * Returns the signature timestamp.
+ *
+ * @return The timestamp or {@code null} if none is present.
+ */
+ public Timestamp getTimestamp() {
+ return timestamp;
+ }
+
+ /**
+ * Returns the hash code value for this code signer.
+ * The hash code is generated using the signer's certificate path and the
+ * timestamp, if present.
+ *
+ * @return a hash code value for this code signer.
+ */
+ public int hashCode() {
+ if (myhash == -1) {
+ if (timestamp == null) {
+ myhash = signerCertPath.hashCode();
+ } else {
+ myhash = signerCertPath.hashCode() + timestamp.hashCode();
+ }
+ }
+ return myhash;
+ }
+
+ /**
+ * Tests for equality between the specified object and this
+ * code signer. Two code signers are considered equal if their
+ * signer certificate paths are equal and if their timestamps are equal,
+ * if present in both.
+ *
+ * @param obj the object to test for equality with this object.
+ *
+ * @return true if the objects are considered equal, false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == null || (!(obj instanceof CodeSigner))) {
+ return false;
+ }
+ CodeSigner that = (CodeSigner)obj;
+
+ if (this == that) {
+ return true;
+ }
+ Timestamp thatTimestamp = that.getTimestamp();
+ if (timestamp == null) {
+ if (thatTimestamp != null) {
+ return false;
+ }
+ } else {
+ if (thatTimestamp == null ||
+ (! timestamp.equals(thatTimestamp))) {
+ return false;
+ }
+ }
+ return signerCertPath.equals(that.getSignerCertPath());
+ }
+
+ /**
+ * Returns a string describing this code signer.
+ *
+ * @return A string comprising the signer's certificate and a timestamp,
+ * if present.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("(");
+ sb.append("Signer: " + signerCertPath.getCertificates().get(0));
+ if (timestamp != null) {
+ sb.append("timestamp: " + timestamp);
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ // Explicitly reset hash code value to -1
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ myhash = -1;
+ }
+}
diff --git a/java/security/CodeSource.java b/java/security/CodeSource.java
new file mode 100644
index 0000000..8e6653b
--- /dev/null
+++ b/java/security/CodeSource.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+
+import java.net.URL;
+import java.net.SocketPermission;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Hashtable;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.cert.*;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public class CodeSource implements java.io.Serializable {
+
+ /**
+ * The code location.
+ *
+ * @serial
+ */
+ private URL location;
+
+ public CodeSource(URL url, java.security.cert.Certificate certs[]) {
+ this.location = url;
+ }
+
+ public CodeSource(URL url, CodeSigner[] signers) {
+ this.location = url;
+ }
+
+ public final URL getLocation() {
+ /* since URL is practically immutable, returning itself is not
+ a security problem */
+ return this.location;
+ }
+
+ public final java.security.cert.Certificate[] getCertificates() { return null; }
+
+ public final CodeSigner[] getCodeSigners() { return null; }
+
+ public boolean implies(CodeSource codesource) { return true; }
+}
diff --git a/java/security/CryptoPrimitive.java b/java/security/CryptoPrimitive.java
new file mode 100644
index 0000000..158643b
--- /dev/null
+++ b/java/security/CryptoPrimitive.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * An enumeration of cryptographic primitives.
+ *
+ * @since 1.7
+ */
+public enum CryptoPrimitive {
+ /**
+ * Hash function
+ */
+ MESSAGE_DIGEST,
+
+ /**
+ * Cryptographic random number generator
+ */
+ SECURE_RANDOM,
+
+ /**
+ * Symmetric primitive: block cipher
+ */
+ BLOCK_CIPHER,
+
+ /**
+ * Symmetric primitive: stream cipher
+ */
+ STREAM_CIPHER,
+
+ /**
+ * Symmetric primitive: message authentication code
+ */
+ MAC,
+
+ /**
+ * Symmetric primitive: key wrap
+ */
+ KEY_WRAP,
+
+ /**
+ * Asymmetric primitive: public key encryption
+ */
+ PUBLIC_KEY_ENCRYPTION,
+
+ /**
+ * Asymmetric primitive: signature scheme
+ */
+ SIGNATURE,
+
+ /**
+ * Asymmetric primitive: key encapsulation mechanism
+ */
+ KEY_ENCAPSULATION,
+
+ /**
+ * Asymmetric primitive: key agreement and key distribution
+ */
+ KEY_AGREEMENT
+}
diff --git a/java/security/DigestException.java b/java/security/DigestException.java
new file mode 100644
index 0000000..2327c98
--- /dev/null
+++ b/java/security/DigestException.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This is the generic Message Digest exception.
+ *
+ * @author Benjamin Renaud
+ */
+public class DigestException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 5821450303093652515L;
+
+ /**
+ * Constructs a DigestException with no detail message. (A
+ * detail message is a String that describes this particular
+ * exception.)
+ */
+ public DigestException() {
+ super();
+ }
+
+ /**
+ * Constructs a DigestException with the specified detail
+ * message. (A detail message is a String that describes this
+ * particular exception.)
+ *
+ * @param msg the detail message.
+ */
+ public DigestException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code DigestException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public DigestException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code DigestException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public DigestException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/DigestInputStream.java b/java/security/DigestInputStream.java
new file mode 100644
index 0000000..a1bf55a
--- /dev/null
+++ b/java/security/DigestInputStream.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.InputStream;
+import java.io.FilterInputStream;
+import java.io.PrintStream;
+import java.io.ByteArrayInputStream;
+
+/**
+ * A transparent stream that updates the associated message digest using
+ * the bits going through the stream.
+ *
+ * <p>To complete the message digest computation, call one of the
+ * {@code digest} methods on the associated message
+ * digest after your calls to one of this digest input stream's
+ * {@link #read() read} methods.
+ *
+ * <p>It is possible to turn this stream on or off (see
+ * {@link #on(boolean) on}). When it is on, a call to one of the
+ * {@code read} methods
+ * results in an update on the message digest. But when it is off,
+ * the message digest is not updated. The default is for the stream
+ * to be on.
+ *
+ * <p>Note that digest objects can compute only one digest (see
+ * {@link MessageDigest}),
+ * so that in order to compute intermediate digests, a caller should
+ * retain a handle onto the digest object, and clone it for each
+ * digest to be computed, leaving the orginal digest untouched.
+ *
+ * @see MessageDigest
+ *
+ * @see DigestOutputStream
+ *
+ * @author Benjamin Renaud
+ */
+
+public class DigestInputStream extends FilterInputStream {
+
+ /* NOTE: This should be made a generic UpdaterInputStream */
+
+ /* Are we on or off? */
+ private boolean on = true;
+
+ /**
+ * The message digest associated with this stream.
+ */
+ protected MessageDigest digest;
+
+ /**
+ * Creates a digest input stream, using the specified input stream
+ * and message digest.
+ *
+ * @param stream the input stream.
+ *
+ * @param digest the message digest to associate with this stream.
+ */
+ public DigestInputStream(InputStream stream, MessageDigest digest) {
+ super(stream);
+ setMessageDigest(digest);
+ }
+
+ /**
+ * Returns the message digest associated with this stream.
+ *
+ * @return the message digest associated with this stream.
+ * @see #setMessageDigest(java.security.MessageDigest)
+ */
+ public MessageDigest getMessageDigest() {
+ return digest;
+ }
+
+ /**
+ * Associates the specified message digest with this stream.
+ *
+ * @param digest the message digest to be associated with this stream.
+ * @see #getMessageDigest()
+ */
+ public void setMessageDigest(MessageDigest digest) {
+ this.digest = digest;
+ }
+
+ /**
+ * Reads a byte, and updates the message digest (if the digest
+ * function is on). That is, this method reads a byte from the
+ * input stream, blocking until the byte is actually read. If the
+ * digest function is on (see {@link #on(boolean) on}), this method
+ * will then call {@code update} on the message digest associated
+ * with this stream, passing it the byte read.
+ *
+ * @return the byte read.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ * @see MessageDigest#update(byte)
+ */
+ public int read() throws IOException {
+ int ch = in.read();
+ if (on && ch != -1) {
+ digest.update((byte)ch);
+ }
+ return ch;
+ }
+
+ /**
+ * Reads into a byte array, and updates the message digest (if the
+ * digest function is on). That is, this method reads up to
+ * {@code len} bytes from the input stream into the array
+ * {@code b}, starting at offset {@code off}. This method
+ * blocks until the data is actually
+ * read. If the digest function is on (see
+ * {@link #on(boolean) on}), this method will then call {@code update}
+ * on the message digest associated with this stream, passing it
+ * the data.
+ *
+ * @param b the array into which the data is read.
+ *
+ * @param off the starting offset into {@code b} of where the
+ * data should be placed.
+ *
+ * @param len the maximum number of bytes to be read from the input
+ * stream into b, starting at offset {@code off}.
+ *
+ * @return the actual number of bytes read. This is less than
+ * {@code len} if the end of the stream is reached prior to
+ * reading {@code len} bytes. -1 is returned if no bytes were
+ * read because the end of the stream had already been reached when
+ * the call was made.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ * @see MessageDigest#update(byte[], int, int)
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ int result = in.read(b, off, len);
+ if (on && result != -1) {
+ digest.update(b, off, result);
+ }
+ return result;
+ }
+
+ /**
+ * Turns the digest function on or off. The default is on. When
+ * it is on, a call to one of the {@code read} methods results in an
+ * update on the message digest. But when it is off, the message
+ * digest is not updated.
+ *
+ * @param on true to turn the digest function on, false to turn
+ * it off.
+ */
+ public void on(boolean on) {
+ this.on = on;
+ }
+
+ /**
+ * Prints a string representation of this digest input stream and
+ * its associated message digest object.
+ */
+ public String toString() {
+ return "[Digest Input Stream] " + digest.toString();
+ }
+}
diff --git a/java/security/DigestOutputStream.java b/java/security/DigestOutputStream.java
new file mode 100644
index 0000000..4d076ca
--- /dev/null
+++ b/java/security/DigestOutputStream.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.OutputStream;
+import java.io.FilterOutputStream;
+import java.io.PrintStream;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * A transparent stream that updates the associated message digest using
+ * the bits going through the stream.
+ *
+ * <p>To complete the message digest computation, call one of the
+ * {@code digest} methods on the associated message
+ * digest after your calls to one of this digest output stream's
+ * {@link #write(int) write} methods.
+ *
+ * <p>It is possible to turn this stream on or off (see
+ * {@link #on(boolean) on}). When it is on, a call to one of the
+ * {@code write} methods results in
+ * an update on the message digest. But when it is off, the message
+ * digest is not updated. The default is for the stream to be on.
+ *
+ * @see MessageDigest
+ * @see DigestInputStream
+ *
+ * @author Benjamin Renaud
+ */
+public class DigestOutputStream extends FilterOutputStream {
+
+ private boolean on = true;
+
+ /**
+ * The message digest associated with this stream.
+ */
+ protected MessageDigest digest;
+
+ /**
+ * Creates a digest output stream, using the specified output stream
+ * and message digest.
+ *
+ * @param stream the output stream.
+ *
+ * @param digest the message digest to associate with this stream.
+ */
+ public DigestOutputStream(OutputStream stream, MessageDigest digest) {
+ super(stream);
+ setMessageDigest(digest);
+ }
+
+ /**
+ * Returns the message digest associated with this stream.
+ *
+ * @return the message digest associated with this stream.
+ * @see #setMessageDigest(java.security.MessageDigest)
+ */
+ public MessageDigest getMessageDigest() {
+ return digest;
+ }
+
+ /**
+ * Associates the specified message digest with this stream.
+ *
+ * @param digest the message digest to be associated with this stream.
+ * @see #getMessageDigest()
+ */
+ public void setMessageDigest(MessageDigest digest) {
+ this.digest = digest;
+ }
+
+ /**
+ * Updates the message digest (if the digest function is on) using
+ * the specified byte, and in any case writes the byte
+ * to the output stream. That is, if the digest function is on
+ * (see {@link #on(boolean) on}), this method calls
+ * {@code update} on the message digest associated with this
+ * stream, passing it the byte {@code b}. This method then
+ * writes the byte to the output stream, blocking until the byte
+ * is actually written.
+ *
+ * @param b the byte to be used for updating and writing to the
+ * output stream.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ * @see MessageDigest#update(byte)
+ */
+ public void write(int b) throws IOException {
+ out.write(b);
+ if (on) {
+ digest.update((byte)b);
+ }
+ }
+
+ /**
+ * Updates the message digest (if the digest function is on) using
+ * the specified subarray, and in any case writes the subarray to
+ * the output stream. That is, if the digest function is on (see
+ * {@link #on(boolean) on}), this method calls {@code update}
+ * on the message digest associated with this stream, passing it
+ * the subarray specifications. This method then writes the subarray
+ * bytes to the output stream, blocking until the bytes are actually
+ * written.
+ *
+ * @param b the array containing the subarray to be used for updating
+ * and writing to the output stream.
+ *
+ * @param off the offset into {@code b} of the first byte to
+ * be updated and written.
+ *
+ * @param len the number of bytes of data to be updated and written
+ * from {@code b}, starting at offset {@code off}.
+ *
+ * @exception IOException if an I/O error occurs.
+ *
+ * @see MessageDigest#update(byte[], int, int)
+ */
+ public void write(byte[] b, int off, int len) throws IOException {
+ // BEGIN Android-added: perform checks for parameters first.
+ // See org.apache.harmony.security.tests.j.s.DigestOutputStreamTest#test_write$BII_6
+ if (b == null || off + len > b.length) {
+ throw new IllegalArgumentException("wrong parameters for write");
+ }
+ if (off < 0 || len < 0) {
+ throw new IndexOutOfBoundsException("wrong index for write");
+ }
+ // END Android-added
+ out.write(b, off, len);
+ if (on) {
+ digest.update(b, off, len);
+ }
+ }
+
+ /**
+ * Turns the digest function on or off. The default is on. When
+ * it is on, a call to one of the {@code write} methods results in an
+ * update on the message digest. But when it is off, the message
+ * digest is not updated.
+ *
+ * @param on true to turn the digest function on, false to turn it
+ * off.
+ */
+ public void on(boolean on) {
+ this.on = on;
+ }
+
+ /**
+ * Prints a string representation of this digest output stream and
+ * its associated message digest object.
+ */
+ public String toString() {
+ return "[Digest Output Stream] " + digest.toString();
+ }
+}
diff --git a/java/security/DomainCombiner.java b/java/security/DomainCombiner.java
new file mode 100644
index 0000000..e9c010f
--- /dev/null
+++ b/java/security/DomainCombiner.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public interface DomainCombiner {
+
+ ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
+ ProtectionDomain[] assignedDomains);
+}
diff --git a/java/security/DomainLoadStoreParameter.java b/java/security/DomainLoadStoreParameter.java
new file mode 100644
index 0000000..bc96975
--- /dev/null
+++ b/java/security/DomainLoadStoreParameter.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.net.URI;
+import java.util.*;
+import static java.security.KeyStore.*;
+
+/**
+ * Configuration data that specifies the keystores in a keystore domain.
+ * A keystore domain is a collection of keystores that are presented as a
+ * single logical keystore. The configuration data is used during
+ * {@code KeyStore}
+ * {@link KeyStore#load(KeyStore.LoadStoreParameter) load} and
+ * {@link KeyStore#store(KeyStore.LoadStoreParameter) store} operations.
+ * <p>
+ * The following syntax is supported for configuration data:
+ * <pre>{@code
+ * domain <domainName> [<property> ...] {
+ * keystore <keystoreName> [<property> ...] ;
+ * ...
+ * };
+ * ...
+ * }</pre>
+ * where {@code domainName} and {@code keystoreName} are identifiers
+ * and {@code property} is a key/value pairing. The key and value are
+ * separated by an 'equals' symbol and the value is enclosed in double
+ * quotes. A property value may be either a printable string or a binary
+ * string of colon-separated pairs of hexadecimal digits. Multi-valued
+ * properties are represented as a comma-separated list of values,
+ * enclosed in square brackets.
+ * See {@link Arrays#toString(java.lang.Object[])}.
+ * <p>
+ * To ensure that keystore entries are uniquely identified, each
+ * entry's alias is prefixed by its {@code keystoreName} followed
+ * by the entry name separator and each {@code keystoreName} must be
+ * unique within its domain. Entry name prefixes are omitted when
+ * storing a keystore.
+ * <p>
+ * Properties are context-sensitive: properties that apply to
+ * all the keystores in a domain are located in the domain clause,
+ * and properties that apply only to a specific keystore are located
+ * in that keystore's clause.
+ * Unless otherwise specified, a property in a keystore clause overrides
+ * a property of the same name in the domain clause. All property names
+ * are case-insensitive. The following properties are supported:
+ * <dl>
+ * <dt> {@code keystoreType="<type>"} </dt>
+ * <dd> The keystore type. </dd>
+ * <dt> {@code keystoreURI="<url>"} </dt>
+ * <dd> The keystore location. </dd>
+ * <dt> {@code keystoreProviderName="<name>"} </dt>
+ * <dd> The name of the keystore's JCE provider. </dd>
+ * <dt> {@code keystorePasswordEnv="<environment-variable>"} </dt>
+ * <dd> The environment variable that stores a keystore password.
+ * Alternatively, passwords may be supplied to the constructor
+ * method in a {@code Map<String, ProtectionParameter>}. </dd>
+ * <dt> {@code entryNameSeparator="<separator>"} </dt>
+ * <dd> The separator between a keystore name prefix and an entry name.
+ * When specified, it applies to all the entries in a domain.
+ * Its default value is a space. </dd>
+ * </dl>
+ * <p>
+ * For example, configuration data for a simple keystore domain
+ * comprising three keystores is shown below:
+ * <pre>
+ *
+ * domain app1 {
+ * keystore app1-truststore
+ * keystoreURI="file:///app1/etc/truststore.jks";
+ *
+ * keystore system-truststore
+ * keystoreURI="${java.home}/lib/security/cacerts";
+ *
+ * keystore app1-keystore
+ * keystoreType="PKCS12"
+ * keystoreURI="file:///app1/etc/keystore.p12";
+ * };
+ *
+ * </pre>
+ * @since 1.8
+ */
+public final class DomainLoadStoreParameter implements LoadStoreParameter {
+
+ private final URI configuration;
+ private final Map<String,ProtectionParameter> protectionParams;
+
+ /**
+ * Constructs a DomainLoadStoreParameter for a keystore domain with
+ * the parameters used to protect keystore data.
+ *
+ * @param configuration identifier for the domain configuration data.
+ * The name of the target domain should be specified in the
+ * {@code java.net.URI} fragment component when it is necessary
+ * to distinguish between several domain configurations at the
+ * same location.
+ *
+ * @param protectionParams the map from keystore name to the parameter
+ * used to protect keystore data.
+ * A {@code java.util.Collections.EMPTY_MAP} should be used
+ * when protection parameters are not required or when they have
+ * been specified by properties in the domain configuration data.
+ * It is cloned to prevent subsequent modification.
+ *
+ * @exception NullPointerException if {@code configuration} or
+ * {@code protectionParams} is {@code null}
+ */
+ public DomainLoadStoreParameter(URI configuration,
+ Map<String,ProtectionParameter> protectionParams) {
+ if (configuration == null || protectionParams == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.configuration = configuration;
+ this.protectionParams =
+ Collections.unmodifiableMap(new HashMap<>(protectionParams));
+ }
+
+ /**
+ * Gets the identifier for the domain configuration data.
+ *
+ * @return the identifier for the configuration data
+ */
+ public URI getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Gets the keystore protection parameters for keystores in this
+ * domain.
+ *
+ * @return an unmodifiable map of keystore names to protection
+ * parameters
+ */
+ public Map<String,ProtectionParameter> getProtectionParams() {
+ return protectionParams;
+ }
+
+ /**
+ * Gets the keystore protection parameters for this domain.
+ * Keystore domains do not support a protection parameter.
+ *
+ * @return always returns {@code null}
+ */
+ @Override
+ public KeyStore.ProtectionParameter getProtectionParameter() {
+ return null;
+ }
+}
diff --git a/java/security/GeneralSecurityException.java b/java/security/GeneralSecurityException.java
new file mode 100644
index 0000000..dc9ea06
--- /dev/null
+++ b/java/security/GeneralSecurityException.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * The {@code GeneralSecurityException} class is a generic
+ * security exception class that provides type safety for all the
+ * security-related exception classes that extend from it.
+ *
+ * @author Jan Luehe
+ */
+
+public class GeneralSecurityException extends Exception {
+
+ private static final long serialVersionUID = 894798122053539237L;
+
+ /**
+ * Constructs a GeneralSecurityException with no detail message.
+ */
+ public GeneralSecurityException() {
+ super();
+ }
+
+ /**
+ * Constructs a GeneralSecurityException with the specified detail
+ * message.
+ * A detail message is a String that describes this particular
+ * exception.
+ *
+ * @param msg the detail message.
+ */
+ public GeneralSecurityException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code GeneralSecurityException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public GeneralSecurityException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code GeneralSecurityException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public GeneralSecurityException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/Guard.java b/java/security/Guard.java
new file mode 100644
index 0000000..abafb58
--- /dev/null
+++ b/java/security/Guard.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * <p> This interface represents a guard, which is an object that is used
+ * to protect access to another object.
+ *
+ * <p>This interface contains a single method, {@code checkGuard},
+ * with a single {@code object} argument. {@code checkGuard} is
+ * invoked (by the GuardedObject {@code getObject} method)
+ * to determine whether or not to allow access to the object.
+ *
+ * @see GuardedObject
+ *
+ * @author Roland Schemers
+ * @author Li Gong
+ */
+
+public interface Guard {
+
+ /**
+ * Determines whether or not to allow access to the guarded object
+ * {@code object}. Returns silently if access is allowed.
+ * Otherwise, throws a SecurityException.
+ *
+ * @param object the object being protected by the guard.
+ *
+ * @exception SecurityException if access is denied.
+ *
+ */
+ void checkGuard(Object object) throws SecurityException;
+}
diff --git a/java/security/GuardedObject.java b/java/security/GuardedObject.java
new file mode 100644
index 0000000..a275ddf
--- /dev/null
+++ b/java/security/GuardedObject.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * A GuardedObject is an object that is used to protect access to
+ * another object.
+ *
+ * <p>A GuardedObject encapsulates a target object and a Guard object,
+ * such that access to the target object is possible
+ * only if the Guard object allows it.
+ * Once an object is encapsulated by a GuardedObject,
+ * access to that object is controlled by the {@code getObject}
+ * method, which invokes the
+ * {@code checkGuard} method on the Guard object that is
+ * guarding access. If access is not allowed,
+ * an exception is thrown.
+ *
+ * @see Guard
+ * @see Permission
+ *
+ * @author Roland Schemers
+ * @author Li Gong
+ */
+
+public class GuardedObject implements java.io.Serializable {
+
+ private static final long serialVersionUID = -5240450096227834308L;
+
+ private Object object; // the object we are guarding
+ private Guard guard; // the guard
+
+ /**
+ * Constructs a GuardedObject using the specified object and guard.
+ * If the Guard object is null, then no restrictions will
+ * be placed on who can access the object.
+ *
+ * @param object the object to be guarded.
+ *
+ * @param guard the Guard object that guards access to the object.
+ */
+
+ public GuardedObject(Object object, Guard guard)
+ {
+ this.guard = guard;
+ this.object = object;
+ }
+
+ /**
+ * Retrieves the guarded object, or throws an exception if access
+ * to the guarded object is denied by the guard.
+ *
+ * @return the guarded object.
+ *
+ * @exception SecurityException if access to the guarded object is
+ * denied.
+ */
+ public Object getObject()
+ throws SecurityException
+ {
+ if (guard != null)
+ guard.checkGuard(object);
+
+ return object;
+ }
+
+ /**
+ * Writes this object out to a stream (i.e., serializes it).
+ * We check the guard if there is one.
+ */
+ private void writeObject(java.io.ObjectOutputStream oos)
+ throws java.io.IOException
+ {
+ if (guard != null)
+ guard.checkGuard(object);
+
+ oos.defaultWriteObject();
+ }
+}
diff --git a/java/security/Identity.java b/java/security/Identity.java
new file mode 100644
index 0000000..e63131e
--- /dev/null
+++ b/java/security/Identity.java
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * <p>This class represents identities: real-world objects such as people,
+ * companies or organizations whose identities can be authenticated using
+ * their public keys. Identities may also be more abstract (or concrete)
+ * constructs, such as daemon threads or smart cards.
+ *
+ * <p>All Identity objects have a name and a public key. Names are
+ * immutable. Identities may also be scoped. That is, if an Identity is
+ * specified to have a particular scope, then the name and public
+ * key of the Identity are unique within that scope.
+ *
+ * <p>An Identity also has a set of certificates (all certifying its own
+ * public key). The Principal names specified in these certificates need
+ * not be the same, only the key.
+ *
+ * <p>An Identity can be subclassed, to include postal and email addresses,
+ * telephone numbers, images of faces and logos, and so on.
+ *
+ * @see IdentityScope
+ * @see Signer
+ * @see Principal
+ *
+ * @author Benjamin Renaud
+ * @deprecated This class is no longer used. Its functionality has been
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
+ */
+@Deprecated
+public abstract class Identity implements Principal, Serializable {
+
+ /** use serialVersionUID from JDK 1.1.x for interoperability */
+ private static final long serialVersionUID = 3609922007826600659L;
+
+ /**
+ * The name for this identity.
+ *
+ * @serial
+ */
+ private String name;
+
+ /**
+ * The public key for this identity.
+ *
+ * @serial
+ */
+ private PublicKey publicKey;
+
+ /**
+ * Generic, descriptive information about the identity.
+ *
+ * @serial
+ */
+ String info = "No further information available.";
+
+ /**
+ * The scope of the identity.
+ *
+ * @serial
+ */
+ IdentityScope scope;
+
+ /**
+ * The certificates for this identity.
+ *
+ * @serial
+ */
+ Vector<Certificate> certificates;
+
+ /**
+ * Constructor for serialization only.
+ */
+ protected Identity() {
+ this("restoring...");
+ }
+
+ /**
+ * Constructs an identity with the specified name and scope.
+ *
+ * @param name the identity name.
+ * @param scope the scope of the identity.
+ *
+ * @exception KeyManagementException if there is already an identity
+ * with the same name in the scope.
+ */
+ public Identity(String name, IdentityScope scope) throws
+ KeyManagementException {
+ this(name);
+ if (scope != null) {
+ scope.addIdentity(this);
+ }
+ this.scope = scope;
+ }
+
+ /**
+ * Constructs an identity with the specified name and no scope.
+ *
+ * @param name the identity name.
+ */
+ public Identity(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns this identity's name.
+ *
+ * @return the name of this identity.
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Returns this identity's scope.
+ *
+ * @return the scope of this identity.
+ */
+ public final IdentityScope getScope() {
+ return scope;
+ }
+
+ /**
+ * Returns this identity's public key.
+ *
+ * @return the public key for this identity.
+ *
+ * @see #setPublicKey
+ */
+ public PublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ /**
+ * Sets this identity's public key. The old key and all of this
+ * identity's certificates are removed by this operation.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "setIdentityPublicKey"}
+ * as its argument to see if it's ok to set the public key.
+ *
+ * @param key the public key for this identity.
+ *
+ * @exception KeyManagementException if another identity in the
+ * identity's scope has the same public key, or if another exception occurs.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * setting the public key.
+ *
+ * @see #getPublicKey
+ * @see SecurityManager#checkSecurityAccess
+ */
+ /* Should we throw an exception if this is already set? */
+ public void setPublicKey(PublicKey key) throws KeyManagementException {
+
+ check("setIdentityPublicKey");
+ this.publicKey = key;
+ certificates = new Vector<Certificate>();
+ }
+
+ /**
+ * Specifies a general information string for this identity.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "setIdentityInfo"}
+ * as its argument to see if it's ok to specify the information string.
+ *
+ * @param info the information string.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * setting the information string.
+ *
+ * @see #getInfo
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public void setInfo(String info) {
+ check("setIdentityInfo");
+ this.info = info;
+ }
+
+ /**
+ * Returns general information previously specified for this identity.
+ *
+ * @return general information about this identity.
+ *
+ * @see #setInfo
+ */
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * Adds a certificate for this identity. If the identity has a public
+ * key, the public key in the certificate must be the same, and if
+ * the identity does not have a public key, the identity's
+ * public key is set to be that specified in the certificate.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "addIdentityCertificate"}
+ * as its argument to see if it's ok to add a certificate.
+ *
+ * @param certificate the certificate to be added.
+ *
+ * @exception KeyManagementException if the certificate is not valid,
+ * if the public key in the certificate being added conflicts with
+ * this identity's public key, or if another exception occurs.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * adding a certificate.
+ *
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public void addCertificate(Certificate certificate)
+ throws KeyManagementException {
+
+ check("addIdentityCertificate");
+
+ if (certificates == null) {
+ certificates = new Vector<Certificate>();
+ }
+ if (publicKey != null) {
+ if (!keyEquals(publicKey, certificate.getPublicKey())) {
+ throw new KeyManagementException(
+ "public key different from cert public key");
+ }
+ } else {
+ publicKey = certificate.getPublicKey();
+ }
+ certificates.addElement(certificate);
+ }
+
+ private boolean keyEquals(PublicKey aKey, PublicKey anotherKey) {
+ String aKeyFormat = aKey.getFormat();
+ String anotherKeyFormat = anotherKey.getFormat();
+ if ((aKeyFormat == null) ^ (anotherKeyFormat == null))
+ return false;
+ if (aKeyFormat != null && anotherKeyFormat != null)
+ if (!aKeyFormat.equalsIgnoreCase(anotherKeyFormat))
+ return false;
+ return java.util.Arrays.equals(aKey.getEncoded(),
+ anotherKey.getEncoded());
+ }
+
+
+ /**
+ * Removes a certificate from this identity.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "removeIdentityCertificate"}
+ * as its argument to see if it's ok to remove a certificate.
+ *
+ * @param certificate the certificate to be removed.
+ *
+ * @exception KeyManagementException if the certificate is
+ * missing, or if another exception occurs.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * removing a certificate.
+ *
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public void removeCertificate(Certificate certificate)
+ throws KeyManagementException {
+ check("removeIdentityCertificate");
+ if (certificates != null) {
+ // Android-changed: Throw a KeyManagementException if certificate is null or
+ // not contained within |certificates|.
+ if (certificate == null || !certificates.contains(certificate)) {
+ throw new KeyManagementException();
+ }
+ certificates.removeElement(certificate);
+ }
+ }
+
+ /**
+ * Returns a copy of all the certificates for this identity.
+ *
+ * @return a copy of all the certificates for this identity.
+ */
+ public Certificate[] certificates() {
+ if (certificates == null) {
+ return new Certificate[0];
+ }
+ int len = certificates.size();
+ Certificate[] certs = new Certificate[len];
+ certificates.copyInto(certs);
+ return certs;
+ }
+
+ /**
+ * Tests for equality between the specified object and this identity.
+ * This first tests to see if the entities actually refer to the same
+ * object, in which case it returns true. Next, it checks to see if
+ * the entities have the same name and the same scope. If they do,
+ * the method returns true. Otherwise, it calls
+ * {@link #identityEquals(Identity) identityEquals}, which subclasses should
+ * override.
+ *
+ * @param identity the object to test for equality with this identity.
+ *
+ * @return true if the objects are considered equal, false otherwise.
+ *
+ * @see #identityEquals
+ */
+ public final boolean equals(Object identity) {
+
+ if (identity == this) {
+ return true;
+ }
+
+ if (identity instanceof Identity) {
+ Identity i = (Identity)identity;
+ if (this.fullName().equals(i.fullName())) {
+ return true;
+ } else {
+ return identityEquals(i);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests for equality between the specified identity and this identity.
+ * This method should be overriden by subclasses to test for equality.
+ * The default behavior is to return true if the names and public keys
+ * are equal.
+ *
+ * @param identity the identity to test for equality with this identity.
+ *
+ * @return true if the identities are considered equal, false
+ * otherwise.
+ *
+ * @see #equals
+ */
+ protected boolean identityEquals(Identity identity) {
+ if (!name.equalsIgnoreCase(identity.name))
+ return false;
+
+ if ((publicKey == null) ^ (identity.publicKey == null))
+ return false;
+
+ if (publicKey != null && identity.publicKey != null)
+ if (!publicKey.equals(identity.publicKey))
+ return false;
+
+ return true;
+
+ }
+
+ /**
+ * Returns a parsable name for identity: identityName.scopeName
+ */
+ String fullName() {
+ String parsable = name;
+ if (scope != null) {
+ parsable += "." + scope.getName();
+ }
+ return parsable;
+ }
+
+ /**
+ * Returns a short string describing this identity, telling its
+ * name and its scope (if any).
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "printIdentity"}
+ * as its argument to see if it's ok to return the string.
+ *
+ * @return information about this identity, such as its name and the
+ * name of its scope (if any).
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * returning a string describing this identity.
+ *
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public String toString() {
+ check("printIdentity");
+ String printable = name;
+ if (scope != null) {
+ printable += "[" + scope.getName() + "]";
+ }
+ return printable;
+ }
+
+ /**
+ * Returns a string representation of this identity, with
+ * optionally more details than that provided by the
+ * {@code toString} method without any arguments.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "printIdentity"}
+ * as its argument to see if it's ok to return the string.
+ *
+ * @param detailed whether or not to provide detailed information.
+ *
+ * @return information about this identity. If {@code detailed}
+ * is true, then this method returns more information than that
+ * provided by the {@code toString} method without any arguments.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * returning a string describing this identity.
+ *
+ * @see #toString
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public String toString(boolean detailed) {
+ String out = toString();
+ if (detailed) {
+ out += "\n";
+ out += printKeys();
+ out += "\n" + printCertificates();
+ if (info != null) {
+ out += "\n\t" + info;
+ } else {
+ out += "\n\tno additional information available.";
+ }
+ }
+ return out;
+ }
+
+ String printKeys() {
+ String key = "";
+ if (publicKey != null) {
+ key = "\tpublic key initialized";
+ } else {
+ key = "\tno public key";
+ }
+ return key;
+ }
+
+ String printCertificates() {
+ String out = "";
+ if (certificates == null) {
+ return "\tno certificates";
+ } else {
+ out += "\tcertificates: \n";
+
+ int i = 1;
+ for (Certificate cert : certificates) {
+ out += "\tcertificate " + i++ +
+ "\tfor : " + cert.getPrincipal() + "\n";
+ out += "\t\t\tfrom : " +
+ cert.getGuarantor() + "\n";
+ }
+ }
+ return out;
+ }
+
+ /**
+ * Returns a hashcode for this identity.
+ *
+ * @return a hashcode for this identity.
+ */
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ private static void check(String directive) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkSecurityAccess(directive);
+ }
+ }
+}
diff --git a/java/security/IdentityScope.java b/java/security/IdentityScope.java
new file mode 100644
index 0000000..61d37cb
--- /dev/null
+++ b/java/security/IdentityScope.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * <p>This class represents a scope for identities. It is an Identity
+ * itself, and therefore has a name and can have a scope. It can also
+ * optionally have a public key and associated certificates.
+ *
+ * <p>An IdentityScope can contain Identity objects of all kinds, including
+ * Signers. All types of Identity objects can be retrieved, added, and
+ * removed using the same methods. Note that it is possible, and in fact
+ * expected, that different types of identity scopes will
+ * apply different policies for their various operations on the
+ * various types of Identities.
+ *
+ * <p>There is a one-to-one mapping between keys and identities, and
+ * there can only be one copy of one key per scope. For example, suppose
+ * <b>Acme Software, Inc</b> is a software publisher known to a user.
+ * Suppose it is an Identity, that is, it has a public key, and a set of
+ * associated certificates. It is named in the scope using the name
+ * "Acme Software". No other named Identity in the scope has the same
+ * public key. Of course, none has the same name as well.
+ *
+ * @see Identity
+ * @see Signer
+ * @see Principal
+ * @see Key
+ *
+ * @author Benjamin Renaud
+ *
+ * @deprecated This class is no longer used. Its functionality has been
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
+ */
+@Deprecated
+public abstract
+class IdentityScope extends Identity {
+
+ private static final long serialVersionUID = -2337346281189773310L;
+
+ /* The system's scope */
+ private static IdentityScope scope;
+
+ // initialize the system scope
+ private static void initializeSystemScope() {
+
+ String classname = AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty("system.scope");
+ }
+ });
+
+ if (classname == null) {
+ return;
+
+ } else {
+
+ try {
+ // Android-changed: Actually set the system scope after initializing it
+ // Class.forName(classname);
+ scope = (IdentityScope) Class.forName(classname).newInstance();
+ } catch (Exception e) {
+ //Security.error("unable to establish a system scope from " +
+ // classname);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * This constructor is used for serialization only and should not
+ * be used by subclasses.
+ */
+ protected IdentityScope() {
+ this("restoring...");
+ }
+
+ /**
+ * Constructs a new identity scope with the specified name.
+ *
+ * @param name the scope name.
+ */
+ public IdentityScope(String name) {
+ super(name);
+ }
+
+ /**
+ * Constructs a new identity scope with the specified name and scope.
+ *
+ * @param name the scope name.
+ * @param scope the scope for the new identity scope.
+ *
+ * @exception KeyManagementException if there is already an identity
+ * with the same name in the scope.
+ */
+ public IdentityScope(String name, IdentityScope scope)
+ throws KeyManagementException {
+ super(name, scope);
+ }
+
+ /**
+ * Returns the system's identity scope.
+ *
+ * @return the system's identity scope, or {@code null} if none has been
+ * set.
+ *
+ * @see #setSystemScope
+ */
+ public static IdentityScope getSystemScope() {
+ if (scope == null) {
+ initializeSystemScope();
+ }
+ return scope;
+ }
+
+
+ /**
+ * Sets the system's identity scope.
+ *
+ * <p>First, if there is a security manager, its
+ * {@code checkSecurityAccess}
+ * method is called with {@code "setSystemScope"}
+ * as its argument to see if it's ok to set the identity scope.
+ *
+ * @param scope the scope to set.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * setting the identity scope.
+ *
+ * @see #getSystemScope
+ * @see SecurityManager#checkSecurityAccess
+ */
+ protected static void setSystemScope(IdentityScope scope) {
+ check("setSystemScope");
+ IdentityScope.scope = scope;
+ }
+
+ /**
+ * Returns the number of identities within this identity scope.
+ *
+ * @return the number of identities within this identity scope.
+ */
+ public abstract int size();
+
+ /**
+ * Returns the identity in this scope with the specified name (if any).
+ *
+ * @param name the name of the identity to be retrieved.
+ *
+ * @return the identity named {@code name}, or null if there are
+ * no identities named {@code name} in this scope.
+ */
+ public abstract Identity getIdentity(String name);
+
+ /**
+ * Retrieves the identity whose name is the same as that of the
+ * specified principal. (Note: Identity implements Principal.)
+ *
+ * @param principal the principal corresponding to the identity
+ * to be retrieved.
+ *
+ * @return the identity whose name is the same as that of the
+ * principal, or null if there are no identities of the same name
+ * in this scope.
+ */
+ public Identity getIdentity(Principal principal) {
+ return getIdentity(principal.getName());
+ }
+
+ /**
+ * Retrieves the identity with the specified public key.
+ *
+ * @param key the public key for the identity to be returned.
+ *
+ * @return the identity with the given key, or null if there are
+ * no identities in this scope with that key.
+ */
+ public abstract Identity getIdentity(PublicKey key);
+
+ /**
+ * Adds an identity to this identity scope.
+ *
+ * @param identity the identity to be added.
+ *
+ * @exception KeyManagementException if the identity is not
+ * valid, a name conflict occurs, another identity has the same
+ * public key as the identity being added, or another exception
+ * occurs. */
+ public abstract void addIdentity(Identity identity)
+ throws KeyManagementException;
+
+ /**
+ * Removes an identity from this identity scope.
+ *
+ * @param identity the identity to be removed.
+ *
+ * @exception KeyManagementException if the identity is missing,
+ * or another exception occurs.
+ */
+ public abstract void removeIdentity(Identity identity)
+ throws KeyManagementException;
+
+ /**
+ * Returns an enumeration of all identities in this identity scope.
+ *
+ * @return an enumeration of all identities in this identity scope.
+ */
+ public abstract Enumeration<Identity> identities();
+
+ /**
+ * Returns a string representation of this identity scope, including
+ * its name, its scope name, and the number of identities in this
+ * identity scope.
+ *
+ * @return a string representation of this identity scope.
+ */
+ public String toString() {
+ return super.toString() + "[" + size() + "]";
+ }
+
+ private static void check(String directive) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkSecurityAccess(directive);
+ }
+ }
+
+}
diff --git a/java/security/InvalidAlgorithmParameterException.java b/java/security/InvalidAlgorithmParameterException.java
new file mode 100644
index 0000000..559a8be
--- /dev/null
+++ b/java/security/InvalidAlgorithmParameterException.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This is the exception for invalid or inappropriate algorithm parameters.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see AlgorithmParameters
+ * @see java.security.spec.AlgorithmParameterSpec
+ *
+ * @since 1.2
+ */
+
+public class InvalidAlgorithmParameterException
+extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 2864672297499471472L;
+
+ /**
+ * Constructs an InvalidAlgorithmParameterException with no detail
+ * message.
+ * A detail message is a String that describes this particular
+ * exception.
+ */
+ public InvalidAlgorithmParameterException() {
+ super();
+ }
+
+ /**
+ * Constructs an InvalidAlgorithmParameterException with the specified
+ * detail message.
+ * A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public InvalidAlgorithmParameterException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code InvalidAlgorithmParameterException} with the
+ * specified detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public InvalidAlgorithmParameterException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code InvalidAlgorithmParameterException} with the
+ * specified cause and a detail message of
+ * {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public InvalidAlgorithmParameterException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/InvalidKeyException.java b/java/security/InvalidKeyException.java
new file mode 100644
index 0000000..35fc64c
--- /dev/null
+++ b/java/security/InvalidKeyException.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package java.security;
+
+/**
+ * This is the exception for invalid Keys (invalid encoding, wrong
+ * length, uninitialized, etc).
+ *
+ * @author Benjamin Renaud
+ */
+
+public class InvalidKeyException extends KeyException {
+
+ private static final long serialVersionUID = 5698479920593359816L;
+
+ /**
+ * Constructs an InvalidKeyException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public InvalidKeyException() {
+ super();
+ }
+
+ /**
+ * Constructs an InvalidKeyException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public InvalidKeyException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code InvalidKeyException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public InvalidKeyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code InvalidKeyException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public InvalidKeyException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/InvalidParameterException.java b/java/security/InvalidParameterException.java
new file mode 100644
index 0000000..a095f90
--- /dev/null
+++ b/java/security/InvalidParameterException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This exception, designed for use by the JCA/JCE engine classes,
+ * is thrown when an invalid parameter is passed
+ * to a method.
+ *
+ * @author Benjamin Renaud
+ */
+
+public class InvalidParameterException extends IllegalArgumentException {
+
+ private static final long serialVersionUID = -857968536935667808L;
+
+ /**
+ * Constructs an InvalidParameterException with no detail message.
+ * A detail message is a String that describes this particular
+ * exception.
+ */
+ public InvalidParameterException() {
+ super();
+ }
+
+ /**
+ * Constructs an InvalidParameterException with the specified
+ * detail message. A detail message is a String that describes
+ * this particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public InvalidParameterException(String msg) {
+ super(msg);
+ }
+}
diff --git a/java/security/Key.java b/java/security/Key.java
new file mode 100644
index 0000000..c8132f4
--- /dev/null
+++ b/java/security/Key.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * The Key interface is the top-level interface for all keys. It
+ * defines the functionality shared by all key objects. All keys
+ * have three characteristics:
+ *
+ * <UL>
+ *
+ * <LI>An Algorithm
+ *
+ * <P>This is the key algorithm for that key. The key algorithm is usually
+ * an encryption or asymmetric operation algorithm (such as DSA or
+ * RSA), which will work with those algorithms and with related
+ * algorithms (such as MD5 with RSA, SHA-1 with RSA, Raw DSA, etc.)
+ * The name of the algorithm of a key is obtained using the
+ * {@link #getAlgorithm() getAlgorithm} method.
+ *
+ * <LI>An Encoded Form
+ *
+ * <P>This is an external encoded form for the key used when a standard
+ * representation of the key is needed outside the Java Virtual Machine,
+ * as when transmitting the key to some other party. The key
+ * is encoded according to a standard format (such as
+ * X.509 {@code SubjectPublicKeyInfo} or PKCS#8), and
+ * is returned using the {@link #getEncoded() getEncoded} method.
+ * Note: The syntax of the ASN.1 type {@code SubjectPublicKeyInfo}
+ * is defined as follows:
+ *
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * </pre>
+ *
+ * For more information, see
+ * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>.
+ *
+ * <LI>A Format
+ *
+ * <P>This is the name of the format of the encoded key. It is returned
+ * by the {@link #getFormat() getFormat} method.
+ *
+ * </UL>
+ *
+ * Keys are generally obtained through key generators, certificates,
+ * or various Identity classes used to manage keys.
+ * Keys may also be obtained from key specifications (transparent
+ * representations of the underlying key material) through the use of a key
+ * factory (see {@link KeyFactory}).
+ *
+ * <p> A Key should use KeyRep as its serialized representation.
+ * Note that a serialized Key may contain sensitive information
+ * which should not be exposed in untrusted environments. See the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/security.html">
+ * Security Appendix</a>
+ * of the Serialization Specification for more information.
+ *
+ * @see PublicKey
+ * @see PrivateKey
+ * @see KeyPair
+ * @see KeyPairGenerator
+ * @see KeyFactory
+ * @see KeyRep
+ * @see java.security.spec.KeySpec
+ * @see Identity
+ * @see Signer
+ *
+ * @author Benjamin Renaud
+ */
+
+public interface Key extends java.io.Serializable {
+
+ // Declare serialVersionUID to be compatible with JDK1.1
+
+ /**
+ * The class fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the class.
+ */
+ static final long serialVersionUID = 6603384152749567654L;
+
+ /**
+ * Returns the standard algorithm name for this key. For
+ * example, "DSA" would indicate that this key is a DSA key.
+ * See Appendix A in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture API Specification & Reference </a>
+ * for information about standard algorithm names.
+ *
+ * @return the name of the algorithm associated with this key.
+ */
+ public String getAlgorithm();
+
+ /**
+ * Returns the name of the primary encoding format of this key,
+ * or null if this key does not support encoding.
+ * The primary encoding format is
+ * named in terms of the appropriate ASN.1 data format, if an
+ * ASN.1 specification for this key exists.
+ * For example, the name of the ASN.1 data format for public
+ * keys is <I>SubjectPublicKeyInfo</I>, as
+ * defined by the X.509 standard; in this case, the returned format is
+ * {@code "X.509"}. Similarly,
+ * the name of the ASN.1 data format for private keys is
+ * <I>PrivateKeyInfo</I>,
+ * as defined by the PKCS #8 standard; in this case, the returned format is
+ * {@code "PKCS#8"}.
+ *
+ * @return the primary encoding format of the key.
+ */
+ public String getFormat();
+
+ /**
+ * Returns the key in its primary encoding format, or null
+ * if this key does not support encoding.
+ *
+ * @return the encoded key, or null if the key does not support
+ * encoding.
+ */
+ public byte[] getEncoded();
+}
diff --git a/java/security/KeyException.java b/java/security/KeyException.java
new file mode 100644
index 0000000..59cdd6f
--- /dev/null
+++ b/java/security/KeyException.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This is the basic key exception.
+ *
+ * @see Key
+ * @see InvalidKeyException
+ * @see KeyManagementException
+ *
+ * @author Benjamin Renaud
+ */
+
+public class KeyException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -7483676942812432108L;
+
+ /**
+ * Constructs a KeyException with no detail message. A detail
+ * message is a String that describes this particular exception.
+ */
+ public KeyException() {
+ super();
+ }
+
+ /**
+ * Constructs a KeyException with the specified detail message.
+ * A detail message is a String that describes this particular
+ * exception.
+ *
+ * @param msg the detail message.
+ */
+ public KeyException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code KeyException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public KeyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code KeyException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public KeyException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/KeyFactory.java b/java/security/KeyFactory.java
new file mode 100644
index 0000000..a6b912c
--- /dev/null
+++ b/java/security/KeyFactory.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+import java.security.Provider.Service;
+import java.security.spec.KeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPrivateKeySpec;
+
+import sun.security.util.Debug;
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * Key factories are used to convert <I>keys</I> (opaque
+ * cryptographic keys of type {@code Key}) into <I>key specifications</I>
+ * (transparent representations of the underlying key material), and vice
+ * versa.
+ *
+ * <P> Key factories are bi-directional. That is, they allow you 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.
+ *
+ * <P> Multiple compatible key specifications may exist for the same key.
+ * For example, a DSA public key may be specified using
+ * {@code DSAPublicKeySpec} or
+ * {@code X509EncodedKeySpec}. A key factory can be used to translate
+ * between compatible key specifications.
+ *
+ * <P> The following is an example of how to use a key factory in order to
+ * instantiate a DSA public key from its encoding.
+ * Assume Alice has received a digital signature from Bob.
+ * Bob also sent her his public key (in encoded format) to verify
+ * his signature. Alice then performs the following actions:
+ *
+ * <pre>
+ * X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
+ * KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+ * PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
+ * Signature sig = Signature.getInstance("DSA");
+ * sig.initVerify(bobPubKey);
+ * sig.update(data);
+ * sig.verify(signature);
+ * </pre>
+ *
+ * <p> Android provides the following <code>KeyFactory</code> algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>DH</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>EC</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>RSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>X.509</td>
+ * <td>1-8</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These algorithms are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyFactory">
+ * KeyFactory section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Jan Luehe
+ *
+ * @see Key
+ * @see PublicKey
+ * @see PrivateKey
+ * @see java.security.spec.KeySpec
+ * @see java.security.spec.DSAPublicKeySpec
+ * @see java.security.spec.X509EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public class KeyFactory {
+
+ private static final Debug debug =
+ Debug.getInstance("jca", "KeyFactory");
+
+ // The algorithm associated with this key factory
+ private final String algorithm;
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation (delegate)
+ private volatile KeyFactorySpi 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<Service> serviceIterator;
+
+ /**
+ * Creates a KeyFactory object.
+ *
+ * @param keyFacSpi the delegate
+ * @param provider the provider
+ * @param algorithm the name of the algorithm
+ * to associate with this {@code KeyFactory}
+ */
+ protected KeyFactory(KeyFactorySpi keyFacSpi, Provider provider,
+ String algorithm) {
+ this.spi = keyFacSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
+ this.algorithm = algorithm;
+ List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
+ serviceIterator = list.iterator();
+ // fetch and instantiate initial spi
+ if (nextSpi(null) == null) {
+ throw new NoSuchAlgorithmException
+ (algorithm + " KeyFactory not available");
+ }
+ }
+
+ /**
+ * Returns a KeyFactory object that converts
+ * public/private keys of the specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new KeyFactory object encapsulating the
+ * KeyFactorySpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the requested key algorithm.
+ * See the KeyFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new KeyFactory object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * KeyFactorySpi implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ */
+ public static KeyFactory getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ return new KeyFactory(algorithm);
+ }
+
+ /**
+ * Returns a KeyFactory object that converts
+ * public/private keys of the specified algorithm.
+ *
+ * <p> A new KeyFactory object encapsulating the
+ * KeyFactorySpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the requested key algorithm.
+ * See the KeyFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new KeyFactory object.
+ *
+ * @exception NoSuchAlgorithmException if a KeyFactorySpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static KeyFactory getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ Instance instance = GetInstance.getInstance("KeyFactory",
+ KeyFactorySpi.class, algorithm, provider);
+ return new KeyFactory((KeyFactorySpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a KeyFactory object that converts
+ * public/private keys of the specified algorithm.
+ *
+ * <p> A new KeyFactory object encapsulating the
+ * KeyFactorySpi 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 name of the requested key algorithm.
+ * See the KeyFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new KeyFactory object.
+ *
+ * @exception NoSuchAlgorithmException if a KeyFactorySpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the specified provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static KeyFactory getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("KeyFactory",
+ KeyFactorySpi.class, algorithm, provider);
+ return new KeyFactory((KeyFactorySpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the provider of this key factory object.
+ *
+ * @return the provider of this key factory object
+ */
+ public final Provider getProvider() {
+ synchronized (lock) {
+ // disable further failover after this call
+ serviceIterator = null;
+ return provider;
+ }
+ }
+
+ /**
+ * Gets the name of the algorithm
+ * associated with this {@code KeyFactory}.
+ *
+ * @return the name of the algorithm associated with this
+ * {@code KeyFactory}
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Update the active KeyFactorySpi 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 KeyFactorySpi nextSpi(KeyFactorySpi 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 = serviceIterator.next();
+ try {
+ Object obj = s.newInstance(null);
+ if (obj instanceof KeyFactorySpi == false) {
+ continue;
+ }
+ KeyFactorySpi spi = (KeyFactorySpi)obj;
+ provider = s.getProvider();
+ this.spi = spi;
+ return spi;
+ } catch (NoSuchAlgorithmException e) {
+ // ignore
+ }
+ }
+ serviceIterator = null;
+ return null;
+ }
+ }
+
+ /**
+ * Generates a public key object from the provided key specification
+ * (key material).
+ *
+ * @param keySpec the specification (key material) of the public key.
+ *
+ * @return the public key.
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this key factory to produce a public key.
+ */
+ public final PublicKey generatePublic(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ if (serviceIterator == null) {
+ return spi.engineGeneratePublic(keySpec);
+ }
+ Exception failure = null;
+ KeyFactorySpi mySpi = spi;
+ do {
+ try {
+ return mySpi.engineGeneratePublic(keySpec);
+ } catch (Exception e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi);
+ }
+ } while (mySpi != null);
+ if (failure instanceof RuntimeException) {
+ throw (RuntimeException)failure;
+ }
+ if (failure instanceof InvalidKeySpecException) {
+ throw (InvalidKeySpecException)failure;
+ }
+ throw new InvalidKeySpecException
+ ("Could not generate public key", failure);
+ }
+
+ /**
+ * Generates a private key object from the provided key specification
+ * (key material).
+ *
+ * @param keySpec the specification (key material) of the private key.
+ *
+ * @return the private key.
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this key factory to produce a private key.
+ */
+ public final PrivateKey generatePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ if (serviceIterator == null) {
+ return spi.engineGeneratePrivate(keySpec);
+ }
+ Exception failure = null;
+ KeyFactorySpi mySpi = spi;
+ do {
+ try {
+ return mySpi.engineGeneratePrivate(keySpec);
+ } catch (Exception e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi);
+ }
+ } while (mySpi != null);
+ if (failure instanceof RuntimeException) {
+ throw (RuntimeException)failure;
+ }
+ if (failure instanceof InvalidKeySpecException) {
+ throw (InvalidKeySpecException)failure;
+ }
+ throw new InvalidKeySpecException
+ ("Could not generate private key", failure);
+ }
+
+ /**
+ * Returns a specification (key material) of the given key object.
+ * {@code keySpec} identifies the specification class in which
+ * the key material should be returned. It could, for example, be
+ * {@code DSAPublicKeySpec.class}, to indicate that the
+ * key material should be returned in an instance of the
+ * {@code DSAPublicKeySpec} class.
+ *
+ * @param <T> the type of the key specification to be returned
+ *
+ * @param key the key.
+ *
+ * @param keySpec the specification class in which
+ * the key material should be returned.
+ *
+ * @return the underlying key specification (key material) in an instance
+ * of the requested specification class.
+ *
+ * @exception InvalidKeySpecException if the requested key specification is
+ * inappropriate for the given key, or the given key cannot be processed
+ * (e.g., the given key has an unrecognized algorithm or format).
+ */
+ public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)
+ throws InvalidKeySpecException {
+ if (serviceIterator == null) {
+ return spi.engineGetKeySpec(key, keySpec);
+ }
+ Exception failure = null;
+ KeyFactorySpi 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 RuntimeException) {
+ throw (RuntimeException)failure;
+ }
+ 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 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 key factory.
+ */
+ public final Key translateKey(Key key) throws InvalidKeyException {
+ if (serviceIterator == null) {
+ return spi.engineTranslateKey(key);
+ }
+ Exception failure = null;
+ KeyFactorySpi 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 RuntimeException) {
+ throw (RuntimeException)failure;
+ }
+ if (failure instanceof InvalidKeyException) {
+ throw (InvalidKeyException)failure;
+ }
+ throw new InvalidKeyException
+ ("Could not translate key", failure);
+ }
+
+}
diff --git a/java/security/KeyFactorySpi.java b/java/security/KeyFactorySpi.java
new file mode 100644
index 0000000..5ee7f45
--- /dev/null
+++ b/java/security/KeyFactorySpi.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.security.spec.KeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code KeyFactory} 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 factory for a particular algorithm.
+ *
+ * <P> Key factories are used to convert <I>keys</I> (opaque
+ * cryptographic keys of type {@code Key}) into <I>key specifications</I>
+ * (transparent representations of the underlying key material), and vice
+ * versa.
+ *
+ * <P> Key factories are bi-directional. That is, they allow you 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.
+ *
+ * <P> Multiple compatible key specifications may exist for the same key.
+ * For example, a DSA public key may be specified using
+ * {@code DSAPublicKeySpec} or
+ * {@code X509EncodedKeySpec}. A key factory can be used to translate
+ * between compatible key specifications.
+ *
+ * <P> A provider should document all the key specifications supported by its
+ * key factory.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see KeyFactory
+ * @see Key
+ * @see PublicKey
+ * @see PrivateKey
+ * @see java.security.spec.KeySpec
+ * @see java.security.spec.DSAPublicKeySpec
+ * @see java.security.spec.X509EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public abstract class KeyFactorySpi {
+
+ /**
+ * Generates a public key object from the provided key
+ * specification (key material).
+ *
+ * @param keySpec the specification (key material) of the public key.
+ *
+ * @return the public key.
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this key factory to produce a public key.
+ */
+ protected abstract PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Generates a private key object from the provided key
+ * specification (key material).
+ *
+ * @param keySpec the specification (key material) of the private key.
+ *
+ * @return the private key.
+ *
+ * @exception InvalidKeySpecException if the given key specification
+ * is inappropriate for this key factory to produce a private key.
+ */
+ protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Returns a specification (key material) of the given key
+ * object.
+ * {@code keySpec} identifies the specification class in which
+ * the key material should be returned. It could, for example, be
+ * {@code DSAPublicKeySpec.class}, to indicate that the
+ * key material should be returned in an instance of the
+ * {@code DSAPublicKeySpec} class.
+ *
+ * @param <T> the type of the key specification to be returned
+ *
+ * @param key the key.
+ *
+ * @param keySpec the specification class in which
+ * the key material should be returned.
+ *
+ * @return the underlying key specification (key material) in an instance
+ * of the requested specification class.
+
+ * @exception InvalidKeySpecException if the requested key specification is
+ * inappropriate for the given key, or the given key cannot be dealt with
+ * (e.g., the given key has an unrecognized format).
+ */
+ protected abstract <T extends KeySpec>
+ T engineGetKeySpec(Key key, Class<T> keySpec)
+ throws InvalidKeySpecException;
+
+ /**
+ * Translates a key object, whose provider may be unknown or
+ * potentially untrusted, into a corresponding key object of this 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 key factory.
+ */
+ protected abstract Key engineTranslateKey(Key key)
+ throws InvalidKeyException;
+
+}
diff --git a/java/security/KeyManagementException.java b/java/security/KeyManagementException.java
new file mode 100644
index 0000000..be212b9
--- /dev/null
+++ b/java/security/KeyManagementException.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This is the general key management exception for all operations
+ * dealing with key management. Examples of subclasses of
+ * KeyManagementException that developers might create for
+ * giving more detailed information could include:
+ *
+ * <ul>
+ * <li>KeyIDConflictException
+ * <li>KeyAuthorizationFailureException
+ * <li>ExpiredKeyException
+ * </ul>
+ *
+ * @author Benjamin Renaud
+ *
+ * @see Key
+ * @see KeyException
+ */
+
+public class KeyManagementException extends KeyException {
+
+ private static final long serialVersionUID = 947674216157062695L;
+
+ /**
+ * Constructs a KeyManagementException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public KeyManagementException() {
+ super();
+ }
+
+ /**
+ * Constructs a KeyManagementException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public KeyManagementException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code KeyManagementException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public KeyManagementException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code KeyManagementException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public KeyManagementException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/KeyPair.java b/java/security/KeyPair.java
new file mode 100644
index 0000000..6147a16
--- /dev/null
+++ b/java/security/KeyPair.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+
+/**
+ * This class is a simple holder for a key pair (a public key and a
+ * private key). It does not enforce any security, and, when initialized,
+ * should be treated like a PrivateKey.
+ *
+ * @see PublicKey
+ * @see PrivateKey
+ *
+ * @author Benjamin Renaud
+ */
+
+public final class KeyPair implements java.io.Serializable {
+
+ private static final long serialVersionUID = -7565189502268009837L;
+
+ private PrivateKey privateKey;
+ private PublicKey publicKey;
+
+ /**
+ * Constructs a key pair from the given public key and private key.
+ *
+ * <p>Note that this constructor only stores references to the public
+ * and private key components in the generated key pair. This is safe,
+ * because {@code Key} objects are immutable.
+ *
+ * @param publicKey the public key.
+ *
+ * @param privateKey the private key.
+ */
+ public KeyPair(PublicKey publicKey, PrivateKey privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ /**
+ * Returns a reference to the public key component of this key pair.
+ *
+ * @return a reference to the public key.
+ */
+ public PublicKey getPublic() {
+ return publicKey;
+ }
+
+ /**
+ * Returns a reference to the private key component of this key pair.
+ *
+ * @return a reference to the private key.
+ */
+ public PrivateKey getPrivate() {
+ return privateKey;
+ }
+}
diff --git a/java/security/KeyPairGenerator.java b/java/security/KeyPairGenerator.java
new file mode 100644
index 0000000..68ab5e9
--- /dev/null
+++ b/java/security/KeyPairGenerator.java
@@ -0,0 +1,741 @@
+/*
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+import java.security.Provider.Service;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * The KeyPairGenerator class is used to generate pairs of
+ * public and private keys. Key pair generators are constructed using the
+ * {@code getInstance} factory methods (static methods that
+ * return instances of a given class).
+ *
+ * <p>A Key pair generator for a particular algorithm creates a public/private
+ * key pair that can be used with this algorithm. It also associates
+ * algorithm-specific parameters with each of the generated keys.
+ *
+ * <p>There are two ways to generate a key pair: in an algorithm-independent
+ * manner, and in an algorithm-specific manner.
+ * The only difference between the two is the initialization of the object:
+ *
+ * <ul>
+ * <li><b>Algorithm-Independent Initialization</b>
+ * <p>All key pair generators share the concepts of a keysize and a
+ * source of randomness. The keysize is interpreted differently for different
+ * algorithms (e.g., in the case of the <i>DSA</i> algorithm, the keysize
+ * corresponds to the length of the modulus).
+ * There is an
+ * {@link #initialize(int, java.security.SecureRandom) initialize}
+ * method in this KeyPairGenerator class that takes these two universally
+ * shared types of arguments. There is also one that takes just a
+ * {@code keysize} argument, and uses the {@code SecureRandom}
+ * implementation of the highest-priority installed provider as the source
+ * of randomness. (If none of the installed providers supply an implementation
+ * of {@code SecureRandom}, a system-provided source of randomness is
+ * used.)
+ *
+ * <p>Since no other parameters are specified when you call the above
+ * algorithm-independent {@code initialize} 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.
+ *
+ * <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus
+ * size) is 512, 768, or 1024, then the <i>Sun</i> provider uses a set of
+ * precomputed values for the {@code p}, {@code q}, and
+ * {@code g} parameters. If the modulus size is not one of the above
+ * values, the <i>Sun</i> provider creates a new set of parameters. Other
+ * providers might have precomputed parameter sets for more than just the
+ * three modulus sizes mentioned above. Still others might not have a list of
+ * precomputed parameters at all and instead always create new parameter sets.
+ *
+ * <li><b>Algorithm-Specific Initialization</b>
+ * <p>For situations where a set of algorithm-specific parameters already
+ * exists (e.g., so-called <i>community parameters</i> in DSA), there are two
+ * {@link #initialize(java.security.spec.AlgorithmParameterSpec)
+ * initialize} methods that have an {@code AlgorithmParameterSpec}
+ * argument. One also has a {@code SecureRandom} argument, while the
+ * the other uses the {@code SecureRandom}
+ * implementation of the highest-priority installed provider as the source
+ * of randomness. (If none of the installed providers supply an implementation
+ * of {@code SecureRandom}, a system-provided source of randomness is
+ * used.)
+ * </ul>
+ *
+ * <p>In case the client does not explicitly initialize the KeyPairGenerator
+ * (via a call to an {@code initialize} method), each provider must
+ * supply (and document) a default initialization.
+ * For example, the <i>Sun</i> provider uses a default modulus size (keysize)
+ * of 1024 bits.
+ *
+ * <p>Note that this class is abstract and extends from
+ * {@code KeyPairGeneratorSpi} for historical reasons.
+ * Application developers should only take notice of the methods defined in
+ * this {@code KeyPairGenerator} class; all the methods in
+ * the superclass are intended for cryptographic service providers who wish to
+ * supply their own implementations of key pair generators.
+ *
+ * <p> Android provides the following <code>KeyPairGenerator</code> algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>DH</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>EC</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>RSA</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These algorithms are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * KeyPairGenerator section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Benjamin Renaud
+ *
+ * @see java.security.spec.AlgorithmParameterSpec
+ */
+
+public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
+
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
+ private static final Debug pdebug =
+ Debug.getInstance("provider", "Provider");
+ private static final boolean skipDebug =
+ Debug.isOn("engine=") && !Debug.isOn("keypairgenerator");
+ */
+
+ private final String algorithm;
+
+ // The provider
+ Provider provider;
+
+ /**
+ * Creates a KeyPairGenerator object for the specified algorithm.
+ *
+ * @param algorithm the standard string name of the algorithm.
+ * See the KeyPairGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ */
+ protected KeyPairGenerator(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns the standard name of the algorithm for this key pair generator.
+ * See the KeyPairGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the standard string name of the algorithm.
+ */
+ public String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ private static KeyPairGenerator getInstance(Instance instance,
+ String algorithm) {
+ KeyPairGenerator kpg;
+ if (instance.impl instanceof KeyPairGenerator) {
+ kpg = (KeyPairGenerator)instance.impl;
+ } else {
+ KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)instance.impl;
+ kpg = new Delegate(spi, algorithm);
+ }
+ kpg.provider = instance.provider;
+
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("KeyPairGenerator." + algorithm +
+ " algorithm from: " + kpg.provider.getName());
+ }
+ */
+
+ return kpg;
+ }
+
+ /**
+ * Returns a KeyPairGenerator object that generates public/private
+ * key pairs for the specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new KeyPairGenerator object encapsulating the
+ * KeyPairGeneratorSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard string name of the algorithm.
+ * See the KeyPairGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new KeyPairGenerator object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * KeyPairGeneratorSpi implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ */
+ public static KeyPairGenerator getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ List<Service> list =
+ GetInstance.getServices("KeyPairGenerator", algorithm);
+ Iterator<Service> t = list.iterator();
+ if (t.hasNext() == false) {
+ throw new NoSuchAlgorithmException
+ (algorithm + " KeyPairGenerator not available");
+ }
+ // find a working Spi or KeyPairGenerator subclass
+ NoSuchAlgorithmException failure = null;
+ do {
+ Service s = t.next();
+ try {
+ Instance instance =
+ GetInstance.getInstance(s, KeyPairGeneratorSpi.class);
+ if (instance.impl instanceof KeyPairGenerator) {
+ return getInstance(instance, algorithm);
+ } else {
+ return new Delegate(instance, t, algorithm);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ if (failure == null) {
+ failure = e;
+ }
+ }
+ } while (t.hasNext());
+ throw failure;
+ }
+
+ /**
+ * Returns a KeyPairGenerator object that generates public/private
+ * key pairs for the specified algorithm.
+ *
+ * <p> A new KeyPairGenerator object encapsulating the
+ * KeyPairGeneratorSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the standard string name of the algorithm.
+ * See the KeyPairGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the string name of the provider.
+ *
+ * @return the new KeyPairGenerator object.
+ *
+ * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static KeyPairGenerator getInstance(String algorithm,
+ String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ Instance instance = GetInstance.getInstance("KeyPairGenerator",
+ KeyPairGeneratorSpi.class, algorithm, provider);
+ return getInstance(instance, algorithm);
+ }
+
+ /**
+ * Returns a KeyPairGenerator object that generates public/private
+ * key pairs for the specified algorithm.
+ *
+ * <p> A new KeyPairGenerator object encapsulating the
+ * KeyPairGeneratorSpi 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 string name of the algorithm.
+ * See the KeyPairGenerator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new KeyPairGenerator object.
+ *
+ * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the specified provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static KeyPairGenerator getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("KeyPairGenerator",
+ KeyPairGeneratorSpi.class, algorithm, provider);
+ return getInstance(instance, algorithm);
+ }
+
+ /**
+ * Returns the provider of this key pair generator object.
+ *
+ * @return the provider of this key pair generator object
+ */
+ public final Provider getProvider() {
+ disableFailover();
+ return this.provider;
+ }
+
+ void disableFailover() {
+ // empty, overridden in Delegate
+ }
+
+ /**
+ * Initializes the key pair generator for a certain keysize using
+ * a default parameter set and the {@code SecureRandom}
+ * implementation of the highest-priority installed provider as the source
+ * of randomness.
+ * (If none of the installed providers supply an implementation of
+ * {@code SecureRandom}, a system-provided source of randomness is
+ * used.)
+ *
+ * @param keysize the keysize. This is an
+ * algorithm-specific metric, such as modulus length, specified in
+ * number of bits.
+ *
+ * @exception InvalidParameterException if the {@code keysize} is not
+ * supported by this KeyPairGenerator object.
+ */
+ public void initialize(int keysize) {
+ initialize(keysize, JCAUtil.getSecureRandom());
+ }
+
+ /**
+ * Initializes the key pair generator for a certain keysize with
+ * the given source of randomness (and a default parameter set).
+ *
+ * @param keysize the keysize. This is an
+ * algorithm-specific metric, such as modulus length, specified in
+ * number of bits.
+ * @param random the source of randomness.
+ *
+ * @exception InvalidParameterException if the {@code keysize} is not
+ * supported by this KeyPairGenerator object.
+ *
+ * @since 1.2
+ */
+ public void initialize(int keysize, SecureRandom random) {
+ // This does nothing, because either
+ // 1. the implementation object returned by getInstance() is an
+ // instance of KeyPairGenerator which has its own
+ // initialize(keysize, random) method, so the application would
+ // be calling that method directly, or
+ // 2. the implementation returned by getInstance() is an instance
+ // of Delegate, in which case initialize(keysize, random) is
+ // overridden to call the corresponding SPI method.
+ // (This is a special case, because the API and SPI method have the
+ // same name.)
+ }
+
+ /**
+ * Initializes the key pair generator using the specified parameter
+ * set and the {@code SecureRandom}
+ * implementation of the highest-priority installed provider as the source
+ * of randomness.
+ * (If none of the installed providers supply an implementation of
+ * {@code SecureRandom}, a system-provided source of randomness is
+ * used.).
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class.
+ * This method calls the KeyPairGeneratorSpi
+ * {@link KeyPairGeneratorSpi#initialize(
+ * java.security.spec.AlgorithmParameterSpec,
+ * java.security.SecureRandom) initialize} method,
+ * passing it {@code params} and a source of randomness (obtained
+ * from the highest-priority installed provider or system-provided if none
+ * of the installed providers supply one).
+ * That {@code initialize} method always throws an
+ * UnsupportedOperationException if it is not overridden by the provider.
+ *
+ * @param params the parameter set used to generate the keys.
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key pair generator.
+ *
+ * @since 1.2
+ */
+ public void initialize(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ initialize(params, JCAUtil.getSecureRandom());
+ }
+
+ /**
+ * Initializes the key pair generator with the given parameter
+ * set and source of randomness.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class.
+ * This method calls the KeyPairGeneratorSpi {@link
+ * KeyPairGeneratorSpi#initialize(
+ * java.security.spec.AlgorithmParameterSpec,
+ * java.security.SecureRandom) initialize} method,
+ * passing it {@code params} and {@code random}.
+ * That {@code initialize}
+ * method always throws an
+ * UnsupportedOperationException if it is not overridden by the provider.
+ *
+ * @param params the parameter set used to generate the keys.
+ * @param random the source of randomness.
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key pair generator.
+ *
+ * @since 1.2
+ */
+ public void initialize(AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException
+ {
+ // This does nothing, because either
+ // 1. the implementation object returned by getInstance() is an
+ // instance of KeyPairGenerator which has its own
+ // initialize(params, random) method, so the application would
+ // be calling that method directly, or
+ // 2. the implementation returned by getInstance() is an instance
+ // of Delegate, in which case initialize(params, random) is
+ // overridden to call the corresponding SPI method.
+ // (This is a special case, because the API and SPI method have the
+ // same name.)
+ }
+
+ /**
+ * Generates a key pair.
+ *
+ * <p>If this KeyPairGenerator has not been initialized explicitly,
+ * provider-specific defaults will be used for the size and other
+ * (algorithm-specific) values of the generated keys.
+ *
+ * <p>This will generate a new key pair every time it is called.
+ *
+ * <p>This method is functionally equivalent to
+ * {@link #generateKeyPair() generateKeyPair}.
+ *
+ * @return the generated key pair
+ *
+ * @since 1.2
+ */
+ public final KeyPair genKeyPair() {
+ return generateKeyPair();
+ }
+
+ /**
+ * Generates a key pair.
+ *
+ * <p>If this KeyPairGenerator has not been initialized explicitly,
+ * provider-specific defaults will be used for the size and other
+ * (algorithm-specific) values of the generated keys.
+ *
+ * <p>This will generate a new key pair every time it is called.
+ *
+ * <p>This method is functionally equivalent to
+ * {@link #genKeyPair() genKeyPair}.
+ *
+ * @return the generated key pair
+ */
+ public KeyPair generateKeyPair() {
+ // This does nothing (except returning null), because either:
+ //
+ // 1. the implementation object returned by getInstance() is an
+ // instance of KeyPairGenerator which has its own implementation
+ // of generateKeyPair (overriding this one), so the application
+ // would be calling that method directly, or
+ //
+ // 2. the implementation returned by getInstance() is an instance
+ // of Delegate, in which case generateKeyPair is
+ // overridden to invoke the corresponding SPI method.
+ //
+ // (This is a special case, because in JDK 1.1.x the generateKeyPair
+ // method was used both as an API and a SPI method.)
+ return null;
+ }
+
+
+ /*
+ * The following class allows providers to extend from KeyPairGeneratorSpi
+ * rather than from KeyPairGenerator. It represents a KeyPairGenerator
+ * with an encapsulated, provider-supplied SPI object (of type
+ * KeyPairGeneratorSpi).
+ * If the provider implementation is an instance of KeyPairGeneratorSpi,
+ * the getInstance() methods above return an instance of this class, with
+ * the SPI object encapsulated.
+ *
+ * Note: All SPI methods from the original KeyPairGenerator class have been
+ * moved up the hierarchy into a new class (KeyPairGeneratorSpi), which has
+ * been interposed in the hierarchy between the API (KeyPairGenerator)
+ * and its original parent (Object).
+ */
+
+ //
+ // error failover notes:
+ //
+ // . we failover if the implementation throws an error during init
+ // by retrying the init on other providers
+ //
+ // . we also failover if the init succeeded but the subsequent call
+ // to generateKeyPair() fails. In order for this to work, we need
+ // to remember the parameters to the last successful call to init
+ // and initialize() the next spi using them.
+ //
+ // . although not specified, KeyPairGenerators could be thread safe,
+ // so we make sure we do not interfere with that
+ //
+ // . failover is not available, if:
+ // . getInstance(algorithm, provider) was used
+ // . a provider extends KeyPairGenerator rather than
+ // KeyPairGeneratorSpi (JDK 1.1 style)
+ // . once getProvider() is called
+ //
+
+ private static final class Delegate extends KeyPairGenerator {
+
+ // The provider implementation (delegate)
+ private volatile KeyPairGeneratorSpi spi;
+
+ private final Object lock = new Object();
+
+ private Iterator<Service> serviceIterator;
+
+ private final static int I_NONE = 1;
+ private final static int I_SIZE = 2;
+ private final static int I_PARAMS = 3;
+
+ private int initType;
+ private int initKeySize;
+ private AlgorithmParameterSpec initParams;
+ private SecureRandom initRandom;
+
+ // constructor
+ Delegate(KeyPairGeneratorSpi spi, String algorithm) {
+ super(algorithm);
+ this.spi = spi;
+ }
+
+ Delegate(Instance instance, Iterator<Service> serviceIterator,
+ String algorithm) {
+ super(algorithm);
+ spi = (KeyPairGeneratorSpi)instance.impl;
+ provider = instance.provider;
+ this.serviceIterator = serviceIterator;
+ initType = I_NONE;
+
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("KeyPairGenerator." + algorithm +
+ " algorithm from: " + provider.getName());
+ }
+ */
+ }
+
+ /**
+ * 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 KeyPairGeneratorSpi nextSpi(KeyPairGeneratorSpi 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 = serviceIterator.next();
+ try {
+ Object inst = s.newInstance(null);
+ // ignore non-spis
+ if (inst instanceof KeyPairGeneratorSpi == false) {
+ continue;
+ }
+ if (inst instanceof KeyPairGenerator) {
+ continue;
+ }
+ KeyPairGeneratorSpi spi = (KeyPairGeneratorSpi)inst;
+ if (reinit) {
+ if (initType == I_SIZE) {
+ spi.initialize(initKeySize, initRandom);
+ } else if (initType == I_PARAMS) {
+ spi.initialize(initParams, initRandom);
+ } else if (initType != I_NONE) {
+ throw new AssertionError
+ ("KeyPairGenerator 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;
+ }
+
+ // engine method
+ public void initialize(int keysize, SecureRandom random) {
+ if (serviceIterator == null) {
+ spi.initialize(keysize, random);
+ return;
+ }
+ RuntimeException failure = null;
+ KeyPairGeneratorSpi mySpi = spi;
+ do {
+ try {
+ mySpi.initialize(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;
+ }
+
+ // engine method
+ public void initialize(AlgorithmParameterSpec params,
+ SecureRandom random) throws InvalidAlgorithmParameterException {
+ if (serviceIterator == null) {
+ spi.initialize(params, random);
+ return;
+ }
+ Exception failure = null;
+ KeyPairGeneratorSpi mySpi = spi;
+ do {
+ try {
+ mySpi.initialize(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 RuntimeException) {
+ throw (RuntimeException)failure;
+ }
+ // must be an InvalidAlgorithmParameterException
+ throw (InvalidAlgorithmParameterException)failure;
+ }
+
+ // engine method
+ public KeyPair generateKeyPair() {
+ if (serviceIterator == null) {
+ return spi.generateKeyPair();
+ }
+ RuntimeException failure = null;
+ KeyPairGeneratorSpi mySpi = spi;
+ do {
+ try {
+ return mySpi.generateKeyPair();
+ } catch (RuntimeException e) {
+ if (failure == null) {
+ failure = e;
+ }
+ mySpi = nextSpi(mySpi, true);
+ }
+ } while (mySpi != null);
+ throw failure;
+ }
+ }
+
+}
diff --git a/java/security/KeyPairGeneratorSpi.java b/java/security/KeyPairGeneratorSpi.java
new file mode 100644
index 0000000..dfe8c04
--- /dev/null
+++ b/java/security/KeyPairGeneratorSpi.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * <p> This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code KeyPairGenerator} class, which is used to generate
+ * pairs of public and private keys.
+ *
+ * <p> All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a key pair generator for a particular algorithm.
+ *
+ * <p> In case the client does not explicitly initialize the KeyPairGenerator
+ * (via a call to an {@code initialize} method), each provider must
+ * supply (and document) a default initialization.
+ * For example, the <i>Sun</i> provider uses a default modulus size (keysize)
+ * of 1024 bits.
+ *
+ * @author Benjamin Renaud
+ *
+ *
+ * @see KeyPairGenerator
+ * @see java.security.spec.AlgorithmParameterSpec
+ */
+
+public abstract class KeyPairGeneratorSpi {
+
+ /**
+ * Initializes the key pair generator for a certain keysize, using
+ * the default parameter set.
+ *
+ * @param keysize the keysize. This is an
+ * algorithm-specific metric, such as modulus length, specified in
+ * number of bits.
+ *
+ * @param random the source of randomness for this generator.
+ *
+ * @exception InvalidParameterException if the {@code keysize} is not
+ * supported by this KeyPairGeneratorSpi object.
+ */
+ public abstract void initialize(int keysize, SecureRandom random);
+
+ /**
+ * Initializes the key pair generator using the specified parameter
+ * set and user-provided source of randomness.
+ *
+ * <p>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 initialize the key pair
+ * generator. Such an override
+ * is expected to throw an InvalidAlgorithmParameterException if
+ * a parameter is inappropriate for this key pair generator.
+ * If this method is not overridden, it always throws an
+ * UnsupportedOperationException.
+ *
+ * @param params the parameter set used to generate the keys.
+ *
+ * @param random the source of randomness for this generator.
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this key pair generator.
+ *
+ * @since 1.2
+ */
+ public void initialize(AlgorithmParameterSpec params,
+ SecureRandom random)
+ throws InvalidAlgorithmParameterException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Generates a key pair. Unless an initialization method is called
+ * using a KeyPairGenerator interface, algorithm-specific defaults
+ * will be used. This will generate a new key pair every time it
+ * is called.
+ *
+ * @return the newly generated {@code KeyPair}
+ */
+ public abstract KeyPair generateKeyPair();
+}
diff --git a/java/security/KeyRep.java b/java/security/KeyRep.java
new file mode 100644
index 0000000..97a6c16
--- /dev/null
+++ b/java/security/KeyRep.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.util.Locale;
+
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Standardized representation for serialized Key objects.
+ *
+ * <p>
+ *
+ * Note that a serialized Key may contain sensitive information
+ * which should not be exposed in untrusted environments. See the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/security.html">
+ * Security Appendix</a>
+ * of the Serialization Specification for more information.
+ *
+ * @see Key
+ * @see KeyFactory
+ * @see javax.crypto.spec.SecretKeySpec
+ * @see java.security.spec.X509EncodedKeySpec
+ * @see java.security.spec.PKCS8EncodedKeySpec
+ *
+ * @since 1.5
+ */
+
+public class KeyRep implements Serializable {
+
+ private static final long serialVersionUID = -4757683898830641853L;
+
+ /**
+ * Key type.
+ *
+ * @since 1.5
+ */
+ public static enum Type {
+
+ /** Type for secret keys. */
+ SECRET,
+
+ /** Type for public keys. */
+ PUBLIC,
+
+ /** Type for private keys. */
+ PRIVATE,
+
+ }
+
+ private static final String PKCS8 = "PKCS#8";
+ private static final String X509 = "X.509";
+ private static final String RAW = "RAW";
+
+ /**
+ * Either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE
+ *
+ * @serial
+ */
+ private Type type;
+
+ /**
+ * The Key algorithm
+ *
+ * @serial
+ */
+ private String algorithm;
+
+ /**
+ * The Key encoding format
+ *
+ * @serial
+ */
+ private String format;
+
+ /**
+ * The encoded Key bytes
+ *
+ * @serial
+ */
+ private byte[] encoded;
+
+ /**
+ * Construct the alternate Key class.
+ *
+ * <p>
+ *
+ * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE
+ * @param algorithm the algorithm returned from
+ * {@code Key.getAlgorithm()}
+ * @param format the encoding format returned from
+ * {@code Key.getFormat()}
+ * @param encoded the encoded bytes returned from
+ * {@code Key.getEncoded()}
+ *
+ * @exception NullPointerException
+ * if type is {@code null},
+ * if algorithm is {@code null},
+ * if format is {@code null},
+ * or if encoded is {@code null}
+ */
+ public KeyRep(Type type, String algorithm,
+ String format, byte[] encoded) {
+
+ if (type == null || algorithm == null ||
+ format == null || encoded == null) {
+ throw new NullPointerException("invalid null input(s)");
+ }
+
+ this.type = type;
+ this.algorithm = algorithm;
+ this.format = format.toUpperCase(Locale.ENGLISH);
+ this.encoded = encoded.clone();
+ }
+
+ /**
+ * Resolve the Key object.
+ *
+ * <p> This method supports three Type/format combinations:
+ * <ul>
+ * <li> Type.SECRET/"RAW" - returns a SecretKeySpec object
+ * constructed using encoded key bytes and algorithm
+ * <li> Type.PUBLIC/"X.509" - gets a KeyFactory instance for
+ * the key algorithm, constructs an X509EncodedKeySpec with the
+ * encoded key bytes, and generates a public key from the spec
+ * <li> Type.PRIVATE/"PKCS#8" - gets a KeyFactory instance for
+ * the key algorithm, constructs a PKCS8EncodedKeySpec with the
+ * encoded key bytes, and generates a private key from the spec
+ * </ul>
+ *
+ * <p>
+ *
+ * @return the resolved Key object
+ *
+ * @exception ObjectStreamException if the Type/format
+ * combination is unrecognized, if the algorithm, key format, or
+ * encoded key bytes are unrecognized/invalid, of if the
+ * resolution of the key fails for any reason
+ */
+ protected Object readResolve() throws ObjectStreamException {
+ try {
+ if (type == Type.SECRET && RAW.equals(format)) {
+ return new SecretKeySpec(encoded, algorithm);
+ } else if (type == Type.PUBLIC && X509.equals(format)) {
+ KeyFactory f = KeyFactory.getInstance(algorithm);
+ return f.generatePublic(new X509EncodedKeySpec(encoded));
+ } else if (type == Type.PRIVATE && PKCS8.equals(format)) {
+ KeyFactory f = KeyFactory.getInstance(algorithm);
+ return f.generatePrivate(new PKCS8EncodedKeySpec(encoded));
+ } else {
+ throw new NotSerializableException
+ ("unrecognized type/format combination: " +
+ type + "/" + format);
+ }
+ } catch (NotSerializableException nse) {
+ throw nse;
+ } catch (Exception e) {
+ NotSerializableException nse = new NotSerializableException
+ ("java.security.Key: " +
+ "[" + type + "] " +
+ "[" + algorithm + "] " +
+ "[" + format + "]");
+ nse.initCause(e);
+ throw nse;
+ }
+ }
+}
diff --git a/java/security/KeyStore.java b/java/security/KeyStore.java
new file mode 100644
index 0000000..d091781
--- /dev/null
+++ b/java/security/KeyStore.java
@@ -0,0 +1,2040 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.net.URI;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.*;
+import javax.crypto.SecretKey;
+
+import javax.security.auth.DestroyFailedException;
+import javax.security.auth.callback.*;
+
+/**
+ * This class represents a storage facility for cryptographic
+ * keys and certificates.
+ *
+ * <p> A {@code KeyStore} manages different types of entries.
+ * Each type of entry implements the {@code KeyStore.Entry} interface.
+ * Three basic {@code KeyStore.Entry} implementations are provided:
+ *
+ * <ul>
+ * <li><b>KeyStore.PrivateKeyEntry</b>
+ * <p> This type of entry holds a cryptographic {@code PrivateKey},
+ * which is optionally stored in a protected format to prevent
+ * unauthorized access. It is also accompanied by a certificate chain
+ * for the corresponding public key.
+ *
+ * <p> Private keys and certificate chains are used by a given entity for
+ * self-authentication. Applications for this authentication include software
+ * distribution organizations which sign JAR files as part of releasing
+ * and/or licensing software.
+ *
+ * <li><b>KeyStore.SecretKeyEntry</b>
+ * <p> This type of entry holds a cryptographic {@code SecretKey},
+ * which is optionally stored in a protected format to prevent
+ * unauthorized access.
+ *
+ * <li><b>KeyStore.TrustedCertificateEntry</b>
+ * <p> This type of entry contains a single public key {@code Certificate}
+ * belonging to another party. It is called a <i>trusted certificate</i>
+ * because the keystore owner trusts that the public key in the certificate
+ * indeed belongs to the identity identified by the <i>subject</i> (owner)
+ * of the certificate.
+ *
+ * <p>This type of entry can be used to authenticate other parties.
+ * </ul>
+ *
+ * <p> Each entry in a keystore is identified by an "alias" string. In the
+ * case of private keys and their associated certificate chains, these strings
+ * distinguish among the different ways in which the entity may authenticate
+ * itself. For example, the entity may authenticate itself using different
+ * certificate authorities, or using different public key algorithms.
+ *
+ * <p> Whether aliases are case sensitive is implementation dependent. In order
+ * to avoid problems, it is recommended not to use aliases in a KeyStore that
+ * only differ in case.
+ *
+ * <p> Whether keystores are persistent, and the mechanisms used by the
+ * keystore if it is persistent, are not specified here. This allows
+ * use of a variety of techniques for protecting sensitive (e.g., private or
+ * secret) keys. Smart cards or other integrated cryptographic engines
+ * (SafeKeyper) are one option, and simpler mechanisms such as files may also
+ * be used (in a variety of formats).
+ *
+ * <p> Typical ways to request a KeyStore object include
+ * relying on the default type and providing a specific keystore type.
+ *
+ * <ul>
+ * <li>To rely on the default type:
+ * <pre>
+ * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ * </pre>
+ * The system will return a keystore implementation for the default type.
+ *
+ * <li>To provide a specific keystore type:
+ * <pre>
+ * KeyStore ks = KeyStore.getInstance("JKS");
+ * </pre>
+ * The system will return the most preferred implementation of the
+ * specified keystore type available in the environment. <p>
+ * </ul>
+ *
+ * <p> Before a keystore can be accessed, it must be
+ * {@link #load(java.io.InputStream, char[]) loaded}.
+ * <pre>
+ * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ *
+ * // get user password and file input stream
+ * char[] password = getPassword();
+ *
+ * try (FileInputStream fis = new FileInputStream("keyStoreName")) {
+ * ks.load(fis, password);
+ * }
+ * </pre>
+ *
+ * To create an empty keystore using the above {@code load} method,
+ * pass {@code null} as the {@code InputStream} argument.
+ *
+ * <p> Once the keystore has been loaded, it is possible
+ * to read existing entries from the keystore, or to write new entries
+ * into the keystore:
+ * <pre>
+ * KeyStore.ProtectionParameter protParam =
+ * new KeyStore.PasswordProtection(password);
+ *
+ * // get my private key
+ * KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
+ * ks.getEntry("privateKeyAlias", protParam);
+ * PrivateKey myPrivateKey = pkEntry.getPrivateKey();
+ *
+ * // save my secret key
+ * javax.crypto.SecretKey mySecretKey;
+ * KeyStore.SecretKeyEntry skEntry =
+ * new KeyStore.SecretKeyEntry(mySecretKey);
+ * ks.setEntry("secretKeyAlias", skEntry, protParam);
+ *
+ * // store away the keystore
+ * try (FileOutputStream fos = new FileOutputStream("newKeyStoreName")) {
+ * ks.store(fos, password);
+ * }
+ * </pre>
+ *
+ * Note that although the same password may be used to
+ * load the keystore, to protect the private key entry,
+ * to protect the secret key entry, and to store the keystore
+ * (as is shown in the sample code above),
+ * different passwords or other protection parameters
+ * may also be used.
+ *
+ * <p> Android provides the following <code>KeyStore</code> types:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>AndroidCAStore</td>
+ * <td>14+</td>
+ * </tr>
+ * <tr>
+ * <td>AndroidKeyStore</td>
+ * <td>18+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>BCPKCS12</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>BKS</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>BouncyCastle</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>PKCS12</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>PKCS12-DEF</td>
+ * <td>1-8</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These types are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyStore">
+ * KeyStore section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Jan Luehe
+ *
+ * @see java.security.PrivateKey
+ * @see javax.crypto.SecretKey
+ * @see java.security.cert.Certificate
+ *
+ * @since 1.2
+ */
+
+public class KeyStore {
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ private static final Debug pdebug =
+ Debug.getInstance("provider", "Provider");
+ private static final boolean skipDebug =
+ Debug.isOn("engine=") && !Debug.isOn("keystore");
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+
+ /*
+ * Constant to lookup in the Security properties file to determine
+ * the default keystore type.
+ * In the Security properties file, the default keystore type is given as:
+ * <pre>
+ * keystore.type=jks
+ * </pre>
+ */
+ private static final String KEYSTORE_TYPE = "keystore.type";
+
+ // The keystore type
+ private String type;
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation
+ private KeyStoreSpi keyStoreSpi;
+
+ // Has this keystore been initialized (loaded)?
+ private boolean initialized = false;
+
+ /**
+ * A marker interface for {@code KeyStore}
+ * {@link #load(KeyStore.LoadStoreParameter) load}
+ * and
+ * {@link #store(KeyStore.LoadStoreParameter) store}
+ * parameters.
+ *
+ * @since 1.5
+ */
+ public static interface LoadStoreParameter {
+ /**
+ * Gets the parameter used to protect keystore data.
+ *
+ * @return the parameter used to protect keystore data, or null
+ */
+ public ProtectionParameter getProtectionParameter();
+ }
+
+ /**
+ * A marker interface for keystore protection parameters.
+ *
+ * <p> The information stored in a {@code ProtectionParameter}
+ * object protects the contents of a keystore.
+ * For example, protection parameters may be used to check
+ * the integrity of keystore data, or to protect the
+ * confidentiality of sensitive keystore data
+ * (such as a {@code PrivateKey}).
+ *
+ * @since 1.5
+ */
+ public static interface ProtectionParameter { }
+
+ /**
+ * A password-based implementation of {@code ProtectionParameter}.
+ *
+ * @since 1.5
+ */
+ public static class PasswordProtection implements
+ ProtectionParameter, javax.security.auth.Destroyable {
+
+ private final char[] password;
+ private final String protectionAlgorithm;
+ private final AlgorithmParameterSpec protectionParameters;
+ private volatile boolean destroyed = false;
+
+ /**
+ * Creates a password parameter.
+ *
+ * <p> The specified {@code password} is cloned before it is stored
+ * in the new {@code PasswordProtection} object.
+ *
+ * @param password the password, which may be {@code null}
+ */
+ public PasswordProtection(char[] password) {
+ this.password = (password == null) ? null : password.clone();
+ this.protectionAlgorithm = null;
+ this.protectionParameters = null;
+ }
+
+ /**
+ * Creates a password parameter and specifies the protection algorithm
+ * and associated parameters to use when encrypting a keystore entry.
+ * <p>
+ * The specified {@code password} is cloned before it is stored in the
+ * new {@code PasswordProtection} object.
+ *
+ * @param password the password, which may be {@code null}
+ * @param protectionAlgorithm the encryption algorithm name, for
+ * example, {@code PBEWithHmacSHA256AndAES_256}.
+ * See the Cipher section in the <a href=
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
+ * Java Cryptography Architecture Standard Algorithm Name
+ * Documentation</a>
+ * for information about standard encryption algorithm names.
+ * @param protectionParameters the encryption algorithm parameter
+ * specification, which may be {@code null}
+ * @exception NullPointerException if {@code protectionAlgorithm} is
+ * {@code null}
+ *
+ * @since 1.8
+ */
+ public PasswordProtection(char[] password, String protectionAlgorithm,
+ AlgorithmParameterSpec protectionParameters) {
+ if (protectionAlgorithm == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.password = (password == null) ? null : password.clone();
+ this.protectionAlgorithm = protectionAlgorithm;
+ this.protectionParameters = protectionParameters;
+ }
+
+ /**
+ * Gets the name of the protection algorithm.
+ * If none was set then the keystore provider will use its default
+ * protection algorithm. The name of the default protection algorithm
+ * for a given keystore type is set using the
+ * {@code 'keystore.<type>.keyProtectionAlgorithm'} security property.
+ * For example, the
+ * {@code keystore.PKCS12.keyProtectionAlgorithm} property stores the
+ * name of the default key protection algorithm used for PKCS12
+ * keystores. If the security property is not set, an
+ * implementation-specific algorithm will be used.
+ *
+ * @return the algorithm name, or {@code null} if none was set
+ *
+ * @since 1.8
+ */
+ public String getProtectionAlgorithm() {
+ return protectionAlgorithm;
+ }
+
+ /**
+ * Gets the parameters supplied for the protection algorithm.
+ *
+ * @return the algorithm parameter specification, or {@code null},
+ * if none was set
+ *
+ * @since 1.8
+ */
+ public AlgorithmParameterSpec getProtectionParameters() {
+ return protectionParameters;
+ }
+
+ /**
+ * Gets the password.
+ *
+ * <p>Note that this method returns a reference to the password.
+ * If a clone of the array is created it is the caller's
+ * responsibility to zero out the password information
+ * after it is no longer needed.
+ *
+ * @see #destroy()
+ * @return the password, which may be {@code null}
+ * @exception IllegalStateException if the password has
+ * been cleared (destroyed)
+ */
+ public synchronized char[] getPassword() {
+ if (destroyed) {
+ throw new IllegalStateException("password has been cleared");
+ }
+ return password;
+ }
+
+ /**
+ * Clears the password.
+ *
+ * @exception DestroyFailedException if this method was unable
+ * to clear the password
+ */
+ public synchronized void destroy() throws DestroyFailedException {
+ destroyed = true;
+ if (password != null) {
+ Arrays.fill(password, ' ');
+ }
+ }
+
+ /**
+ * Determines if password has been cleared.
+ *
+ * @return true if the password has been cleared, false otherwise
+ */
+ public synchronized boolean isDestroyed() {
+ return destroyed;
+ }
+ }
+
+ /**
+ * A ProtectionParameter encapsulating a CallbackHandler.
+ *
+ * @since 1.5
+ */
+ public static class CallbackHandlerProtection
+ implements ProtectionParameter {
+
+ private final CallbackHandler handler;
+
+ /**
+ * Constructs a new CallbackHandlerProtection from a
+ * CallbackHandler.
+ *
+ * @param handler the CallbackHandler
+ * @exception NullPointerException if handler is null
+ */
+ public CallbackHandlerProtection(CallbackHandler handler) {
+ if (handler == null) {
+ throw new NullPointerException("handler must not be null");
+ }
+ this.handler = handler;
+ }
+
+ /**
+ * Returns the CallbackHandler.
+ *
+ * @return the CallbackHandler.
+ */
+ public CallbackHandler getCallbackHandler() {
+ return handler;
+ }
+
+ }
+
+ /**
+ * A marker interface for {@code KeyStore} entry types.
+ *
+ * @since 1.5
+ */
+ public static interface Entry {
+
+ /**
+ * Retrieves the attributes associated with an entry.
+ * <p>
+ * The default implementation returns an empty {@code Set}.
+ *
+ * @return an unmodifiable {@code Set} of attributes, possibly empty
+ *
+ * @since 1.8
+ */
+ public default Set<Attribute> getAttributes() {
+ return Collections.<Attribute>emptySet();
+ }
+
+ /**
+ * An attribute associated with a keystore entry.
+ * It comprises a name and one or more values.
+ *
+ * @since 1.8
+ */
+ public interface Attribute {
+ /**
+ * Returns the attribute's name.
+ *
+ * @return the attribute name
+ */
+ public String getName();
+
+ /**
+ * Returns the attribute's value.
+ * Multi-valued attributes encode their values as a single string.
+ *
+ * @return the attribute value
+ */
+ public String getValue();
+ }
+ }
+
+ /**
+ * A {@code KeyStore} entry that holds a {@code PrivateKey}
+ * and corresponding certificate chain.
+ *
+ * @since 1.5
+ */
+ public static final class PrivateKeyEntry implements Entry {
+
+ private final PrivateKey privKey;
+ private final Certificate[] chain;
+ private final Set<Attribute> attributes;
+
+ /**
+ * Constructs a {@code PrivateKeyEntry} with a
+ * {@code PrivateKey} and corresponding certificate chain.
+ *
+ * <p> The specified {@code chain} is cloned before it is stored
+ * in the new {@code PrivateKeyEntry} object.
+ *
+ * @param privateKey the {@code PrivateKey}
+ * @param chain an array of {@code Certificate}s
+ * representing the certificate chain.
+ * The chain must be ordered and contain a
+ * {@code Certificate} at index 0
+ * corresponding to the private key.
+ *
+ * @exception NullPointerException if
+ * {@code privateKey} or {@code chain}
+ * is {@code null}
+ * @exception IllegalArgumentException if the specified chain has a
+ * length of 0, if the specified chain does not contain
+ * {@code Certificate}s of the same type,
+ * or if the {@code PrivateKey} algorithm
+ * does not match the algorithm of the {@code PublicKey}
+ * in the end entity {@code Certificate} (at index 0)
+ */
+ public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
+ this(privateKey, chain, Collections.<Attribute>emptySet());
+ }
+
+ /**
+ * Constructs a {@code PrivateKeyEntry} with a {@code PrivateKey} and
+ * corresponding certificate chain and associated entry attributes.
+ *
+ * <p> The specified {@code chain} and {@code attributes} are cloned
+ * before they are stored in the new {@code PrivateKeyEntry} object.
+ *
+ * @param privateKey the {@code PrivateKey}
+ * @param chain an array of {@code Certificate}s
+ * representing the certificate chain.
+ * The chain must be ordered and contain a
+ * {@code Certificate} at index 0
+ * corresponding to the private key.
+ * @param attributes the attributes
+ *
+ * @exception NullPointerException if {@code privateKey}, {@code chain}
+ * or {@code attributes} is {@code null}
+ * @exception IllegalArgumentException if the specified chain has a
+ * length of 0, if the specified chain does not contain
+ * {@code Certificate}s of the same type,
+ * or if the {@code PrivateKey} algorithm
+ * does not match the algorithm of the {@code PublicKey}
+ * in the end entity {@code Certificate} (at index 0)
+ *
+ * @since 1.8
+ */
+ public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain,
+ Set<Attribute> attributes) {
+
+ if (privateKey == null || chain == null || attributes == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ if (chain.length == 0) {
+ throw new IllegalArgumentException
+ ("invalid zero-length input chain");
+ }
+
+ Certificate[] clonedChain = chain.clone();
+ String certType = clonedChain[0].getType();
+ for (int i = 1; i < clonedChain.length; i++) {
+ if (!certType.equals(clonedChain[i].getType())) {
+ throw new IllegalArgumentException
+ ("chain does not contain certificates " +
+ "of the same type");
+ }
+ }
+ if (!privateKey.getAlgorithm().equals
+ (clonedChain[0].getPublicKey().getAlgorithm())) {
+ throw new IllegalArgumentException
+ ("private key algorithm does not match " +
+ "algorithm of public key in end entity " +
+ "certificate (at index 0)");
+ }
+ this.privKey = privateKey;
+
+ if (clonedChain[0] instanceof X509Certificate &&
+ !(clonedChain instanceof X509Certificate[])) {
+
+ this.chain = new X509Certificate[clonedChain.length];
+ System.arraycopy(clonedChain, 0,
+ this.chain, 0, clonedChain.length);
+ } else {
+ this.chain = clonedChain;
+ }
+
+ this.attributes =
+ Collections.unmodifiableSet(new HashSet<>(attributes));
+ }
+
+ /**
+ * Gets the {@code PrivateKey} from this entry.
+ *
+ * @return the {@code PrivateKey} from this entry
+ */
+ public PrivateKey getPrivateKey() {
+ return privKey;
+ }
+
+ /**
+ * Gets the {@code Certificate} chain from this entry.
+ *
+ * <p> The stored chain is cloned before being returned.
+ *
+ * @return an array of {@code Certificate}s corresponding
+ * to the certificate chain for the public key.
+ * If the certificates are of type X.509,
+ * the runtime type of the returned array is
+ * {@code X509Certificate[]}.
+ */
+ public Certificate[] getCertificateChain() {
+ return chain.clone();
+ }
+
+ /**
+ * Gets the end entity {@code Certificate}
+ * from the certificate chain in this entry.
+ *
+ * @return the end entity {@code Certificate} (at index 0)
+ * from the certificate chain in this entry.
+ * If the certificate is of type X.509,
+ * the runtime type of the returned certificate is
+ * {@code X509Certificate}.
+ */
+ public Certificate getCertificate() {
+ return chain[0];
+ }
+
+ /**
+ * Retrieves the attributes associated with an entry.
+ * <p>
+ *
+ * @return an unmodifiable {@code Set} of attributes, possibly empty
+ *
+ * @since 1.8
+ */
+ @Override
+ public Set<Attribute> getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Returns a string representation of this PrivateKeyEntry.
+ * @return a string representation of this PrivateKeyEntry.
+ */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Private key entry and certificate chain with "
+ + chain.length + " elements:\r\n");
+ for (Certificate cert : chain) {
+ sb.append(cert);
+ sb.append("\r\n");
+ }
+ return sb.toString();
+ }
+
+ }
+
+ /**
+ * A {@code KeyStore} entry that holds a {@code SecretKey}.
+ *
+ * @since 1.5
+ */
+ public static final class SecretKeyEntry implements Entry {
+
+ private final SecretKey sKey;
+ private final Set<Attribute> attributes;
+
+ /**
+ * Constructs a {@code SecretKeyEntry} with a
+ * {@code SecretKey}.
+ *
+ * @param secretKey the {@code SecretKey}
+ *
+ * @exception NullPointerException if {@code secretKey}
+ * is {@code null}
+ */
+ public SecretKeyEntry(SecretKey secretKey) {
+ if (secretKey == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.sKey = secretKey;
+ this.attributes = Collections.<Attribute>emptySet();
+ }
+
+ /**
+ * Constructs a {@code SecretKeyEntry} with a {@code SecretKey} and
+ * associated entry attributes.
+ *
+ * <p> The specified {@code attributes} is cloned before it is stored
+ * in the new {@code SecretKeyEntry} object.
+ *
+ * @param secretKey the {@code SecretKey}
+ * @param attributes the attributes
+ *
+ * @exception NullPointerException if {@code secretKey} or
+ * {@code attributes} is {@code null}
+ *
+ * @since 1.8
+ */
+ public SecretKeyEntry(SecretKey secretKey, Set<Attribute> attributes) {
+
+ if (secretKey == null || attributes == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.sKey = secretKey;
+ this.attributes =
+ Collections.unmodifiableSet(new HashSet<>(attributes));
+ }
+
+ /**
+ * Gets the {@code SecretKey} from this entry.
+ *
+ * @return the {@code SecretKey} from this entry
+ */
+ public SecretKey getSecretKey() {
+ return sKey;
+ }
+
+ /**
+ * Retrieves the attributes associated with an entry.
+ * <p>
+ *
+ * @return an unmodifiable {@code Set} of attributes, possibly empty
+ *
+ * @since 1.8
+ */
+ @Override
+ public Set<Attribute> getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Returns a string representation of this SecretKeyEntry.
+ * @return a string representation of this SecretKeyEntry.
+ */
+ public String toString() {
+ return "Secret key entry with algorithm " + sKey.getAlgorithm();
+ }
+ }
+
+ /**
+ * A {@code KeyStore} entry that holds a trusted
+ * {@code Certificate}.
+ *
+ * @since 1.5
+ */
+ public static final class TrustedCertificateEntry implements Entry {
+
+ private final Certificate cert;
+ private final Set<Attribute> attributes;
+
+ /**
+ * Constructs a {@code TrustedCertificateEntry} with a
+ * trusted {@code Certificate}.
+ *
+ * @param trustedCert the trusted {@code Certificate}
+ *
+ * @exception NullPointerException if
+ * {@code trustedCert} is {@code null}
+ */
+ public TrustedCertificateEntry(Certificate trustedCert) {
+ if (trustedCert == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.cert = trustedCert;
+ this.attributes = Collections.<Attribute>emptySet();
+ }
+
+ /**
+ * Constructs a {@code TrustedCertificateEntry} with a
+ * trusted {@code Certificate} and associated entry attributes.
+ *
+ * <p> The specified {@code attributes} is cloned before it is stored
+ * in the new {@code TrustedCertificateEntry} object.
+ *
+ * @param trustedCert the trusted {@code Certificate}
+ * @param attributes the attributes
+ *
+ * @exception NullPointerException if {@code trustedCert} or
+ * {@code attributes} is {@code null}
+ *
+ * @since 1.8
+ */
+ public TrustedCertificateEntry(Certificate trustedCert,
+ Set<Attribute> attributes) {
+ if (trustedCert == null || attributes == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ this.cert = trustedCert;
+ this.attributes =
+ Collections.unmodifiableSet(new HashSet<>(attributes));
+ }
+
+ /**
+ * Gets the trusted {@code Certficate} from this entry.
+ *
+ * @return the trusted {@code Certificate} from this entry
+ */
+ public Certificate getTrustedCertificate() {
+ return cert;
+ }
+
+ /**
+ * Retrieves the attributes associated with an entry.
+ * <p>
+ *
+ * @return an unmodifiable {@code Set} of attributes, possibly empty
+ *
+ * @since 1.8
+ */
+ @Override
+ public Set<Attribute> getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Returns a string representation of this TrustedCertificateEntry.
+ * @return a string representation of this TrustedCertificateEntry.
+ */
+ public String toString() {
+ return "Trusted certificate entry:\r\n" + cert.toString();
+ }
+ }
+
+ /**
+ * Creates a KeyStore object of the given type, and encapsulates the given
+ * provider implementation (SPI object) in it.
+ *
+ * @param keyStoreSpi the provider implementation.
+ * @param provider the provider.
+ * @param type the keystore type.
+ */
+ protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
+ {
+ this.keyStoreSpi = keyStoreSpi;
+ this.provider = provider;
+ this.type = type;
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("KeyStore." + type.toUpperCase() + " type from: " +
+ this.provider.getName());
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ }
+
+ /**
+ * Returns a keystore object of the specified type.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new KeyStore object encapsulating the
+ * KeyStoreSpi implementation from the first
+ * Provider that supports the specified type is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param type the type of keystore.
+ * See the KeyStore section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyStore">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard keystore types.
+ *
+ * @return a keystore object of the specified type.
+ *
+ * @exception KeyStoreException if no Provider supports a
+ * KeyStoreSpi implementation for the
+ * specified type.
+ *
+ * @see Provider
+ */
+ public static KeyStore getInstance(String type)
+ throws KeyStoreException
+ {
+ try {
+ Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
+ return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new KeyStoreException(type + " not found", nsae);
+ } catch (NoSuchProviderException nspe) {
+ throw new KeyStoreException(type + " not found", nspe);
+ }
+ }
+
+ /**
+ * Returns a keystore object of the specified type.
+ *
+ * <p> A new KeyStore object encapsulating the
+ * KeyStoreSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param type the type of keystore.
+ * See the KeyStore section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyStore">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard keystore types.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a keystore object of the specified type.
+ *
+ * @exception KeyStoreException if a KeyStoreSpi
+ * implementation for the specified type 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static KeyStore getInstance(String type, String provider)
+ throws KeyStoreException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("missing provider");
+ try {
+ Object[] objs = Security.getImpl(type, "KeyStore", provider);
+ return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new KeyStoreException(type + " not found", nsae);
+ }
+ }
+
+ /**
+ * Returns a keystore object of the specified type.
+ *
+ * <p> A new KeyStore object encapsulating the
+ * KeyStoreSpi 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 type the type of keystore.
+ * See the KeyStore section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#KeyStore">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard keystore types.
+ *
+ * @param provider the provider.
+ *
+ * @return a keystore object of the specified type.
+ *
+ * @exception KeyStoreException if KeyStoreSpi
+ * implementation for the specified type is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the specified provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static KeyStore getInstance(String type, Provider provider)
+ throws KeyStoreException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("missing provider");
+ try {
+ Object[] objs = Security.getImpl(type, "KeyStore", provider);
+ return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new KeyStoreException(type + " not found", nsae);
+ }
+ }
+
+ /**
+ * Returns the default keystore type as specified by the
+ * {@code keystore.type} security property, or the string
+ * {@literal "jks"} (acronym for {@literal "Java keystore"})
+ * if no such property exists.
+ *
+ * <p>The default keystore type can be used by applications that do not
+ * want to use a hard-coded keystore type when calling one of the
+ * {@code getInstance} methods, and want to provide a default keystore
+ * type in case a user does not specify its own.
+ *
+ * <p>The default keystore type can be changed by setting the value of the
+ * {@code keystore.type} security property to the desired keystore type.
+ *
+ * @return the default keystore type as specified by the
+ * {@code keystore.type} security property, or the string {@literal "jks"}
+ * if no such property exists.
+ * @see java.security.Security security properties
+ */
+ public final static String getDefaultType() {
+ String kstype;
+ kstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(KEYSTORE_TYPE);
+ }
+ });
+ if (kstype == null) {
+ kstype = "jks";
+ }
+ return kstype;
+ }
+
+ /**
+ * Returns the provider of this keystore.
+ *
+ * @return the provider of this keystore.
+ */
+ public final Provider getProvider()
+ {
+ return this.provider;
+ }
+
+ /**
+ * Returns the type of this keystore.
+ *
+ * @return the type of this keystore.
+ */
+ public final String getType()
+ {
+ return this.type;
+ }
+
+ /**
+ * Returns the key associated with the given alias, using the given
+ * password to recover it. The key must have been associated with
+ * the alias by a call to {@code setKeyEntry},
+ * or by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry} or {@code SecretKeyEntry}.
+ *
+ * @param alias the alias name
+ * @param password the password for recovering the key
+ *
+ * @return the requested key, or null if the given alias does not exist
+ * or does not identify a key-related entry.
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ * @exception NoSuchAlgorithmException if the algorithm for recovering the
+ * key cannot be found
+ * @exception UnrecoverableKeyException if the key cannot be recovered
+ * (e.g., the given password is wrong).
+ */
+ public final Key getKey(String alias, char[] password)
+ throws KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableKeyException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineGetKey(alias, password);
+ }
+
+ /**
+ * Returns the certificate chain associated with the given alias.
+ * The certificate chain must have been associated with the alias
+ * by a call to {@code setKeyEntry},
+ * or by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry}.
+ *
+ * @param alias the alias name
+ *
+ * @return the certificate chain (ordered with the user's certificate first
+ * followed by zero or more certificate authorities), or null if the given alias
+ * does not exist or does not contain a certificate chain
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final Certificate[] getCertificateChain(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineGetCertificateChain(alias);
+ }
+
+ /**
+ * Returns the certificate associated with the given alias.
+ *
+ * <p> If the given alias name identifies an entry
+ * created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry},
+ * then the trusted certificate contained in that entry is returned.
+ *
+ * <p> If the given alias name identifies an entry
+ * created by a call to {@code setKeyEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry},
+ * then the first element of the certificate chain in that entry
+ * is returned.
+ *
+ * @param alias the alias name
+ *
+ * @return the certificate, or null if the given alias does not exist or
+ * does not contain a certificate.
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final Certificate getCertificate(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineGetCertificate(alias);
+ }
+
+ /**
+ * Returns the creation date of the entry identified by the given alias.
+ *
+ * @param alias the alias name
+ *
+ * @return the creation date of this entry, or null if the given alias does
+ * not exist
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final Date getCreationDate(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineGetCreationDate(alias);
+ }
+
+ /**
+ * Assigns the given key to the given alias, protecting it with the given
+ * password.
+ *
+ * <p>If the given key is of type {@code java.security.PrivateKey},
+ * it must be accompanied by a certificate chain certifying the
+ * corresponding public key.
+ *
+ * <p>If the given alias already exists, the keystore information
+ * associated with it is overridden by the given key (and possibly
+ * certificate chain).
+ *
+ * @param alias the alias name
+ * @param key the key to be associated with the alias
+ * @param password the password to protect the key
+ * @param chain the certificate chain for the corresponding public
+ * key (only required if the given key is of type
+ * {@code java.security.PrivateKey}).
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded), the given key cannot be protected, or this operation fails
+ * for some other reason
+ */
+ public final void setKeyEntry(String alias, Key key, char[] password,
+ Certificate[] chain)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ if ((key instanceof PrivateKey) &&
+ (chain == null || chain.length == 0)) {
+ throw new IllegalArgumentException("Private key must be "
+ + "accompanied by certificate "
+ + "chain");
+ }
+ keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
+ }
+
+ /**
+ * Assigns the given key (that has already been protected) to the given
+ * alias.
+ *
+ * <p>If the protected key is of type
+ * {@code java.security.PrivateKey}, it must be accompanied by a
+ * certificate chain certifying the corresponding public key. If the
+ * underlying keystore implementation is of type {@code jks},
+ * {@code key} must be encoded as an
+ * {@code EncryptedPrivateKeyInfo} as defined in the PKCS #8 standard.
+ *
+ * <p>If the given alias already exists, the keystore information
+ * associated with it is overridden by the given key (and possibly
+ * certificate chain).
+ *
+ * @param alias the alias name
+ * @param key the key (in protected format) to be associated with the alias
+ * @param chain the certificate chain for the corresponding public
+ * key (only useful if the protected key is of type
+ * {@code java.security.PrivateKey}).
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded), or if this operation fails for some other reason.
+ */
+ public final void setKeyEntry(String alias, byte[] key,
+ Certificate[] chain)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ keyStoreSpi.engineSetKeyEntry(alias, key, chain);
+ }
+
+ /**
+ * Assigns the given trusted certificate to the given alias.
+ *
+ * <p> If the given alias identifies an existing entry
+ * created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry},
+ * the trusted certificate in the existing entry
+ * is overridden by the given certificate.
+ *
+ * @param alias the alias name
+ * @param cert the certificate
+ *
+ * @exception KeyStoreException if the keystore has not been initialized,
+ * or the given alias already exists and does not identify an
+ * entry containing a trusted certificate,
+ * or this operation fails for some other reason.
+ */
+ public final void setCertificateEntry(String alias, Certificate cert)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ keyStoreSpi.engineSetCertificateEntry(alias, cert);
+ }
+
+ /**
+ * Deletes the entry identified by the given alias from this keystore.
+ *
+ * @param alias the alias name
+ *
+ * @exception KeyStoreException if the keystore has not been initialized,
+ * or if the entry cannot be removed.
+ */
+ public final void deleteEntry(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ keyStoreSpi.engineDeleteEntry(alias);
+ }
+
+ /**
+ * Lists all the alias names of this keystore.
+ *
+ * @return enumeration of the alias names
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final Enumeration<String> aliases()
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineAliases();
+ }
+
+ /**
+ * Checks if the given alias exists in this keystore.
+ *
+ * @param alias the alias name
+ *
+ * @return true if the alias exists, false otherwise
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final boolean containsAlias(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineContainsAlias(alias);
+ }
+
+ /**
+ * Retrieves the number of entries in this keystore.
+ *
+ * @return the number of entries in this keystore
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final int size()
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineSize();
+ }
+
+ /**
+ * Returns true if the entry identified by the given alias
+ * was created by a call to {@code setKeyEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.
+ *
+ * @param alias the alias for the keystore entry to be checked
+ *
+ * @return true if the entry identified by the given alias is a
+ * key-related entry, false otherwise.
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final boolean isKeyEntry(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineIsKeyEntry(alias);
+ }
+
+ /**
+ * Returns true if the entry identified by the given alias
+ * was created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry}.
+ *
+ * @param alias the alias for the keystore entry to be checked
+ *
+ * @return true if the entry identified by the given alias contains a
+ * trusted certificate, false otherwise.
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final boolean isCertificateEntry(String alias)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineIsCertificateEntry(alias);
+ }
+
+ /**
+ * Returns the (alias) name of the first keystore entry whose certificate
+ * matches the given certificate.
+ *
+ * <p> This method attempts to match the given certificate with each
+ * keystore entry. If the entry being considered was
+ * created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry},
+ * then the given certificate is compared to that entry's certificate.
+ *
+ * <p> If the entry being considered was
+ * created by a call to {@code setKeyEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry},
+ * then the given certificate is compared to the first
+ * element of that entry's certificate chain.
+ *
+ * @param cert the certificate to match with.
+ *
+ * @return the alias name of the first entry with a matching certificate,
+ * or null if no such entry exists in this keystore.
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ */
+ public final String getCertificateAlias(Certificate cert)
+ throws KeyStoreException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineGetCertificateAlias(cert);
+ }
+
+ /**
+ * Stores this keystore to the given output stream, and protects its
+ * integrity with the given password.
+ *
+ * @param stream the output stream to which this keystore is written.
+ * @param password the password to generate the keystore integrity check
+ *
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ * @exception IOException if there was an I/O problem with data
+ * @exception NoSuchAlgorithmException if the appropriate data integrity
+ * algorithm could not be found
+ * @exception CertificateException if any of the certificates included in
+ * the keystore data could not be stored
+ */
+ public final void store(OutputStream stream, char[] password)
+ throws KeyStoreException, IOException, NoSuchAlgorithmException,
+ CertificateException
+ {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ keyStoreSpi.engineStore(stream, password);
+ }
+
+ /**
+ * Stores this keystore using the given {@code LoadStoreParameter}.
+ *
+ * @param param the {@code LoadStoreParameter}
+ * that specifies how to store the keystore,
+ * which may be {@code null}
+ *
+ * @exception IllegalArgumentException if the given
+ * {@code LoadStoreParameter}
+ * input is not recognized
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded)
+ * @exception IOException if there was an I/O problem with data
+ * @exception NoSuchAlgorithmException if the appropriate data integrity
+ * algorithm could not be found
+ * @exception CertificateException if any of the certificates included in
+ * the keystore data could not be stored
+ *
+ * @since 1.5
+ */
+ public final void store(LoadStoreParameter param)
+ throws KeyStoreException, IOException,
+ NoSuchAlgorithmException, CertificateException {
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ keyStoreSpi.engineStore(param);
+ }
+
+ /**
+ * Loads this KeyStore from the given input stream.
+ *
+ * <p>A password may be given to unlock the keystore
+ * (e.g. the keystore resides on a hardware token device),
+ * or to check the integrity of the keystore data.
+ * If a password is not given for integrity checking,
+ * then integrity checking is not performed.
+ *
+ * <p>In order to create an empty keystore, or if the keystore cannot
+ * be initialized from a stream, pass {@code null}
+ * as the {@code stream} argument.
+ *
+ * <p> Note that if this keystore has already been loaded, it is
+ * reinitialized and loaded again from the given input stream.
+ *
+ * @param stream the input stream from which the keystore is loaded,
+ * or {@code null}
+ * @param password the password used to check the integrity of
+ * the keystore, the password used to unlock the keystore,
+ * or {@code null}
+ *
+ * @exception IOException if there is an I/O or format problem with the
+ * keystore data, if a password is required but not given,
+ * or if the given password was incorrect. If the error is due to a
+ * wrong password, the {@link Throwable#getCause cause} of the
+ * {@code IOException} should be an
+ * {@code UnrecoverableKeyException}
+ * @exception NoSuchAlgorithmException if the algorithm used to check
+ * the integrity of the keystore cannot be found
+ * @exception CertificateException if any of the certificates in the
+ * keystore could not be loaded
+ */
+ public final void load(InputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException
+ {
+ keyStoreSpi.engineLoad(stream, password);
+ initialized = true;
+ }
+
+ /**
+ * Loads this keystore using the given {@code LoadStoreParameter}.
+ *
+ * <p> Note that if this KeyStore has already been loaded, it is
+ * reinitialized and loaded again from the given parameter.
+ *
+ * @param param the {@code LoadStoreParameter}
+ * that specifies how to load the keystore,
+ * which may be {@code null}
+ *
+ * @exception IllegalArgumentException if the given
+ * {@code LoadStoreParameter}
+ * input is not recognized
+ * @exception IOException if there is an I/O or format problem with the
+ * keystore data. If the error is due to an incorrect
+ * {@code ProtectionParameter} (e.g. wrong password)
+ * the {@link Throwable#getCause cause} of the
+ * {@code IOException} should be an
+ * {@code UnrecoverableKeyException}
+ * @exception NoSuchAlgorithmException if the algorithm used to check
+ * the integrity of the keystore cannot be found
+ * @exception CertificateException if any of the certificates in the
+ * keystore could not be loaded
+ *
+ * @since 1.5
+ */
+ public final void load(LoadStoreParameter param)
+ throws IOException, NoSuchAlgorithmException,
+ CertificateException {
+
+ keyStoreSpi.engineLoad(param);
+ initialized = true;
+ }
+
+ /**
+ * Gets a keystore {@code Entry} for the specified alias
+ * with the specified protection parameter.
+ *
+ * @param alias get the keystore {@code Entry} for this alias
+ * @param protParam the {@code ProtectionParameter}
+ * used to protect the {@code Entry},
+ * which may be {@code null}
+ *
+ * @return the keystore {@code Entry} for the specified alias,
+ * or {@code null} if there is no such entry
+ *
+ * @exception NullPointerException if
+ * {@code alias} is {@code null}
+ * @exception NoSuchAlgorithmException if the algorithm for recovering the
+ * entry cannot be found
+ * @exception UnrecoverableEntryException if the specified
+ * {@code protParam} were insufficient or invalid
+ * @exception UnrecoverableKeyException if the entry is a
+ * {@code PrivateKeyEntry} or {@code SecretKeyEntry}
+ * and the specified {@code protParam} does not contain
+ * the information needed to recover the key (e.g. wrong password)
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded).
+ * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
+ *
+ * @since 1.5
+ */
+ public final Entry getEntry(String alias, ProtectionParameter protParam)
+ throws NoSuchAlgorithmException, UnrecoverableEntryException,
+ KeyStoreException {
+
+ if (alias == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineGetEntry(alias, protParam);
+ }
+
+ /**
+ * Saves a keystore {@code Entry} under the specified alias.
+ * The protection parameter is used to protect the
+ * {@code Entry}.
+ *
+ * <p> If an entry already exists for the specified alias,
+ * it is overridden.
+ *
+ * @param alias save the keystore {@code Entry} under this alias
+ * @param entry the {@code Entry} to save
+ * @param protParam the {@code ProtectionParameter}
+ * used to protect the {@code Entry},
+ * which may be {@code null}
+ *
+ * @exception NullPointerException if
+ * {@code alias} or {@code entry}
+ * is {@code null}
+ * @exception KeyStoreException if the keystore has not been initialized
+ * (loaded), or if this operation fails for some other reason
+ *
+ * @see #getEntry(String, KeyStore.ProtectionParameter)
+ *
+ * @since 1.5
+ */
+ public final void setEntry(String alias, Entry entry,
+ ProtectionParameter protParam)
+ throws KeyStoreException {
+ if (alias == null || entry == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ keyStoreSpi.engineSetEntry(alias, entry, protParam);
+ }
+
+ /**
+ * Determines if the keystore {@code Entry} for the specified
+ * {@code alias} is an instance or subclass of the specified
+ * {@code entryClass}.
+ *
+ * @param alias the alias name
+ * @param entryClass the entry class
+ *
+ * @return true if the keystore {@code Entry} for the specified
+ * {@code alias} is an instance or subclass of the
+ * specified {@code entryClass}, false otherwise
+ *
+ * @exception NullPointerException if
+ * {@code alias} or {@code entryClass}
+ * is {@code null}
+ * @exception KeyStoreException if the keystore has not been
+ * initialized (loaded)
+ *
+ * @since 1.5
+ */
+ public final boolean
+ entryInstanceOf(String alias,
+ Class<? extends KeyStore.Entry> entryClass)
+ throws KeyStoreException
+ {
+
+ if (alias == null || entryClass == null) {
+ throw new NullPointerException("invalid null input");
+ }
+ if (!initialized) {
+ throw new KeyStoreException("Uninitialized keystore");
+ }
+ return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
+ }
+
+ /**
+ * A description of a to-be-instantiated KeyStore object.
+ *
+ * <p>An instance of this class encapsulates the information needed to
+ * instantiate and initialize a KeyStore object. That process is
+ * triggered when the {@linkplain #getKeyStore} method is called.
+ *
+ * <p>This makes it possible to decouple configuration from KeyStore
+ * object creation and e.g. delay a password prompt until it is
+ * needed.
+ *
+ * @see KeyStore
+ * @see javax.net.ssl.KeyStoreBuilderParameters
+ * @since 1.5
+ */
+ public static abstract class Builder {
+
+ // maximum times to try the callbackhandler if the password is wrong
+ static final int MAX_CALLBACK_TRIES = 3;
+
+ /**
+ * Construct a new Builder.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ /**
+ * Returns the KeyStore described by this object.
+ *
+ * @return the {@code KeyStore} described by this object
+ * @exception KeyStoreException if an error occurred during the
+ * operation, for example if the KeyStore could not be
+ * instantiated or loaded
+ */
+ public abstract KeyStore getKeyStore() throws KeyStoreException;
+
+ /**
+ * Returns the ProtectionParameters that should be used to obtain
+ * the {@link KeyStore.Entry Entry} with the given alias.
+ * The {@code getKeyStore} method must be invoked before this
+ * method may be called.
+ *
+ * @return the ProtectionParameters that should be used to obtain
+ * the {@link KeyStore.Entry Entry} with the given alias.
+ * @param alias the alias of the KeyStore entry
+ * @throws NullPointerException if alias is null
+ * @throws KeyStoreException if an error occurred during the
+ * operation
+ * @throws IllegalStateException if the getKeyStore method has
+ * not been invoked prior to calling this method
+ */
+ public abstract ProtectionParameter getProtectionParameter(String alias)
+ throws KeyStoreException;
+
+ /**
+ * Returns a new Builder that encapsulates the given KeyStore.
+ * The {@linkplain #getKeyStore} method of the returned object
+ * will return {@code keyStore}, the {@linkplain
+ * #getProtectionParameter getProtectionParameter()} method will
+ * return {@code protectionParameters}.
+ *
+ * <p> This is useful if an existing KeyStore object needs to be
+ * used with Builder-based APIs.
+ *
+ * @return a new Builder object
+ * @param keyStore the KeyStore to be encapsulated
+ * @param protectionParameter the ProtectionParameter used to
+ * protect the KeyStore entries
+ * @throws NullPointerException if keyStore or
+ * protectionParameters is null
+ * @throws IllegalArgumentException if the keyStore has not been
+ * initialized
+ */
+ public static Builder newInstance(final KeyStore keyStore,
+ final ProtectionParameter protectionParameter) {
+ if ((keyStore == null) || (protectionParameter == null)) {
+ throw new NullPointerException();
+ }
+ if (keyStore.initialized == false) {
+ throw new IllegalArgumentException("KeyStore not initialized");
+ }
+ return new Builder() {
+ private volatile boolean getCalled;
+
+ public KeyStore getKeyStore() {
+ getCalled = true;
+ return keyStore;
+ }
+
+ public ProtectionParameter getProtectionParameter(String alias)
+ {
+ if (alias == null) {
+ throw new NullPointerException();
+ }
+ if (getCalled == false) {
+ throw new IllegalStateException
+ ("getKeyStore() must be called first");
+ }
+ return protectionParameter;
+ }
+ };
+ }
+
+ /**
+ * Returns a new Builder object.
+ *
+ * <p>The first call to the {@link #getKeyStore} method on the returned
+ * builder will create a KeyStore of type {@code type} and call
+ * its {@link KeyStore#load load()} method.
+ * The {@code inputStream} argument is constructed from
+ * {@code file}.
+ * If {@code protection} is a
+ * {@code PasswordProtection}, the password is obtained by
+ * calling the {@code getPassword} method.
+ * Otherwise, if {@code protection} is a
+ * {@code CallbackHandlerProtection}, the password is obtained
+ * by invoking the CallbackHandler.
+ *
+ * <p>Subsequent calls to {@link #getKeyStore} return the same object
+ * as the initial call. If the initial call to failed with a
+ * KeyStoreException, subsequent calls also throw a
+ * KeyStoreException.
+ *
+ * <p>The KeyStore is instantiated from {@code provider} if
+ * non-null. Otherwise, all installed providers are searched.
+ *
+ * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
+ * will return a {@link KeyStore.PasswordProtection PasswordProtection}
+ * object encapsulating the password that was used to invoke the
+ * {@code load} method.
+ *
+ * <p><em>Note</em> that the {@link #getKeyStore} method is executed
+ * within the {@link AccessControlContext} of the code invoking this
+ * method.
+ *
+ * @return a new Builder object
+ * @param type the type of KeyStore to be constructed
+ * @param provider the provider from which the KeyStore is to
+ * be instantiated (or null)
+ * @param file the File that contains the KeyStore data
+ * @param protection the ProtectionParameter securing the KeyStore data
+ * @throws NullPointerException if type, file or protection is null
+ * @throws IllegalArgumentException if protection is not an instance
+ * of either PasswordProtection or CallbackHandlerProtection; or
+ * if file does not exist or does not refer to a normal file
+ */
+ public static Builder newInstance(String type, Provider provider,
+ File file, ProtectionParameter protection) {
+ if ((type == null) || (file == null) || (protection == null)) {
+ throw new NullPointerException();
+ }
+ if ((protection instanceof PasswordProtection == false) &&
+ (protection instanceof CallbackHandlerProtection == false)) {
+ throw new IllegalArgumentException
+ ("Protection must be PasswordProtection or " +
+ "CallbackHandlerProtection");
+ }
+ if (file.isFile() == false) {
+ throw new IllegalArgumentException
+ ("File does not exist or it does not refer " +
+ "to a normal file: " + file);
+ }
+ return new FileBuilder(type, provider, file, protection,
+ AccessController.getContext());
+ }
+
+ private static final class FileBuilder extends Builder {
+
+ private final String type;
+ private final Provider provider;
+ private final File file;
+ private ProtectionParameter protection;
+ private ProtectionParameter keyProtection;
+ private final AccessControlContext context;
+
+ private KeyStore keyStore;
+
+ private Throwable oldException;
+
+ FileBuilder(String type, Provider provider, File file,
+ ProtectionParameter protection,
+ AccessControlContext context) {
+ this.type = type;
+ this.provider = provider;
+ this.file = file;
+ this.protection = protection;
+ this.context = context;
+ }
+
+ public synchronized KeyStore getKeyStore() throws KeyStoreException
+ {
+ if (keyStore != null) {
+ return keyStore;
+ }
+ if (oldException != null) {
+ throw new KeyStoreException
+ ("Previous KeyStore instantiation failed",
+ oldException);
+ }
+ PrivilegedExceptionAction<KeyStore> action =
+ new PrivilegedExceptionAction<KeyStore>() {
+ public KeyStore run() throws Exception {
+ if (protection instanceof CallbackHandlerProtection == false) {
+ return run0();
+ }
+ // when using a CallbackHandler,
+ // reprompt if the password is wrong
+ int tries = 0;
+ while (true) {
+ tries++;
+ try {
+ return run0();
+ } catch (IOException e) {
+ if ((tries < MAX_CALLBACK_TRIES)
+ && (e.getCause() instanceof UnrecoverableKeyException)) {
+ continue;
+ }
+ throw e;
+ }
+ }
+ }
+ public KeyStore run0() throws Exception {
+ KeyStore ks;
+ if (provider == null) {
+ ks = KeyStore.getInstance(type);
+ } else {
+ ks = KeyStore.getInstance(type, provider);
+ }
+ InputStream in = null;
+ char[] password = null;
+ try {
+ in = new FileInputStream(file);
+ if (protection instanceof PasswordProtection) {
+ password =
+ ((PasswordProtection)protection).getPassword();
+ keyProtection = protection;
+ } else {
+ CallbackHandler handler =
+ ((CallbackHandlerProtection)protection)
+ .getCallbackHandler();
+ PasswordCallback callback = new PasswordCallback
+ ("Password for keystore " + file.getName(),
+ false);
+ handler.handle(new Callback[] {callback});
+ password = callback.getPassword();
+ if (password == null) {
+ throw new KeyStoreException("No password" +
+ " provided");
+ }
+ callback.clearPassword();
+ keyProtection = new PasswordProtection(password);
+ }
+ ks.load(in, password);
+ return ks;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+ }
+ };
+ try {
+ keyStore = AccessController.doPrivileged(action, context);
+ return keyStore;
+ } catch (PrivilegedActionException e) {
+ oldException = e.getCause();
+ throw new KeyStoreException
+ ("KeyStore instantiation failed", oldException);
+ }
+ }
+
+ public synchronized ProtectionParameter
+ getProtectionParameter(String alias) {
+ if (alias == null) {
+ throw new NullPointerException();
+ }
+ if (keyStore == null) {
+ throw new IllegalStateException
+ ("getKeyStore() must be called first");
+ }
+ return keyProtection;
+ }
+ }
+
+ /**
+ * Returns a new Builder object.
+ *
+ * <p>Each call to the {@link #getKeyStore} method on the returned
+ * builder will return a new KeyStore object of type {@code type}.
+ * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
+ * method is invoked using a
+ * {@code LoadStoreParameter} that encapsulates
+ * {@code protection}.
+ *
+ * <p>The KeyStore is instantiated from {@code provider} if
+ * non-null. Otherwise, all installed providers are searched.
+ *
+ * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
+ * will return {@code protection}.
+ *
+ * <p><em>Note</em> that the {@link #getKeyStore} method is executed
+ * within the {@link AccessControlContext} of the code invoking this
+ * method.
+ *
+ * @return a new Builder object
+ * @param type the type of KeyStore to be constructed
+ * @param provider the provider from which the KeyStore is to
+ * be instantiated (or null)
+ * @param protection the ProtectionParameter securing the Keystore
+ * @throws NullPointerException if type or protection is null
+ */
+ public static Builder newInstance(final String type,
+ final Provider provider, final ProtectionParameter protection) {
+ if ((type == null) || (protection == null)) {
+ throw new NullPointerException();
+ }
+ final AccessControlContext context = AccessController.getContext();
+ return new Builder() {
+ private volatile boolean getCalled;
+ private IOException oldException;
+
+ private final PrivilegedExceptionAction<KeyStore> action
+ = new PrivilegedExceptionAction<KeyStore>() {
+
+ public KeyStore run() throws Exception {
+ KeyStore ks;
+ if (provider == null) {
+ ks = KeyStore.getInstance(type);
+ } else {
+ ks = KeyStore.getInstance(type, provider);
+ }
+ LoadStoreParameter param = new SimpleLoadStoreParameter(protection);
+ if (protection instanceof CallbackHandlerProtection == false) {
+ ks.load(param);
+ } else {
+ // when using a CallbackHandler,
+ // reprompt if the password is wrong
+ int tries = 0;
+ while (true) {
+ tries++;
+ try {
+ ks.load(param);
+ break;
+ } catch (IOException e) {
+ if (e.getCause() instanceof UnrecoverableKeyException) {
+ if (tries < MAX_CALLBACK_TRIES) {
+ continue;
+ } else {
+ oldException = e;
+ }
+ }
+ throw e;
+ }
+ }
+ }
+ getCalled = true;
+ return ks;
+ }
+ };
+
+ public synchronized KeyStore getKeyStore()
+ throws KeyStoreException {
+ if (oldException != null) {
+ throw new KeyStoreException
+ ("Previous KeyStore instantiation failed",
+ oldException);
+ }
+ try {
+ return AccessController.doPrivileged(action, context);
+ } catch (PrivilegedActionException e) {
+ Throwable cause = e.getCause();
+ throw new KeyStoreException
+ ("KeyStore instantiation failed", cause);
+ }
+ }
+
+ public ProtectionParameter getProtectionParameter(String alias)
+ {
+ if (alias == null) {
+ throw new NullPointerException();
+ }
+ if (getCalled == false) {
+ throw new IllegalStateException
+ ("getKeyStore() must be called first");
+ }
+ return protection;
+ }
+ };
+ }
+
+ }
+
+ static class SimpleLoadStoreParameter implements LoadStoreParameter {
+
+ private final ProtectionParameter protection;
+
+ SimpleLoadStoreParameter(ProtectionParameter protection) {
+ this.protection = protection;
+ }
+
+ public ProtectionParameter getProtectionParameter() {
+ return protection;
+ }
+ }
+
+}
diff --git a/java/security/KeyStoreException.java b/java/security/KeyStoreException.java
new file mode 100644
index 0000000..cf56d6a
--- /dev/null
+++ b/java/security/KeyStoreException.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This is the generic KeyStore exception.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @since 1.2
+ */
+
+public class KeyStoreException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -1119353179322377262L;
+
+ /**
+ * Constructs a KeyStoreException with no detail message. (A
+ * detail message is a String that describes this particular
+ * exception.)
+ */
+ public KeyStoreException() {
+ super();
+ }
+
+ /**
+ * Constructs a KeyStoreException with the specified detail
+ * message. (A detail message is a String that describes this
+ * particular exception.)
+ *
+ * @param msg the detail message.
+ */
+ public KeyStoreException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code KeyStoreException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public KeyStoreException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code KeyStoreException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public KeyStoreException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/KeyStoreSpi.java b/java/security/KeyStoreSpi.java
new file mode 100644
index 0000000..531a983
--- /dev/null
+++ b/java/security/KeyStoreSpi.java
@@ -0,0 +1,587 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.util.*;
+import java.security.KeyStore;
+import java.security.KeyStore.*;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+
+import javax.crypto.SecretKey;
+
+import javax.security.auth.callback.*;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code KeyStore} class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a keystore for a particular keystore type.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see KeyStore
+ *
+ * @since 1.2
+ */
+
+public abstract class KeyStoreSpi {
+
+ /**
+ * Returns the key associated with the given alias, using the given
+ * password to recover it. The key must have been associated with
+ * the alias by a call to {@code setKeyEntry},
+ * or by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry} or {@code SecretKeyEntry}.
+ *
+ * @param alias the alias name
+ * @param password the password for recovering the key
+ *
+ * @return the requested key, or null if the given alias does not exist
+ * or does not identify a key-related entry.
+ *
+ * @exception NoSuchAlgorithmException if the algorithm for recovering the
+ * key cannot be found
+ * @exception UnrecoverableKeyException if the key cannot be recovered
+ * (e.g., the given password is wrong).
+ */
+ public abstract Key engineGetKey(String alias, char[] password)
+ throws NoSuchAlgorithmException, UnrecoverableKeyException;
+
+ /**
+ * Returns the certificate chain associated with the given alias.
+ * The certificate chain must have been associated with the alias
+ * by a call to {@code setKeyEntry},
+ * or by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry}.
+ *
+ * @param alias the alias name
+ *
+ * @return the certificate chain (ordered with the user's certificate first
+ * and the root certificate authority last), or null if the given alias
+ * does not exist or does not contain a certificate chain
+ */
+ public abstract Certificate[] engineGetCertificateChain(String alias);
+
+ /**
+ * Returns the certificate associated with the given alias.
+ *
+ * <p> If the given alias name identifies an entry
+ * created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry},
+ * then the trusted certificate contained in that entry is returned.
+ *
+ * <p> If the given alias name identifies an entry
+ * created by a call to {@code setKeyEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry},
+ * then the first element of the certificate chain in that entry
+ * (if a chain exists) is returned.
+ *
+ * @param alias the alias name
+ *
+ * @return the certificate, or null if the given alias does not exist or
+ * does not contain a certificate.
+ */
+ public abstract Certificate engineGetCertificate(String alias);
+
+ /**
+ * Returns the creation date of the entry identified by the given alias.
+ *
+ * @param alias the alias name
+ *
+ * @return the creation date of this entry, or null if the given alias does
+ * not exist
+ */
+ public abstract Date engineGetCreationDate(String alias);
+
+ /**
+ * Assigns the given key to the given alias, protecting it with the given
+ * password.
+ *
+ * <p>If the given key is of type {@code java.security.PrivateKey},
+ * it must be accompanied by a certificate chain certifying the
+ * corresponding public key.
+ *
+ * <p>If the given alias already exists, the keystore information
+ * associated with it is overridden by the given key (and possibly
+ * certificate chain).
+ *
+ * @param alias the alias name
+ * @param key the key to be associated with the alias
+ * @param password the password to protect the key
+ * @param chain the certificate chain for the corresponding public
+ * key (only required if the given key is of type
+ * {@code java.security.PrivateKey}).
+ *
+ * @exception KeyStoreException if the given key cannot be protected, or
+ * this operation fails for some other reason
+ */
+ public abstract void engineSetKeyEntry(String alias, Key key,
+ char[] password,
+ Certificate[] chain)
+ throws KeyStoreException;
+
+ /**
+ * Assigns the given key (that has already been protected) to the given
+ * alias.
+ *
+ * <p>If the protected key is of type
+ * {@code java.security.PrivateKey},
+ * it must be accompanied by a certificate chain certifying the
+ * corresponding public key.
+ *
+ * <p>If the given alias already exists, the keystore information
+ * associated with it is overridden by the given key (and possibly
+ * certificate chain).
+ *
+ * @param alias the alias name
+ * @param key the key (in protected format) to be associated with the alias
+ * @param chain the certificate chain for the corresponding public
+ * key (only useful if the protected key is of type
+ * {@code java.security.PrivateKey}).
+ *
+ * @exception KeyStoreException if this operation fails.
+ */
+ public abstract void engineSetKeyEntry(String alias, byte[] key,
+ Certificate[] chain)
+ throws KeyStoreException;
+
+ /**
+ * Assigns the given certificate to the given alias.
+ *
+ * <p> If the given alias identifies an existing entry
+ * created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry},
+ * the trusted certificate in the existing entry
+ * is overridden by the given certificate.
+ *
+ * @param alias the alias name
+ * @param cert the certificate
+ *
+ * @exception KeyStoreException if the given alias already exists and does
+ * not identify an entry containing a trusted certificate,
+ * or this operation fails for some other reason.
+ */
+ public abstract void engineSetCertificateEntry(String alias,
+ Certificate cert)
+ throws KeyStoreException;
+
+ /**
+ * Deletes the entry identified by the given alias from this keystore.
+ *
+ * @param alias the alias name
+ *
+ * @exception KeyStoreException if the entry cannot be removed.
+ */
+ public abstract void engineDeleteEntry(String alias)
+ throws KeyStoreException;
+
+ /**
+ * Lists all the alias names of this keystore.
+ *
+ * @return enumeration of the alias names
+ */
+ public abstract Enumeration<String> engineAliases();
+
+ /**
+ * Checks if the given alias exists in this keystore.
+ *
+ * @param alias the alias name
+ *
+ * @return true if the alias exists, false otherwise
+ */
+ public abstract boolean engineContainsAlias(String alias);
+
+ /**
+ * Retrieves the number of entries in this keystore.
+ *
+ * @return the number of entries in this keystore
+ */
+ public abstract int engineSize();
+
+ /**
+ * Returns true if the entry identified by the given alias
+ * was created by a call to {@code setKeyEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry} or a {@code SecretKeyEntry}.
+ *
+ * @param alias the alias for the keystore entry to be checked
+ *
+ * @return true if the entry identified by the given alias is a
+ * key-related, false otherwise.
+ */
+ public abstract boolean engineIsKeyEntry(String alias);
+
+ /**
+ * Returns true if the entry identified by the given alias
+ * was created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry}.
+ *
+ * @param alias the alias for the keystore entry to be checked
+ *
+ * @return true if the entry identified by the given alias contains a
+ * trusted certificate, false otherwise.
+ */
+ public abstract boolean engineIsCertificateEntry(String alias);
+
+ /**
+ * Returns the (alias) name of the first keystore entry whose certificate
+ * matches the given certificate.
+ *
+ * <p>This method attempts to match the given certificate with each
+ * keystore entry. If the entry being considered was
+ * created by a call to {@code setCertificateEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code TrustedCertificateEntry},
+ * then the given certificate is compared to that entry's certificate.
+ *
+ * <p> If the entry being considered was
+ * created by a call to {@code setKeyEntry},
+ * or created by a call to {@code setEntry} with a
+ * {@code PrivateKeyEntry},
+ * then the given certificate is compared to the first
+ * element of that entry's certificate chain.
+ *
+ * @param cert the certificate to match with.
+ *
+ * @return the alias name of the first entry with matching certificate,
+ * or null if no such entry exists in this keystore.
+ */
+ public abstract String engineGetCertificateAlias(Certificate cert);
+
+ /**
+ * Stores this keystore to the given output stream, and protects its
+ * integrity with the given password.
+ *
+ * @param stream the output stream to which this keystore is written.
+ * @param password the password to generate the keystore integrity check
+ *
+ * @exception IOException if there was an I/O problem with data
+ * @exception NoSuchAlgorithmException if the appropriate data integrity
+ * algorithm could not be found
+ * @exception CertificateException if any of the certificates included in
+ * the keystore data could not be stored
+ */
+ public abstract void engineStore(OutputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException;
+
+ /**
+ * Stores this keystore using the given
+ * {@code KeyStore.LoadStoreParmeter}.
+ *
+ * @param param the {@code KeyStore.LoadStoreParmeter}
+ * that specifies how to store the keystore,
+ * which may be {@code null}
+ *
+ * @exception IllegalArgumentException if the given
+ * {@code KeyStore.LoadStoreParmeter}
+ * input is not recognized
+ * @exception IOException if there was an I/O problem with data
+ * @exception NoSuchAlgorithmException if the appropriate data integrity
+ * algorithm could not be found
+ * @exception CertificateException if any of the certificates included in
+ * the keystore data could not be stored
+ *
+ * @since 1.5
+ */
+ public void engineStore(KeyStore.LoadStoreParameter param)
+ throws IOException, NoSuchAlgorithmException,
+ CertificateException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Loads the keystore from the given input stream.
+ *
+ * <p>A password may be given to unlock the keystore
+ * (e.g. the keystore resides on a hardware token device),
+ * or to check the integrity of the keystore data.
+ * If a password is not given for integrity checking,
+ * then integrity checking is not performed.
+ *
+ * @param stream the input stream from which the keystore is loaded,
+ * or {@code null}
+ * @param password the password used to check the integrity of
+ * the keystore, the password used to unlock the keystore,
+ * or {@code null}
+ *
+ * @exception IOException if there is an I/O or format problem with the
+ * keystore data, if a password is required but not given,
+ * or if the given password was incorrect. If the error is due to a
+ * wrong password, the {@link Throwable#getCause cause} of the
+ * {@code IOException} should be an
+ * {@code UnrecoverableKeyException}
+ * @exception NoSuchAlgorithmException if the algorithm used to check
+ * the integrity of the keystore cannot be found
+ * @exception CertificateException if any of the certificates in the
+ * keystore could not be loaded
+ */
+ public abstract void engineLoad(InputStream stream, char[] password)
+ throws IOException, NoSuchAlgorithmException, CertificateException;
+
+ /**
+ * Loads the keystore using the given
+ * {@code KeyStore.LoadStoreParameter}.
+ *
+ * <p> Note that if this KeyStore has already been loaded, it is
+ * reinitialized and loaded again from the given parameter.
+ *
+ * @param param the {@code KeyStore.LoadStoreParameter}
+ * that specifies how to load the keystore,
+ * which may be {@code null}
+ *
+ * @exception IllegalArgumentException if the given
+ * {@code KeyStore.LoadStoreParameter}
+ * input is not recognized
+ * @exception IOException if there is an I/O or format problem with the
+ * keystore data. If the error is due to an incorrect
+ * {@code ProtectionParameter} (e.g. wrong password)
+ * the {@link Throwable#getCause cause} of the
+ * {@code IOException} should be an
+ * {@code UnrecoverableKeyException}
+ * @exception NoSuchAlgorithmException if the algorithm used to check
+ * the integrity of the keystore cannot be found
+ * @exception CertificateException if any of the certificates in the
+ * keystore could not be loaded
+ *
+ * @since 1.5
+ */
+ public void engineLoad(KeyStore.LoadStoreParameter param)
+ throws IOException, NoSuchAlgorithmException,
+ CertificateException {
+
+ if (param == null) {
+ engineLoad((InputStream)null, (char[])null);
+ return;
+ }
+
+ if (param instanceof KeyStore.SimpleLoadStoreParameter) {
+ ProtectionParameter protection = param.getProtectionParameter();
+ char[] password;
+ if (protection instanceof PasswordProtection) {
+ password = ((PasswordProtection)protection).getPassword();
+ } else if (protection instanceof CallbackHandlerProtection) {
+ CallbackHandler handler =
+ ((CallbackHandlerProtection)protection).getCallbackHandler();
+ PasswordCallback callback =
+ new PasswordCallback("Password: ", false);
+ try {
+ handler.handle(new Callback[] {callback});
+ } catch (UnsupportedCallbackException e) {
+ throw new NoSuchAlgorithmException
+ ("Could not obtain password", e);
+ }
+ password = callback.getPassword();
+ callback.clearPassword();
+ if (password == null) {
+ throw new NoSuchAlgorithmException
+ ("No password provided");
+ }
+ } else {
+ throw new NoSuchAlgorithmException("ProtectionParameter must"
+ + " be PasswordProtection or CallbackHandlerProtection");
+ }
+ engineLoad(null, password);
+ return;
+ }
+
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gets a {@code KeyStore.Entry} for the specified alias
+ * with the specified protection parameter.
+ *
+ * @param alias get the {@code KeyStore.Entry} for this alias
+ * @param protParam the {@code ProtectionParameter}
+ * used to protect the {@code Entry},
+ * which may be {@code null}
+ *
+ * @return the {@code KeyStore.Entry} for the specified alias,
+ * or {@code null} if there is no such entry
+ *
+ * @exception KeyStoreException if the operation failed
+ * @exception NoSuchAlgorithmException if the algorithm for recovering the
+ * entry cannot be found
+ * @exception UnrecoverableEntryException if the specified
+ * {@code protParam} were insufficient or invalid
+ * @exception UnrecoverableKeyException if the entry is a
+ * {@code PrivateKeyEntry} or {@code SecretKeyEntry}
+ * and the specified {@code protParam} does not contain
+ * the information needed to recover the key (e.g. wrong password)
+ *
+ * @since 1.5
+ */
+ public KeyStore.Entry engineGetEntry(String alias,
+ KeyStore.ProtectionParameter protParam)
+ throws KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableEntryException {
+
+ if (!engineContainsAlias(alias)) {
+ return null;
+ }
+
+ if (protParam == null) {
+ if (engineIsCertificateEntry(alias)) {
+ return new KeyStore.TrustedCertificateEntry
+ (engineGetCertificate(alias));
+ // Android-removed: Allow access to entries with no password.
+ // } else {
+ // throw new UnrecoverableKeyException
+ // ("requested entry requires a password");
+ }
+ }
+
+ // Android-changed: Add protParam == null to allow access to entries with no password.
+ if ((protParam == null) || protParam instanceof KeyStore.PasswordProtection) {
+ if (engineIsCertificateEntry(alias)) {
+ throw new UnsupportedOperationException
+ ("trusted certificate entries are not password-protected");
+ } else if (engineIsKeyEntry(alias)) {
+ // Android-changed: Allow access to entries with no password.
+ // KeyStore.PasswordProtection pp =
+ // (KeyStore.PasswordProtection)protParam;
+ // char[] password = pp.getPassword();
+ char[] password = null;
+ if (protParam != null) {
+ KeyStore.PasswordProtection pp =
+ (KeyStore.PasswordProtection)protParam;
+ password = pp.getPassword();
+ }
+ Key key = engineGetKey(alias, password);
+ if (key instanceof PrivateKey) {
+ Certificate[] chain = engineGetCertificateChain(alias);
+ return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain);
+ } else if (key instanceof SecretKey) {
+ return new KeyStore.SecretKeyEntry((SecretKey)key);
+ }
+ }
+ }
+
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Saves a {@code KeyStore.Entry} under the specified alias.
+ * The specified protection parameter is used to protect the
+ * {@code Entry}.
+ *
+ * <p> If an entry already exists for the specified alias,
+ * it is overridden.
+ *
+ * @param alias save the {@code KeyStore.Entry} under this alias
+ * @param entry the {@code Entry} to save
+ * @param protParam the {@code ProtectionParameter}
+ * used to protect the {@code Entry},
+ * which may be {@code null}
+ *
+ * @exception KeyStoreException if this operation fails
+ *
+ * @since 1.5
+ */
+ public void engineSetEntry(String alias, KeyStore.Entry entry,
+ KeyStore.ProtectionParameter protParam)
+ throws KeyStoreException {
+
+ // get password
+ if (protParam != null &&
+ !(protParam instanceof KeyStore.PasswordProtection)) {
+ throw new KeyStoreException("unsupported protection parameter");
+ }
+ KeyStore.PasswordProtection pProtect = null;
+ if (protParam != null) {
+ pProtect = (KeyStore.PasswordProtection)protParam;
+ }
+
+ // BEGIN Android-changed: Allow access to entries with no password.
+ char[] password = (pProtect == null) ? null : pProtect.getPassword();
+ // set entry
+ if (entry instanceof KeyStore.TrustedCertificateEntry) {
+ KeyStore.TrustedCertificateEntry tce =
+ (KeyStore.TrustedCertificateEntry)entry;
+ engineSetCertificateEntry(alias, tce.getTrustedCertificate());
+ return;
+ } else if (entry instanceof KeyStore.PrivateKeyEntry) {
+ engineSetKeyEntry
+ (alias,
+ ((KeyStore.PrivateKeyEntry)entry).getPrivateKey(),
+ password,
+ ((KeyStore.PrivateKeyEntry)entry).getCertificateChain());
+ return;
+ } else if (entry instanceof KeyStore.SecretKeyEntry) {
+ engineSetKeyEntry
+ (alias,
+ ((KeyStore.SecretKeyEntry)entry).getSecretKey(),
+ password,
+ (Certificate[])null);
+ return;
+ }
+ // END Android-changed: Allow access to entries with no password.
+
+ throw new KeyStoreException
+ ("unsupported entry type: " + entry.getClass().getName());
+ }
+
+ /**
+ * Determines if the keystore {@code Entry} for the specified
+ * {@code alias} is an instance or subclass of the specified
+ * {@code entryClass}.
+ *
+ * @param alias the alias name
+ * @param entryClass the entry class
+ *
+ * @return true if the keystore {@code Entry} for the specified
+ * {@code alias} is an instance or subclass of the
+ * specified {@code entryClass}, false otherwise
+ *
+ * @since 1.5
+ */
+ public boolean
+ engineEntryInstanceOf(String alias,
+ Class<? extends KeyStore.Entry> entryClass)
+ {
+ if (entryClass == KeyStore.TrustedCertificateEntry.class) {
+ return engineIsCertificateEntry(alias);
+ }
+ if (entryClass == KeyStore.PrivateKeyEntry.class) {
+ return engineIsKeyEntry(alias) &&
+ engineGetCertificate(alias) != null;
+ }
+ if (entryClass == KeyStore.SecretKeyEntry.class) {
+ return engineIsKeyEntry(alias) &&
+ engineGetCertificate(alias) == null;
+ }
+ return false;
+ }
+}
diff --git a/java/security/MessageDigest.java b/java/security/MessageDigest.java
new file mode 100644
index 0000000..8e5dab1
--- /dev/null
+++ b/java/security/MessageDigest.java
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+import java.lang.*;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+
+import java.nio.ByteBuffer;
+
+/**
+ * This MessageDigest class provides applications the functionality of a
+ * message digest algorithm, such as SHA-1 or SHA-256.
+ * Message digests are secure one-way hash functions that take arbitrary-sized
+ * data and output a fixed-length hash value.
+ *
+ * <p>A MessageDigest object starts out initialized. The data is
+ * processed through it using the {@link #update(byte) update}
+ * methods. At any point {@link #reset() reset} can be called
+ * to reset the digest. Once all the data to be updated has been
+ * updated, one of the {@link #digest() digest} methods should
+ * be called to complete the hash computation.
+ *
+ * <p>The {@code digest} method can be called once for a given number
+ * of updates. After {@code digest} has been called, the MessageDigest
+ * object is reset to its initialized state.
+ *
+ * <p>Implementations are free to implement the Cloneable interface.
+ * Client applications can test cloneability by attempting cloning
+ * and catching the CloneNotSupportedException:
+ *
+ * <pre>{@code
+ * MessageDigest md = MessageDigest.getInstance("SHA");
+ *
+ * try {
+ * md.update(toChapter1);
+ * MessageDigest tc1 = md.clone();
+ * byte[] toChapter1Digest = tc1.digest();
+ * md.update(toChapter2);
+ * ...etc.
+ * } catch (CloneNotSupportedException cnse) {
+ * throw new DigestException("couldn't make digest of partial content");
+ * }
+ * }</pre>
+ *
+ * <p>Note that if a given implementation is not cloneable, it is
+ * still possible to compute intermediate digests by instantiating
+ * several instances, if the number of digests is known in advance.
+ *
+ * <p>Note that this class is abstract and extends from
+ * {@code MessageDigestSpi} for historical reasons.
+ * Application developers should only take notice of the methods defined in
+ * this {@code MessageDigest} class; all the methods in
+ * the superclass are intended for cryptographic service providers who wish to
+ * supply their own implementations of message digest algorithms.
+ *
+ * <p> Android provides the following <code>MessageDigest</code> algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>MD5</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA-1</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA-224</td>
+ * <td>1-8,22+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA-256</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA-384</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA-512</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These algorithms are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#MessageDigest">
+ * MessageDigest section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Benjamin Renaud
+ *
+ * @see DigestInputStream
+ * @see DigestOutputStream
+ */
+
+public abstract class MessageDigest extends MessageDigestSpi {
+
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
+ private static final Debug pdebug =
+ Debug.getInstance("provider", "Provider");
+ private static final boolean skipDebug =
+ Debug.isOn("engine=") && !Debug.isOn("messagedigest");
+ */
+
+ private String algorithm;
+
+ // The state of this digest
+ private static final int INITIAL = 0;
+ private static final int IN_PROGRESS = 1;
+ private int state = INITIAL;
+
+ // The provider
+ private Provider provider;
+
+ /**
+ * Creates a message digest with the specified algorithm name.
+ *
+ * @param algorithm the standard name of the digest algorithm.
+ * See the MessageDigest section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#MessageDigest">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ */
+ protected MessageDigest(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns a MessageDigest object that implements the specified digest
+ * algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new MessageDigest object encapsulating the
+ * MessageDigestSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the algorithm requested.
+ * See the MessageDigest section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#MessageDigest">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return a Message Digest object that implements the specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * MessageDigestSpi implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ */
+ public static MessageDigest getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ try {
+ MessageDigest md;
+ Object[] objs = Security.getImpl(algorithm, "MessageDigest",
+ (String)null);
+ if (objs[0] instanceof MessageDigest) {
+ md = (MessageDigest)objs[0];
+ } else {
+ md = new Delegate((MessageDigestSpi)objs[0], algorithm);
+ }
+ md.provider = (Provider)objs[1];
+
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("MessageDigest." + algorithm +
+ " algorithm from: " + md.provider.getName());
+ }
+ */
+
+ return md;
+
+ } catch(NoSuchProviderException e) {
+ throw new NoSuchAlgorithmException(algorithm + " not found");
+ }
+ }
+
+ /**
+ * Returns a MessageDigest object that implements the specified digest
+ * algorithm.
+ *
+ * <p> A new MessageDigest object encapsulating the
+ * MessageDigestSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the algorithm requested.
+ * See the MessageDigest section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#MessageDigest">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a MessageDigest object that implements the specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if a MessageDigestSpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static MessageDigest getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException
+ {
+ if (provider == null || provider.length() == 0)
+ throw new IllegalArgumentException("missing provider");
+ Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
+ if (objs[0] instanceof MessageDigest) {
+ MessageDigest md = (MessageDigest)objs[0];
+ md.provider = (Provider)objs[1];
+ return md;
+ } else {
+ MessageDigest delegate =
+ new Delegate((MessageDigestSpi)objs[0], algorithm);
+ delegate.provider = (Provider)objs[1];
+ return delegate;
+ }
+ }
+
+ /**
+ * Returns a MessageDigest object that implements the specified digest
+ * algorithm.
+ *
+ * <p> A new MessageDigest object encapsulating the
+ * MessageDigestSpi 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 name of the algorithm requested.
+ * See the MessageDigest section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#MessageDigest">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return a MessageDigest object that implements the specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if a MessageDigestSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the specified provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static MessageDigest getInstance(String algorithm,
+ Provider provider)
+ throws NoSuchAlgorithmException
+ {
+ if (provider == null)
+ throw new IllegalArgumentException("missing provider");
+ Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
+ if (objs[0] instanceof MessageDigest) {
+ MessageDigest md = (MessageDigest)objs[0];
+ md.provider = (Provider)objs[1];
+ return md;
+ } else {
+ MessageDigest delegate =
+ new Delegate((MessageDigestSpi)objs[0], algorithm);
+ delegate.provider = (Provider)objs[1];
+ return delegate;
+ }
+ }
+
+ /**
+ * Returns the provider of this message digest object.
+ *
+ * @return the provider of this message digest object
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Updates the digest using the specified byte.
+ *
+ * @param input the byte with which to update the digest.
+ */
+ public void update(byte input) {
+ engineUpdate(input);
+ state = IN_PROGRESS;
+ }
+
+ /**
+ * Updates the digest using the specified array of bytes, starting
+ * at the specified offset.
+ *
+ * @param input the array of bytes.
+ *
+ * @param offset the offset to start from in the array of bytes.
+ *
+ * @param len the number of bytes to use, starting at
+ * {@code offset}.
+ */
+ public void update(byte[] input, int offset, int len) {
+ if (input == null) {
+ throw new IllegalArgumentException("No input buffer given");
+ }
+ if (input.length - offset < len) {
+ throw new IllegalArgumentException("Input buffer too short");
+ }
+ engineUpdate(input, offset, len);
+ state = IN_PROGRESS;
+ }
+
+ /**
+ * Updates the digest using the specified array of bytes.
+ *
+ * @param input the array of bytes.
+ */
+ public void update(byte[] input) {
+ engineUpdate(input, 0, input.length);
+ state = IN_PROGRESS;
+ }
+
+ /**
+ * Update the digest using the specified ByteBuffer. The digest is
+ * updated using the {@code input.remaining()} bytes starting
+ * at {@code input.position()}.
+ * Upon return, the buffer's position will be equal to its limit;
+ * its limit will not have changed.
+ *
+ * @param input the ByteBuffer
+ * @since 1.5
+ */
+ public final void update(ByteBuffer input) {
+ if (input == null) {
+ throw new NullPointerException();
+ }
+ engineUpdate(input);
+ state = IN_PROGRESS;
+ }
+
+ /**
+ * Completes the hash computation by performing final operations
+ * such as padding. The digest is reset after this call is made.
+ *
+ * @return the array of bytes for the resulting hash value.
+ */
+ public byte[] digest() {
+ /* Resetting is the responsibility of implementors. */
+ byte[] result = engineDigest();
+ state = INITIAL;
+ return result;
+ }
+
+ /**
+ * Completes the hash computation by performing final operations
+ * such as padding. The digest is reset after this call is made.
+ *
+ * @param buf output buffer for the computed digest
+ *
+ * @param offset offset into the output buffer to begin storing the digest
+ *
+ * @param len number of bytes within buf allotted for the digest
+ *
+ * @return the number of bytes placed into {@code buf}
+ *
+ * @exception DigestException if an error occurs.
+ */
+ public int digest(byte[] buf, int offset, int len) throws DigestException {
+ if (buf == null) {
+ throw new IllegalArgumentException("No output buffer given");
+ }
+ if (buf.length - offset < len) {
+ throw new IllegalArgumentException
+ ("Output buffer too small for specified offset and length");
+ }
+ int numBytes = engineDigest(buf, offset, len);
+ state = INITIAL;
+ return numBytes;
+ }
+
+ /**
+ * Performs a final update on the digest using the specified array
+ * of bytes, then completes the digest computation. That is, this
+ * method first calls {@link #update(byte[]) update(input)},
+ * passing the <i>input</i> array to the {@code update} method,
+ * then calls {@link #digest() digest()}.
+ *
+ * @param input the input to be updated before the digest is
+ * completed.
+ *
+ * @return the array of bytes for the resulting hash value.
+ */
+ public byte[] digest(byte[] input) {
+ update(input);
+ return digest();
+ }
+
+ /**
+ * Returns a string representation of this message digest object.
+ */
+ public String toString() {
+ // BEGIN Android-changed: Use StringBuilder instead of a ByteArrayOutputStream.
+ StringBuilder builder = new StringBuilder();
+ builder.append(algorithm);
+ builder.append(" Message Digest from ");
+ builder.append(provider.getName());
+ builder.append(", ");
+
+ switch (state) {
+ case INITIAL:
+ builder.append("<initialized>");
+ break;
+ case IN_PROGRESS:
+ builder.append("<in progress>");
+ break;
+ }
+
+ return builder.toString();
+ // END Android-changed: Use StringBuilder instead of a ByteArrayOutputStream.
+ }
+
+ /**
+ * Compares two digests for equality. Does a simple byte compare.
+ *
+ * @param digesta one of the digests to compare.
+ *
+ * @param digestb the other digest to compare.
+ *
+ * @return true if the digests are equal, false otherwise.
+ */
+ public static boolean isEqual(byte[] digesta, byte[] digestb) {
+ if (digesta == digestb) return true;
+ if (digesta == null || digestb == null) {
+ return false;
+ }
+ if (digesta.length != digestb.length) {
+ return false;
+ }
+
+ int result = 0;
+ // time-constant comparison
+ for (int i = 0; i < digesta.length; i++) {
+ result |= digesta[i] ^ digestb[i];
+ }
+ return result == 0;
+ }
+
+ /**
+ * Resets the digest for further use.
+ */
+ public void reset() {
+ engineReset();
+ state = INITIAL;
+ }
+
+ /**
+ * Returns a string that identifies the algorithm, independent of
+ * implementation details. The name should be a standard
+ * Java Security name (such as "SHA", "MD5", and so on).
+ * See the MessageDigest section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#MessageDigest">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the name of the algorithm
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns the length of the digest in bytes, or 0 if this operation is
+ * not supported by the provider and the implementation is not cloneable.
+ *
+ * @return the digest length in bytes, or 0 if this operation is not
+ * supported by the provider and the implementation is not cloneable.
+ *
+ * @since 1.2
+ */
+ public final int getDigestLength() {
+ int digestLen = engineGetDigestLength();
+ if (digestLen == 0) {
+ try {
+ MessageDigest md = (MessageDigest)clone();
+ byte[] digest = md.digest();
+ return digest.length;
+ } catch (CloneNotSupportedException e) {
+ return digestLen;
+ }
+ }
+ return digestLen;
+ }
+
+ /**
+ * 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 {@code Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ if (this instanceof Cloneable) {
+ return super.clone();
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+
+
+
+ /*
+ * The following class allows providers to extend from MessageDigestSpi
+ * rather than from MessageDigest. It represents a MessageDigest with an
+ * encapsulated, provider-supplied SPI object (of type MessageDigestSpi).
+ * If the provider implementation is an instance of MessageDigestSpi,
+ * the getInstance() methods above return an instance of this class, with
+ * the SPI object encapsulated.
+ *
+ * Note: All SPI methods from the original MessageDigest class have been
+ * moved up the hierarchy into a new class (MessageDigestSpi), which has
+ * been interposed in the hierarchy between the API (MessageDigest)
+ * and its original parent (Object).
+ */
+
+ static class Delegate extends MessageDigest {
+
+ // The provider implementation (delegate)
+ private MessageDigestSpi digestSpi;
+
+ // constructor
+ public Delegate(MessageDigestSpi digestSpi, String algorithm) {
+ super(algorithm);
+ this.digestSpi = digestSpi;
+ }
+
+ /**
+ * Returns a clone if the delegate is cloneable.
+ *
+ * @return a clone if the delegate is cloneable.
+ *
+ * @exception CloneNotSupportedException if this is called on a
+ * delegate that does not support {@code Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ if (digestSpi instanceof Cloneable) {
+ MessageDigestSpi digestSpiClone =
+ (MessageDigestSpi)digestSpi.clone();
+ // Because 'algorithm', 'provider', and 'state' are private
+ // members of our supertype, we must perform a cast to
+ // access them.
+ MessageDigest that =
+ new Delegate(digestSpiClone,
+ ((MessageDigest)this).algorithm);
+ that.provider = ((MessageDigest)this).provider;
+ that.state = ((MessageDigest)this).state;
+ return that;
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+ protected int engineGetDigestLength() {
+ return digestSpi.engineGetDigestLength();
+ }
+
+ protected void engineUpdate(byte input) {
+ digestSpi.engineUpdate(input);
+ }
+
+ protected void engineUpdate(byte[] input, int offset, int len) {
+ digestSpi.engineUpdate(input, offset, len);
+ }
+
+ protected void engineUpdate(ByteBuffer input) {
+ digestSpi.engineUpdate(input);
+ }
+
+ protected byte[] engineDigest() {
+ return digestSpi.engineDigest();
+ }
+
+ protected int engineDigest(byte[] buf, int offset, int len)
+ throws DigestException {
+ return digestSpi.engineDigest(buf, offset, len);
+ }
+
+ protected void engineReset() {
+ digestSpi.engineReset();
+ }
+ }
+}
diff --git a/java/security/MessageDigestSpi.java b/java/security/MessageDigestSpi.java
new file mode 100644
index 0000000..0d5ace1
--- /dev/null
+++ b/java/security/MessageDigestSpi.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.nio.ByteBuffer;
+
+import sun.security.jca.JCAUtil;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code MessageDigest} class, which provides the functionality
+ * of a message digest algorithm, such as MD5 or SHA. Message digests are
+ * secure one-way hash functions that take arbitrary-sized data and output a
+ * fixed-length hash value.
+ *
+ * <p> All the abstract methods in this class must be implemented by a
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular message digest algorithm.
+ *
+ * <p> Implementations are free to implement the Cloneable interface.
+ *
+ * @author Benjamin Renaud
+ *
+ *
+ * @see MessageDigest
+ */
+
+public abstract class MessageDigestSpi {
+
+ // for re-use in engineUpdate(ByteBuffer input)
+ private byte[] tempArray;
+
+ /**
+ * Returns the digest length in bytes.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ *
+ * <p>The default behavior is to return 0.
+ *
+ * <p>This method may be overridden by a provider to return the digest
+ * length.
+ *
+ * @return the digest length in bytes.
+ *
+ * @since 1.2
+ */
+ protected int engineGetDigestLength() {
+ return 0;
+ }
+
+ /**
+ * Updates the digest using the specified byte.
+ *
+ * @param input the byte to use for the update.
+ */
+ protected abstract void engineUpdate(byte input);
+
+ /**
+ * Updates the digest using the specified array of bytes,
+ * starting at the specified offset.
+ *
+ * @param input the array of bytes to use for the update.
+ *
+ * @param offset the offset to start from in the array of bytes.
+ *
+ * @param len the number of bytes to use, starting at
+ * {@code offset}.
+ */
+ protected abstract void engineUpdate(byte[] input, int offset, int len);
+
+ /**
+ * Update the digest using the specified ByteBuffer. The digest is
+ * updated using the {@code input.remaining()} bytes starting
+ * at {@code input.position()}.
+ * Upon return, the buffer's position will be equal to its limit;
+ * its limit will not have changed.
+ *
+ * @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();
+ int n = JCAUtil.getTempArraySize(len);
+ if ((tempArray == null) || (n > tempArray.length)) {
+ tempArray = new byte[n];
+ }
+ while (len > 0) {
+ int chunk = Math.min(len, tempArray.length);
+ input.get(tempArray, 0, chunk);
+ engineUpdate(tempArray, 0, chunk);
+ len -= chunk;
+ }
+ }
+ }
+
+ /**
+ * Completes the hash computation by performing final
+ * operations such as padding. Once {@code engineDigest} has
+ * been called, the engine should be reset (see
+ * {@link #engineReset() engineReset}).
+ * Resetting is the responsibility of the
+ * engine implementor.
+ *
+ * @return the array of bytes for the resulting hash value.
+ */
+ protected abstract byte[] engineDigest();
+
+ /**
+ * Completes the hash computation by performing final
+ * operations such as padding. Once {@code engineDigest} has
+ * been called, the engine should be reset (see
+ * {@link #engineReset() engineReset}).
+ * Resetting is the responsibility of the
+ * engine implementor.
+ *
+ * This method should be abstract, but we leave it concrete for
+ * binary compatibility. Knowledgeable providers should override this
+ * method.
+ *
+ * @param buf the output buffer in which to store the digest
+ *
+ * @param offset offset to start from in the output buffer
+ *
+ * @param len number of bytes within buf allotted for the digest.
+ * Both this default implementation and the SUN provider do not
+ * return partial digests. The presence of this parameter is solely
+ * for consistency in our API's. If the value of this parameter is less
+ * than the actual digest length, the method will throw a DigestException.
+ * This parameter is ignored if its value is greater than or equal to
+ * the actual digest length.
+ *
+ * @return the length of the digest stored in the output buffer.
+ *
+ * @exception DigestException if an error occurs.
+ *
+ * @since 1.2
+ */
+ protected int engineDigest(byte[] buf, int offset, int len)
+ throws DigestException {
+
+ byte[] digest = engineDigest();
+ if (len < digest.length)
+ throw new DigestException("partial digests not returned");
+ if (buf.length - offset < digest.length)
+ throw new DigestException("insufficient space in the output "
+ + "buffer to store the digest");
+ System.arraycopy(digest, 0, buf, offset, digest.length);
+ return digest.length;
+ }
+
+ /**
+ * Resets the digest for further use.
+ */
+ 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 {@code Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ if (this instanceof Cloneable) {
+ return super.clone();
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+}
diff --git a/java/security/NoSuchAlgorithmException.java b/java/security/NoSuchAlgorithmException.java
new file mode 100644
index 0000000..951e44e
--- /dev/null
+++ b/java/security/NoSuchAlgorithmException.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This exception is thrown when a particular cryptographic algorithm is
+ * requested but is not available in the environment.
+ *
+ * @author Benjamin Renaud
+ */
+
+public class NoSuchAlgorithmException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -7443947487218346562L;
+
+ /**
+ * Constructs a NoSuchAlgorithmException with no detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ */
+ public NoSuchAlgorithmException() {
+ super();
+ }
+
+ /**
+ * Constructs a NoSuchAlgorithmException with the specified
+ * detail message. A detail message is a String that describes
+ * this particular exception, which may, for example, specify which
+ * algorithm is not available.
+ *
+ * @param msg the detail message.
+ */
+ public NoSuchAlgorithmException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code NoSuchAlgorithmException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public NoSuchAlgorithmException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code NoSuchAlgorithmException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public NoSuchAlgorithmException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/NoSuchProviderException.java b/java/security/NoSuchProviderException.java
new file mode 100644
index 0000000..9874adb
--- /dev/null
+++ b/java/security/NoSuchProviderException.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This exception is thrown when a particular security provider is
+ * requested but is not available in the environment.
+ *
+ * @author Benjamin Renaud
+ */
+
+public class NoSuchProviderException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 8488111756688534474L;
+
+ /**
+ * Constructs a NoSuchProviderException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public NoSuchProviderException() {
+ super();
+ }
+
+ /**
+ * Constructs a NoSuchProviderException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public NoSuchProviderException(String msg) {
+ super(msg);
+ }
+}
diff --git a/java/security/PKCS12Attribute.java b/java/security/PKCS12Attribute.java
new file mode 100644
index 0000000..e389862
--- /dev/null
+++ b/java/security/PKCS12Attribute.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.regex.Pattern;
+import sun.security.util.*;
+
+/**
+ * An attribute associated with a PKCS12 keystore entry.
+ * The attribute name is an ASN.1 Object Identifier and the attribute
+ * value is a set of ASN.1 types.
+ *
+ * @since 1.8
+ */
+public final class PKCS12Attribute implements KeyStore.Entry.Attribute {
+
+ private static final Pattern COLON_SEPARATED_HEX_PAIRS =
+ Pattern.compile("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2})+$");
+ private String name;
+ private String value;
+ private byte[] encoded;
+ private int hashValue = -1;
+
+ /**
+ * Constructs a PKCS12 attribute from its name and value.
+ * The name is an ASN.1 Object Identifier represented as a list of
+ * dot-separated integers.
+ * A string value is represented as the string itself.
+ * A binary value is represented as a string of colon-separated
+ * pairs of hexadecimal digits.
+ * Multi-valued attributes are represented as a comma-separated
+ * list of values, enclosed in square brackets. See
+ * {@link Arrays#toString(java.lang.Object[])}.
+ * <p>
+ * A string value will be DER-encoded as an ASN.1 UTF8String and a
+ * binary value will be DER-encoded as an ASN.1 Octet String.
+ *
+ * @param name the attribute's identifier
+ * @param value the attribute's value
+ *
+ * @exception NullPointerException if {@code name} or {@code value}
+ * is {@code null}
+ * @exception IllegalArgumentException if {@code name} or
+ * {@code value} is incorrectly formatted
+ */
+ public PKCS12Attribute(String name, String value) {
+ if (name == null || value == null) {
+ throw new NullPointerException();
+ }
+ // Validate name
+ ObjectIdentifier type;
+ try {
+ type = new ObjectIdentifier(name);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Incorrect format: name", e);
+ }
+ this.name = name;
+
+ // Validate value
+ int length = value.length();
+ String[] values;
+ if (value.charAt(0) == '[' && value.charAt(length - 1) == ']') {
+ values = value.substring(1, length - 1).split(", ");
+ } else {
+ values = new String[]{ value };
+ }
+ this.value = value;
+
+ try {
+ this.encoded = encode(type, values);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Incorrect format: value", e);
+ }
+ }
+
+ /**
+ * Constructs a PKCS12 attribute from its ASN.1 DER encoding.
+ * The DER encoding is specified by the following ASN.1 definition:
+ * <pre>
+ *
+ * Attribute ::= SEQUENCE {
+ * type AttributeType,
+ * values SET OF AttributeValue
+ * }
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY defined by type
+ *
+ * </pre>
+ *
+ * @param encoded the attribute's ASN.1 DER encoding. It is cloned
+ * to prevent subsequent modificaion.
+ *
+ * @exception NullPointerException if {@code encoded} is
+ * {@code null}
+ * @exception IllegalArgumentException if {@code encoded} is
+ * incorrectly formatted
+ */
+ public PKCS12Attribute(byte[] encoded) {
+ if (encoded == null) {
+ throw new NullPointerException();
+ }
+ this.encoded = encoded.clone();
+
+ try {
+ parse(encoded);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Incorrect format: encoded", e);
+ }
+ }
+
+ /**
+ * Returns the attribute's ASN.1 Object Identifier represented as a
+ * list of dot-separated integers.
+ *
+ * @return the attribute's identifier
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the attribute's ASN.1 DER-encoded value as a string.
+ * An ASN.1 DER-encoded value is returned in one of the following
+ * {@code String} formats:
+ * <ul>
+ * <li> the DER encoding of a basic ASN.1 type that has a natural
+ * string representation is returned as the string itself.
+ * Such types are currently limited to BOOLEAN, INTEGER,
+ * OBJECT IDENTIFIER, UTCTime, GeneralizedTime and the
+ * following six ASN.1 string types: UTF8String,
+ * PrintableString, T61String, IA5String, BMPString and
+ * GeneralString.
+ * <li> the DER encoding of any other ASN.1 type is not decoded but
+ * returned as a binary string of colon-separated pairs of
+ * hexadecimal digits.
+ * </ul>
+ * Multi-valued attributes are represented as a comma-separated
+ * list of values, enclosed in square brackets. See
+ * {@link Arrays#toString(java.lang.Object[])}.
+ *
+ * @return the attribute value's string encoding
+ */
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the attribute's ASN.1 DER encoding.
+ *
+ * @return a clone of the attribute's DER encoding
+ */
+ public byte[] getEncoded() {
+ return encoded.clone();
+ }
+
+ /**
+ * Compares this {@code PKCS12Attribute} and a specified object for
+ * equality.
+ *
+ * @param obj the comparison object
+ *
+ * @return true if {@code obj} is a {@code PKCS12Attribute} and
+ * their DER encodings are equal.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof PKCS12Attribute)) {
+ return false;
+ }
+ return Arrays.equals(encoded, ((PKCS12Attribute) obj).getEncoded());
+ }
+
+ /**
+ * Returns the hashcode for this {@code PKCS12Attribute}.
+ * The hash code is computed from its DER encoding.
+ *
+ * @return the hash code
+ */
+ @Override
+ public int hashCode() {
+ if (hashValue == -1) {
+ Arrays.hashCode(encoded);
+ }
+ return hashValue;
+ }
+
+ /**
+ * Returns a string representation of this {@code PKCS12Attribute}.
+ *
+ * @return a name/value pair separated by an 'equals' symbol
+ */
+ @Override
+ public String toString() {
+ return (name + "=" + value);
+ }
+
+ private byte[] encode(ObjectIdentifier type, String[] values)
+ throws IOException {
+ DerOutputStream attribute = new DerOutputStream();
+ attribute.putOID(type);
+ DerOutputStream attrContent = new DerOutputStream();
+ for (String value : values) {
+ if (COLON_SEPARATED_HEX_PAIRS.matcher(value).matches()) {
+ byte[] bytes =
+ new BigInteger(value.replace(":", ""), 16).toByteArray();
+ if (bytes[0] == 0) {
+ bytes = Arrays.copyOfRange(bytes, 1, bytes.length);
+ }
+ attrContent.putOctetString(bytes);
+ } else {
+ attrContent.putUTF8String(value);
+ }
+ }
+ attribute.write(DerValue.tag_Set, attrContent);
+ DerOutputStream attributeValue = new DerOutputStream();
+ attributeValue.write(DerValue.tag_Sequence, attribute);
+
+ return attributeValue.toByteArray();
+ }
+
+ private void parse(byte[] encoded) throws IOException {
+ DerInputStream attributeValue = new DerInputStream(encoded);
+ DerValue[] attrSeq = attributeValue.getSequence(2);
+ ObjectIdentifier type = attrSeq[0].getOID();
+ DerInputStream attrContent =
+ new DerInputStream(attrSeq[1].toByteArray());
+ DerValue[] attrValueSet = attrContent.getSet(1);
+ String[] values = new String[attrValueSet.length];
+ String printableString;
+ for (int i = 0; i < attrValueSet.length; i++) {
+ if (attrValueSet[i].tag == DerValue.tag_OctetString) {
+ values[i] = Debug.toString(attrValueSet[i].getOctetString());
+ } else if ((printableString = attrValueSet[i].getAsString())
+ != null) {
+ values[i] = printableString;
+ } else if (attrValueSet[i].tag == DerValue.tag_ObjectId) {
+ values[i] = attrValueSet[i].getOID().toString();
+ } else if (attrValueSet[i].tag == DerValue.tag_GeneralizedTime) {
+ values[i] = attrValueSet[i].getGeneralizedTime().toString();
+ } else if (attrValueSet[i].tag == DerValue.tag_UtcTime) {
+ values[i] = attrValueSet[i].getUTCTime().toString();
+ } else if (attrValueSet[i].tag == DerValue.tag_Integer) {
+ values[i] = attrValueSet[i].getBigInteger().toString();
+ } else if (attrValueSet[i].tag == DerValue.tag_Boolean) {
+ values[i] = String.valueOf(attrValueSet[i].getBoolean());
+ } else {
+ values[i] = Debug.toString(attrValueSet[i].getDataBytes());
+ }
+ }
+
+ this.name = type.toString();
+ this.value = values.length == 1 ? values[0] : Arrays.toString(values);
+ }
+}
diff --git a/java/security/Permission.java b/java/security/Permission.java
new file mode 100644
index 0000000..9b258a6
--- /dev/null
+++ b/java/security/Permission.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public abstract class Permission implements Guard, java.io.Serializable {
+
+ private String name;
+
+ public Permission(String name) {
+ this.name = name;
+ }
+
+ public void checkGuard(Object object) throws SecurityException { }
+
+ public abstract boolean implies(Permission permission);
+
+ public final String getName() {
+ return name;
+ }
+
+ public abstract String getActions();
+
+ public PermissionCollection newPermissionCollection() { return new Permissions(); }
+}
diff --git a/java/security/PermissionCollection.java b/java/security/PermissionCollection.java
new file mode 100644
index 0000000..f1015e3
--- /dev/null
+++ b/java/security/PermissionCollection.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997, 2006, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public abstract class PermissionCollection implements java.io.Serializable {
+
+ public abstract void add(Permission permission);
+
+ public abstract boolean implies(Permission permission);
+
+ public abstract Enumeration<Permission> elements();
+
+ public void setReadOnly() { }
+
+ public boolean isReadOnly() { return true; }
+}
diff --git a/java/security/Permissions.java b/java/security/Permissions.java
new file mode 100644
index 0000000..9796f01
--- /dev/null
+++ b/java/security/Permissions.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.Enumeration;
+import java.io.Serializable;
+
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public final class Permissions extends PermissionCollection
+implements Serializable
+{
+ public void add(Permission permission) { }
+
+ public boolean implies(Permission permission) { return true; }
+
+ public Enumeration<Permission> elements() { return null; }
+}
diff --git a/java/security/Policy.java b/java/security/Policy.java
new file mode 100644
index 0000000..cb7fb3b
--- /dev/null
+++ b/java/security/Policy.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package java.security;
+
+import java.util.Enumeration;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public abstract class Policy {
+
+ public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
+ new UnsupportedEmptyCollection();
+
+ public static Policy getPolicy()
+ {
+ return null;
+ }
+
+ public static void setPolicy(Policy p)
+ {
+ }
+
+ public static Policy getInstance(String type, Policy.Parameters params)
+ throws NoSuchAlgorithmException {
+ return null;
+ }
+
+ public static Policy getInstance(String type,
+ Policy.Parameters params,
+ String provider)
+ throws NoSuchProviderException, NoSuchAlgorithmException {
+ return null;
+ }
+
+
+ public static Policy getInstance(String type,
+ Policy.Parameters params,
+ Provider provider)
+ throws NoSuchAlgorithmException {
+ return null;
+ }
+
+ public Provider getProvider() {
+ return null;
+ }
+
+ public String getType() {
+ return null;
+ }
+
+ public Policy.Parameters getParameters() {
+ return null;
+ }
+
+ public PermissionCollection getPermissions(CodeSource codesource) {
+ return null;
+ }
+
+ public PermissionCollection getPermissions(ProtectionDomain domain) {
+ return null;
+ }
+
+ public boolean implies(ProtectionDomain domain, Permission permission) {
+ return true;
+ }
+
+ public void refresh() { }
+
+ public static interface Parameters { }
+
+ private static class UnsupportedEmptyCollection
+ extends PermissionCollection {
+
+ public UnsupportedEmptyCollection() {
+ }
+
+ @Override public void add(Permission permission) {
+ }
+
+ @Override public boolean implies(Permission permission) {
+ return true;
+ }
+
+ @Override public Enumeration<Permission> elements() {
+ return null;
+ }
+ }
+
+}
diff --git a/java/security/PolicySpi.java b/java/security/PolicySpi.java
new file mode 100644
index 0000000..608ce1f
--- /dev/null
+++ b/java/security/PolicySpi.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package java.security;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code Policy} class.
+ * All the abstract methods in this class must be implemented by each
+ * service provider who wishes to supply a Policy implementation.
+ *
+ * <p> Subclass implementations of this abstract class must provide
+ * a public constructor that takes a {@code Policy.Parameters}
+ * object as an input parameter. This constructor also must throw
+ * an IllegalArgumentException if it does not understand the
+ * {@code Policy.Parameters} input.
+ *
+ *
+ * @since 1.6
+ */
+
+public abstract class PolicySpi {
+
+ /**
+ * Check whether the policy has granted a Permission to a ProtectionDomain.
+ *
+ * @param domain the ProtectionDomain to check.
+ *
+ * @param permission check whether this permission is granted to the
+ * specified domain.
+ *
+ * @return boolean true if the permission is granted to the domain.
+ */
+ protected abstract boolean engineImplies
+ (ProtectionDomain domain, Permission permission);
+
+ /**
+ * Refreshes/reloads the policy configuration. The behavior of this method
+ * depends on the implementation. For example, calling {@code refresh}
+ * on a file-based policy will cause the file to be re-read.
+ *
+ * <p> The default implementation of this method does nothing.
+ * This method should be overridden if a refresh operation is supported
+ * by the policy implementation.
+ */
+ protected void engineRefresh() { }
+
+ /**
+ * Return a PermissionCollection object containing the set of
+ * permissions granted to the specified CodeSource.
+ *
+ * <p> The default implementation of this method returns
+ * Policy.UNSUPPORTED_EMPTY_COLLECTION object. This method can be
+ * overridden if the policy implementation can return a set of
+ * permissions granted to a CodeSource.
+ *
+ * @param codesource the CodeSource to which the returned
+ * PermissionCollection has been granted.
+ *
+ * @return a set of permissions granted to the specified CodeSource.
+ * If this operation is supported, the returned
+ * set of permissions must be a new mutable instance
+ * and it must support heterogeneous Permission types.
+ * If this operation is not supported,
+ * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
+ */
+ protected PermissionCollection engineGetPermissions
+ (CodeSource codesource) {
+ return Policy.UNSUPPORTED_EMPTY_COLLECTION;
+ }
+
+ /**
+ * Return a PermissionCollection object containing the set of
+ * permissions granted to the specified ProtectionDomain.
+ *
+ * <p> The default implementation of this method returns
+ * Policy.UNSUPPORTED_EMPTY_COLLECTION object. This method can be
+ * overridden if the policy implementation can return a set of
+ * permissions granted to a ProtectionDomain.
+ *
+ * @param domain the ProtectionDomain to which the returned
+ * PermissionCollection has been granted.
+ *
+ * @return a set of permissions granted to the specified ProtectionDomain.
+ * If this operation is supported, the returned
+ * set of permissions must be a new mutable instance
+ * and it must support heterogeneous Permission types.
+ * If this operation is not supported,
+ * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
+ */
+ protected PermissionCollection engineGetPermissions
+ (ProtectionDomain domain) {
+ return Policy.UNSUPPORTED_EMPTY_COLLECTION;
+ }
+}
diff --git a/java/security/Principal.java b/java/security/Principal.java
new file mode 100644
index 0000000..a538e70
--- /dev/null
+++ b/java/security/Principal.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import javax.security.auth.Subject;
+
+/**
+ * This interface represents the abstract notion of a principal, which
+ * can be used to represent any entity, such as an individual, a
+ * corporation, and a login id.
+ *
+ * @see java.security.cert.X509Certificate
+ *
+ * @author Li Gong
+ */
+public interface Principal {
+
+ /**
+ * Compares this principal to the specified object. Returns true
+ * if the object passed in matches the principal represented by
+ * the implementation of this interface.
+ *
+ * @param another principal to compare with.
+ *
+ * @return true if the principal passed in is the same as that
+ * encapsulated by this principal, and false otherwise.
+ */
+ public boolean equals(Object another);
+
+ /**
+ * Returns a string representation of this principal.
+ *
+ * @return a string representation of this principal.
+ */
+ public String toString();
+
+ /**
+ * Returns a hashcode for this principal.
+ *
+ * @return a hashcode for this principal.
+ */
+ public int hashCode();
+
+ /**
+ * Returns the name of this principal.
+ *
+ * @return the name of this principal.
+ */
+ public String getName();
+
+ /**
+ * Returns true if the specified subject is implied by this principal.
+ *
+ * <p>The default implementation of this method returns true if
+ * {@code subject} is non-null and contains at least one principal that
+ * is equal to this principal.
+ *
+ * <p>Subclasses may override this with a different implementation, if
+ * necessary.
+ *
+ * @param subject the {@code Subject}
+ * @return true if {@code subject} is non-null and is
+ * implied by this principal, or false otherwise.
+ * @since 1.8
+ */
+ public default boolean implies(Subject subject) {
+ if (subject == null)
+ return false;
+ return subject.getPrincipals().contains(this);
+ }
+}
diff --git a/java/security/PrivateKey.java b/java/security/PrivateKey.java
new file mode 100644
index 0000000..7d8a7ea
--- /dev/null
+++ b/java/security/PrivateKey.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * A private key.
+ * The purpose of this interface is to group (and provide type safety
+ * for) all private key interfaces.
+ * <p>
+ * Note: The specialized private key interfaces extend this interface.
+ * See, for example, the {@code DSAPrivateKey} interface in
+ * {@link java.security.interfaces}.
+ * <p>
+ * Implementations should override the default {@code destroy} and
+ * {@code isDestroyed} methods from the
+ * {@link javax.security.auth.Destroyable} interface to enable
+ * sensitive key information to be destroyed, cleared, or in the case
+ * where such information is immutable, unreferenced.
+ * Finally, since {@code PrivateKey} is {@code Serializable}, implementations
+ * should also override
+ * {@link java.io.ObjectOutputStream#writeObject(java.lang.Object)}
+ * to prevent keys that have been destroyed from being serialized.
+ *
+ * @see Key
+ * @see PublicKey
+ * @see Certificate
+ * @see Signature#initVerify
+ * @see java.security.interfaces.DSAPrivateKey
+ * @see java.security.interfaces.RSAPrivateKey
+ * @see java.security.interfaces.RSAPrivateCrtKey
+ *
+ * @author Benjamin Renaud
+ * @author Josh Bloch
+ */
+
+public interface PrivateKey extends Key, javax.security.auth.Destroyable {
+
+ // Declare serialVersionUID to be compatible with JDK1.1
+ /**
+ * The class fingerprint that is set to indicate serialization
+ * compatibility with a previous version of the class.
+ */
+ static final long serialVersionUID = 6034044314589513430L;
+}
diff --git a/java/security/PrivilegedAction.java b/java/security/PrivilegedAction.java
new file mode 100644
index 0000000..5844b4d
--- /dev/null
+++ b/java/security/PrivilegedAction.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public interface PrivilegedAction<T> {
+
+ T run();
+}
diff --git a/java/security/PrivilegedActionException.java b/java/security/PrivilegedActionException.java
new file mode 100644
index 0000000..b1eb28f
--- /dev/null
+++ b/java/security/PrivilegedActionException.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ *
+ * This exception is thrown by
+ * {@code doPrivileged(PrivilegedExceptionAction)} and
+ * {@code doPrivileged(PrivilegedExceptionAction,
+ * AccessControlContext context)} to indicate
+ * that the action being performed threw a checked exception. The exception
+ * thrown by the action can be obtained by calling the
+ * {@code getException} method. In effect, an
+ * {@code PrivilegedActionException} is a "wrapper"
+ * for an exception thrown by a privileged action.
+ *
+ * <p>As of release 1.4, this exception has been retrofitted to conform to
+ * the general purpose exception-chaining mechanism. The "exception thrown
+ * by the privileged computation" that is provided at construction time and
+ * accessed via the {@link #getException()} method is now known as the
+ * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
+ * method, as well as the aforementioned "legacy method."
+ *
+ * @see PrivilegedExceptionAction
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction)
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext)
+ */
+public class PrivilegedActionException extends Exception {
+ // use serialVersionUID from JDK 1.2.2 for interoperability
+ private static final long serialVersionUID = 4724086851538908602L;
+
+ /**
+ * @serial
+ */
+ private Exception exception;
+
+ /**
+ * Constructs a new PrivilegedActionException "wrapping"
+ * the specific Exception.
+ *
+ * @param exception The exception thrown
+ */
+ public PrivilegedActionException(Exception exception) {
+ super((Throwable)null); // Disallow initCause
+ this.exception = exception;
+ }
+
+ /**
+ * Returns the exception thrown by the privileged computation that
+ * resulted in this {@code PrivilegedActionException}.
+ *
+ * <p>This method predates the general-purpose exception chaining facility.
+ * The {@link Throwable#getCause()} method is now the preferred means of
+ * obtaining this information.
+ *
+ * @return the exception thrown by the privileged computation that
+ * resulted in this {@code PrivilegedActionException}.
+ * @see PrivilegedExceptionAction
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction)
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction,
+ * AccessControlContext)
+ */
+ public Exception getException() {
+ return exception;
+ }
+
+ /**
+ * Returns the cause of this exception (the exception thrown by
+ * the privileged computation that resulted in this
+ * {@code PrivilegedActionException}).
+ *
+ * @return the cause of this exception.
+ * @since 1.4
+ */
+ public Throwable getCause() {
+ return exception;
+ }
+
+ public String toString() {
+ String s = getClass().getName();
+ return (exception != null) ? (s + ": " + exception.toString()) : s;
+ }
+}
diff --git a/java/security/PrivilegedExceptionAction.java b/java/security/PrivilegedExceptionAction.java
new file mode 100644
index 0000000..4023150
--- /dev/null
+++ b/java/security/PrivilegedExceptionAction.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public interface PrivilegedExceptionAction<T> {
+
+ T run() throws Exception;
+}
diff --git a/java/security/ProtectionDomain.java b/java/security/ProtectionDomain.java
new file mode 100644
index 0000000..9e117a6
--- /dev/null
+++ b/java/security/ProtectionDomain.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public class ProtectionDomain {
+
+ public ProtectionDomain(CodeSource codesource,
+ PermissionCollection permissions) { }
+
+ public ProtectionDomain(CodeSource codesource,
+ PermissionCollection permissions,
+ ClassLoader classloader,
+ Principal[] principals) { }
+
+ public final CodeSource getCodeSource() { return null; }
+
+ public final ClassLoader getClassLoader() { return null; }
+
+ public final Principal[] getPrincipals() { return null; }
+
+ public final PermissionCollection getPermissions() { return null; }
+
+ public boolean implies(Permission permission) { return true; }
+}
diff --git a/java/security/Provider.java b/java/security/Provider.java
new file mode 100644
index 0000000..cbf37db
--- /dev/null
+++ b/java/security/Provider.java
@@ -0,0 +1,1925 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static java.util.Locale.ENGLISH;
+
+import java.lang.ref.*;
+import java.lang.reflect.*;
+import java.security.Security;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * This class represents a "provider" for the
+ * Java Security API, where a provider implements some or all parts of
+ * Java Security. Services that a provider may implement include:
+ *
+ * <ul>
+ *
+ * <li>Algorithms (such as DSA, RSA, MD5 or SHA-1).
+ *
+ * <li>Key generation, conversion, and management facilities (such as for
+ * algorithm-specific keys).
+ *
+ *</ul>
+ *
+ * <p>Each provider has a name and a version number, and is configured
+ * in each runtime it is installed in.
+ *
+ * <p>See <a href =
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html#Provider">The Provider Class</a>
+ * in the "Java Cryptography Architecture API Specification & Reference"
+ * for information about how a particular type of provider, the
+ * cryptographic service provider, works and is installed. However,
+ * please note that a provider can be used to implement any security
+ * service in Java that uses a pluggable architecture with a choice
+ * of implementations that fit underneath.
+ *
+ * <p>Some provider implementations may encounter unrecoverable internal
+ * errors during their operation, for example a failure to communicate with a
+ * security token. A {@link ProviderException} should be used to indicate
+ * such errors.
+ *
+ * <p>The service type {@code Provider} is reserved for use by the
+ * security framework. Services of this type cannot be added, removed,
+ * or modified by applications.
+ * The following attributes are automatically placed in each Provider object:
+ * <table cellspacing=4>
+ * <caption><b>Attributes Automatically Placed in a Provider Object</b></caption>
+ * <tr><th>Name</th><th>Value</th>
+ * <tr><td>{@code Provider.id name}</td>
+ * <td>{@code String.valueOf(provider.getName())}</td>
+ * <tr><td>{@code Provider.id version}</td>
+ * <td>{@code String.valueOf(provider.getVersion())}</td>
+ * <tr><td>{@code Provider.id info}</td>
+ <td>{@code String.valueOf(provider.getInfo())}</td>
+ * <tr><td>{@code Provider.id className}</td>
+ * <td>{@code provider.getClass().getName()}</td>
+ * </table>
+ *
+ * @author Benjamin Renaud
+ * @author Andreas Sterbenz
+ */
+public abstract class Provider extends Properties {
+
+ // Declare serialVersionUID to be compatible with JDK1.1
+ static final long serialVersionUID = -4298000515446427739L;
+
+ // Android-added: Provider registration
+ // Marking a provider as "registered" makes it change the security version when
+ // changes to it are made. As of 2017-05-22 this is only used in ProviderTest.
+ // TODO: Change ProviderTest to no longer require this mechanism
+ private volatile boolean registered = false;
+
+ private static final sun.security.util.Debug debug =
+ sun.security.util.Debug.getInstance
+ ("provider", "Provider");
+
+ /**
+ * The provider name.
+ *
+ * @serial
+ */
+ private String name;
+
+ /**
+ * A description of the provider and its services.
+ *
+ * @serial
+ */
+ private String info;
+
+ /**
+ * The provider version number.
+ *
+ * @serial
+ */
+ private double version;
+
+
+ private transient Set<Map.Entry<Object,Object>> entrySet = null;
+ private transient int entrySetCallCount = 0;
+
+ private transient boolean initialized;
+
+ /**
+ * Constructs a provider with the specified name, version number,
+ * and information.
+ *
+ * @param name the provider name.
+ *
+ * @param version the provider version number.
+ *
+ * @param info a description of the provider and its services.
+ */
+ protected Provider(String name, double version, String info) {
+ this.name = name;
+ this.version = version;
+ this.info = info;
+ putId();
+ initialized = true;
+ }
+
+ /**
+ * Returns the name of this provider.
+ *
+ * @return the name of this provider.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the version number for this provider.
+ *
+ * @return the version number for this provider.
+ */
+ public double getVersion() {
+ return version;
+ }
+
+ /**
+ * Returns a human-readable description of the provider and its
+ * services. This may return an HTML page, with relevant links.
+ *
+ * @return a description of the provider and its services.
+ */
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * Returns a string with the name and the version number
+ * of this provider.
+ *
+ * @return the string with the name and the version number
+ * for this provider.
+ */
+ public String toString() {
+ return name + " version " + version;
+ }
+
+ /*
+ * override the following methods to ensure that provider
+ * information can only be changed if the caller has the appropriate
+ * permissions.
+ */
+
+ /**
+ * Clears this provider so that it no longer contains the properties
+ * used to look up facilities implemented by the provider.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "clearProviderProperties."+name}
+ * (where {@code name} is the provider name) to see if it's ok to clear
+ * this provider.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to clear this provider
+ *
+ * @since 1.2
+ */
+ @Override
+ public synchronized void clear() {
+ check("clearProviderProperties."+name);
+ if (debug != null) {
+ debug.println("Remove " + name + " provider properties");
+ }
+ implClear();
+ }
+
+ /**
+ * Reads a property list (key and element pairs) from the input stream.
+ *
+ * @param inStream the input stream.
+ * @exception IOException if an error occurred when reading from the
+ * input stream.
+ * @see java.util.Properties#load
+ */
+ @Override
+ public synchronized void load(InputStream inStream) throws IOException {
+ check("putProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Load " + name + " provider properties");
+ }
+ Properties tempProperties = new Properties();
+ tempProperties.load(inStream);
+ implPutAll(tempProperties);
+ }
+
+ /**
+ * Copies all of the mappings from the specified Map to this provider.
+ * These mappings will replace any properties that this provider had
+ * for any of the keys currently in the specified Map.
+ *
+ * @since 1.2
+ */
+ @Override
+ public synchronized void putAll(Map<?,?> t) {
+ check("putProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Put all " + name + " provider properties");
+ }
+ implPutAll(t);
+ }
+
+ /**
+ * Returns an unmodifiable Set view of the property entries contained
+ * in this Provider.
+ *
+ * @see java.util.Map.Entry
+ * @since 1.2
+ */
+ @Override
+ public synchronized Set<Map.Entry<Object,Object>> entrySet() {
+ checkInitialized();
+ if (entrySet == null) {
+ if (entrySetCallCount++ == 0) // Initial call
+ entrySet = Collections.unmodifiableMap(this).entrySet();
+ else
+ return super.entrySet(); // Recursive call
+ }
+
+ // This exception will be thrown if the implementation of
+ // Collections.unmodifiableMap.entrySet() is changed such that it
+ // no longer calls entrySet() on the backing Map. (Provider's
+ // entrySet implementation depends on this "implementation detail",
+ // which is unlikely to change.
+ if (entrySetCallCount != 2)
+ throw new RuntimeException("Internal error.");
+
+ return entrySet;
+ }
+
+ /**
+ * Returns an unmodifiable Set view of the property keys contained in
+ * this provider.
+ *
+ * @since 1.2
+ */
+ @Override
+ public Set<Object> keySet() {
+ checkInitialized();
+ return Collections.unmodifiableSet(super.keySet());
+ }
+
+ /**
+ * Returns an unmodifiable Collection view of the property values
+ * contained in this provider.
+ *
+ * @since 1.2
+ */
+ @Override
+ public Collection<Object> values() {
+ checkInitialized();
+ return Collections.unmodifiableCollection(super.values());
+ }
+
+ /**
+ * Sets the {@code key} property to have the specified
+ * {@code value}.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ *
+ * @since 1.2
+ */
+ @Override
+ public synchronized Object put(Object key, Object value) {
+ check("putProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Set " + name + " provider property [" +
+ key + "/" + value +"]");
+ }
+ return implPut(key, value);
+ }
+
+ /**
+ * If the specified key is not already associated with a value (or is mapped
+ * to {@code null}) associates it with the given value and returns
+ * {@code null}, else returns the current value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object putIfAbsent(Object key, Object value) {
+ check("putProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Set " + name + " provider property [" +
+ key + "/" + value +"]");
+ }
+ return implPutIfAbsent(key, value);
+ }
+
+ /**
+ * Removes the {@code key} property (and its corresponding
+ * {@code value}).
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "removeProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to remove this
+ * provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to remove this provider's properties.
+ *
+ * @since 1.2
+ */
+ @Override
+ public synchronized Object remove(Object key) {
+ check("removeProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Remove " + name + " provider property " + key);
+ }
+ return implRemove(key);
+ }
+
+ /**
+ * Removes the entry for the specified key only if it is currently
+ * mapped to the specified value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "removeProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to remove this
+ * provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to remove this provider's properties.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized boolean remove(Object key, Object value) {
+ check("removeProviderProperty."+name);
+ if (debug != null) {
+ debug.println("Remove " + name + " provider property " + key);
+ }
+ return implRemove(key, value);
+ }
+
+ /**
+ * Replaces the entry for the specified key only if currently
+ * mapped to the specified value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized boolean replace(Object key, Object oldValue,
+ Object newValue) {
+ check("putProviderProperty." + name);
+
+ if (debug != null) {
+ debug.println("Replace " + name + " provider property " + key);
+ }
+ return implReplace(key, oldValue, newValue);
+ }
+
+ /**
+ * Replaces the entry for the specified key only if it is
+ * currently mapped to some value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object replace(Object key, Object value) {
+ check("putProviderProperty." + name);
+
+ if (debug != null) {
+ debug.println("Replace " + name + " provider property " + key);
+ }
+ return implReplace(key, value);
+ }
+
+ /**
+ * Replaces each entry's value with the result of invoking the given
+ * function on that entry, in the order entries are returned by an entry
+ * set iterator, until all entries have been processed or the function
+ * throws an exception.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the string {@code "putProviderProperty."+name},
+ * where {@code name} is the provider name, to see if it's ok to set this
+ * provider's property values.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized void replaceAll(BiFunction<? super Object, ? super Object, ? extends Object> function) {
+ check("putProviderProperty." + name);
+
+ if (debug != null) {
+ debug.println("ReplaceAll " + name + " provider property ");
+ }
+ implReplaceAll(function);
+ }
+
+ /**
+ * Attempts to compute a mapping for the specified key and its
+ * current mapped value (or {@code null} if there is no current
+ * mapping).
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values or remove properties.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object compute(Object key,
+ BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("Compute " + name + " provider property " + key);
+ }
+ return implCompute(key, remappingFunction);
+ }
+
+ /**
+ * If the specified key is not already associated with a value (or
+ * is mapped to {@code null}), attempts to compute its value using
+ * the given mapping function and enters it into this map unless
+ * {@code null}.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values and remove properties.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object computeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("ComputeIfAbsent " + name + " provider property " +
+ key);
+ }
+ return implComputeIfAbsent(key, mappingFunction);
+ }
+
+ /**
+ * If the value for the specified key is present and non-null, attempts to
+ * compute a new mapping given the key and its current mapped value.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values or remove properties.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object computeIfPresent(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("ComputeIfPresent " + name + " provider property " +
+ key);
+ }
+ return implComputeIfPresent(key, remappingFunction);
+ }
+
+ /**
+ * If the specified key is not already associated with a value or is
+ * associated with null, associates it with the given value. Otherwise,
+ * replaces the value with the results of the given remapping function,
+ * or removes if the result is null. This method may be of use when
+ * combining multiple mapped values for a key.
+ *
+ * <p>If a security manager is enabled, its {@code checkSecurityAccess}
+ * method is called with the strings {@code "putProviderProperty."+name}
+ * and {@code "removeProviderProperty."+name}, where {@code name} is the
+ * provider name, to see if it's ok to set this provider's property values
+ * and remove this provider's properties.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to set property values or remove properties.
+ *
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object merge(Object key, Object value, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ check("putProviderProperty." + name);
+ check("removeProviderProperty" + name);
+
+ if (debug != null) {
+ debug.println("Merge " + name + " provider property " + key);
+ }
+ return implMerge(key, value, remappingFunction);
+ }
+
+ // let javadoc show doc from superclass
+ @Override
+ public Object get(Object key) {
+ checkInitialized();
+ return super.get(key);
+ }
+ /**
+ * @since 1.8
+ */
+ @Override
+ public synchronized Object getOrDefault(Object key, Object defaultValue) {
+ checkInitialized();
+ return super.getOrDefault(key, defaultValue);
+ }
+
+ /**
+ * @since 1.8
+ */
+ @Override
+ public synchronized void forEach(BiConsumer<? super Object, ? super Object> action) {
+ checkInitialized();
+ super.forEach(action);
+ }
+
+ // let javadoc show doc from superclass
+ @Override
+ public Enumeration<Object> keys() {
+ checkInitialized();
+ return super.keys();
+ }
+
+ // let javadoc show doc from superclass
+ @Override
+ public Enumeration<Object> elements() {
+ checkInitialized();
+ return super.elements();
+ }
+
+ // let javadoc show doc from superclass
+ public String getProperty(String key) {
+ checkInitialized();
+ return super.getProperty(key);
+ }
+
+ private void checkInitialized() {
+ if (!initialized) {
+ throw new IllegalStateException();
+ }
+ }
+
+ private void check(String directive) {
+ checkInitialized();
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkSecurityAccess(directive);
+ }
+ }
+
+ // legacy properties changed since last call to any services method?
+ private transient boolean legacyChanged;
+ // serviceMap changed since last call to getServices()
+ private transient boolean servicesChanged;
+
+ // Map<String,String>
+ private transient Map<String,String> legacyStrings;
+
+ // Map<ServiceKey,Service>
+ // used for services added via putService(), initialized on demand
+ private transient Map<ServiceKey,Service> serviceMap;
+
+ // Map<ServiceKey,Service>
+ // used for services added via legacy methods, init on demand
+ private transient Map<ServiceKey,Service> legacyMap;
+
+ // Set<Service>
+ // Unmodifiable set of all services. Initialized on demand.
+ private transient Set<Service> serviceSet;
+
+ // register the id attributes for this provider
+ // this is to ensure that equals() and hashCode() do not incorrectly
+ // report to different provider objects as the same
+ private void putId() {
+ // note: name and info may be null
+ super.put("Provider.id name", String.valueOf(name));
+ super.put("Provider.id version", String.valueOf(version));
+ super.put("Provider.id info", String.valueOf(info));
+ super.put("Provider.id className", this.getClass().getName());
+ }
+
+ private void readObject(ObjectInputStream in)
+ throws IOException, ClassNotFoundException {
+ // Android-added: Provider registration
+ registered = false;
+ Map<Object,Object> copy = new HashMap<>();
+ for (Map.Entry<Object,Object> entry : super.entrySet()) {
+ copy.put(entry.getKey(), entry.getValue());
+ }
+ defaults = null;
+ in.defaultReadObject();
+ implClear();
+ initialized = true;
+ putAll(copy);
+ }
+
+ private boolean checkLegacy(Object key) {
+ // Android-added: Provider registration
+ if (registered) {
+ Security.increaseVersion();
+ }
+ String keyString = (String)key;
+ if (keyString.startsWith("Provider.")) {
+ return false;
+ }
+
+ legacyChanged = true;
+ if (legacyStrings == null) {
+ legacyStrings = new LinkedHashMap<String,String>();
+ }
+ return true;
+ }
+
+ /**
+ * Copies all of the mappings from the specified Map to this provider.
+ * Internal method to be called AFTER the security check has been
+ * performed.
+ */
+ private void implPutAll(Map<?,?> t) {
+ for (Map.Entry<?,?> e : t.entrySet()) {
+ implPut(e.getKey(), e.getValue());
+ }
+ // Android-added: Provider registration
+ if (registered) {
+ Security.increaseVersion();
+ }
+ }
+
+ private Object implRemove(Object key) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.remove((String)key);
+ }
+ return super.remove(key);
+ }
+
+ private boolean implRemove(Object key, Object value) {
+ if (key instanceof String && value instanceof String) {
+ if (!checkLegacy(key)) {
+ return false;
+ }
+ legacyStrings.remove((String)key, value);
+ }
+ return super.remove(key, value);
+ }
+
+ private boolean implReplace(Object key, Object oldValue, Object newValue) {
+ if ((key instanceof String) && (oldValue instanceof String) &&
+ (newValue instanceof String)) {
+ if (!checkLegacy(key)) {
+ return false;
+ }
+ legacyStrings.replace((String)key, (String)oldValue,
+ (String)newValue);
+ }
+ return super.replace(key, oldValue, newValue);
+ }
+
+ private Object implReplace(Object key, Object value) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.replace((String)key, (String)value);
+ }
+ return super.replace(key, value);
+ }
+
+ private void implReplaceAll(BiFunction<? super Object, ? super Object, ? extends Object> function) {
+ legacyChanged = true;
+ if (legacyStrings == null) {
+ legacyStrings = new LinkedHashMap<String,String>();
+ } else {
+ legacyStrings.replaceAll((BiFunction<? super String, ? super String, ? extends String>) function);
+ }
+ super.replaceAll(function);
+ }
+
+
+ private Object implMerge(Object key, Object value, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.merge((String)key, (String)value,
+ (BiFunction<? super String, ? super String, ? extends String>) remappingFunction);
+ }
+ return super.merge(key, value, remappingFunction);
+ }
+
+ private Object implCompute(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ // BEGIN Android-changed: was
+ // legacyStrings.computeIfAbsent((String) key,
+ // (Function<? super String, ? extends String>) remappingFunction);
+ // which cannot ever succeed as the cast from BiFunction to Function always fails
+ legacyStrings.compute((String) key,
+ (BiFunction<? super String, ? super String, ? extends String>)
+ remappingFunction);
+ // END Android-changed
+ }
+ return super.compute(key, remappingFunction);
+ }
+
+ private Object implComputeIfAbsent(Object key, Function<? super Object, ? extends Object> mappingFunction) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.computeIfAbsent((String) key,
+ (Function<? super String, ? extends String>) mappingFunction);
+ }
+ return super.computeIfAbsent(key, mappingFunction);
+ }
+
+ private Object implComputeIfPresent(Object key, BiFunction<? super Object, ? super Object, ? extends Object> remappingFunction) {
+ if (key instanceof String) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.computeIfPresent((String) key,
+ (BiFunction<? super String, ? super String, ? extends String>) remappingFunction);
+ }
+ return super.computeIfPresent(key, remappingFunction);
+ }
+
+ private Object implPut(Object key, Object value) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.put((String)key, (String)value);
+ }
+ return super.put(key, value);
+ }
+
+ private Object implPutIfAbsent(Object key, Object value) {
+ if ((key instanceof String) && (value instanceof String)) {
+ if (!checkLegacy(key)) {
+ return null;
+ }
+ legacyStrings.putIfAbsent((String)key, (String)value);
+ }
+ return super.putIfAbsent(key, value);
+ }
+
+ private void implClear() {
+ if (legacyStrings != null) {
+ legacyStrings.clear();
+ }
+ if (legacyMap != null) {
+ legacyMap.clear();
+ }
+ if (serviceMap != null) {
+ serviceMap.clear();
+ }
+ legacyChanged = false;
+ servicesChanged = false;
+ serviceSet = null;
+ super.clear();
+ putId();
+ // Android-added: Provider registration
+ if (registered) {
+ Security.increaseVersion();
+ }
+ }
+
+ // used as key in the serviceMap and legacyMap HashMaps
+ private static class ServiceKey {
+ private final String type;
+ private final String algorithm;
+ private final String originalAlgorithm;
+ private ServiceKey(String type, String algorithm, boolean intern) {
+ this.type = type;
+ this.originalAlgorithm = algorithm;
+ algorithm = algorithm.toUpperCase(ENGLISH);
+ this.algorithm = intern ? algorithm.intern() : algorithm;
+ }
+ public int hashCode() {
+ return type.hashCode() + algorithm.hashCode();
+ }
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ServiceKey == false) {
+ return false;
+ }
+ ServiceKey other = (ServiceKey)obj;
+ return this.type.equals(other.type)
+ && this.algorithm.equals(other.algorithm);
+ }
+ boolean matches(String type, String algorithm) {
+ return (this.type == type) && (this.originalAlgorithm == algorithm);
+ }
+ }
+
+ /**
+ * Ensure all the legacy String properties are fully parsed into
+ * service objects.
+ */
+ private void ensureLegacyParsed() {
+ if ((legacyChanged == false) || (legacyStrings == null)) {
+ return;
+ }
+ serviceSet = null;
+ if (legacyMap == null) {
+ legacyMap = new LinkedHashMap<ServiceKey,Service>();
+ } else {
+ legacyMap.clear();
+ }
+ for (Map.Entry<String,String> entry : legacyStrings.entrySet()) {
+ parseLegacyPut(entry.getKey(), entry.getValue());
+ }
+ removeInvalidServices(legacyMap);
+ legacyChanged = false;
+ }
+
+ /**
+ * Remove all invalid services from the Map. Invalid services can only
+ * occur if the legacy properties are inconsistent or incomplete.
+ */
+ private void removeInvalidServices(Map<ServiceKey,Service> map) {
+ for (Iterator<Map.Entry<ServiceKey, Service>> t =
+ map.entrySet().iterator(); t.hasNext(); ) {
+ Service s = t.next().getValue();
+ if (s.isValid() == false) {
+ t.remove();
+ }
+ }
+ }
+
+ private String[] getTypeAndAlgorithm(String key) {
+ int i = key.indexOf(".");
+ if (i < 1) {
+ if (debug != null) {
+ debug.println("Ignoring invalid entry in provider "
+ + name + ":" + key);
+ }
+ return null;
+ }
+ String type = key.substring(0, i);
+ String alg = key.substring(i + 1);
+ return new String[] {type, alg};
+ }
+
+ private final static String ALIAS_PREFIX = "Alg.Alias.";
+ private final static String ALIAS_PREFIX_LOWER = "alg.alias.";
+ private final static int ALIAS_LENGTH = ALIAS_PREFIX.length();
+
+ private void parseLegacyPut(String name, String value) {
+ if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) {
+ // e.g. put("Alg.Alias.MessageDigest.SHA", "SHA-1");
+ // aliasKey ~ MessageDigest.SHA
+ String stdAlg = value;
+ String aliasKey = name.substring(ALIAS_LENGTH);
+ String[] typeAndAlg = getTypeAndAlgorithm(aliasKey);
+ if (typeAndAlg == null) {
+ return;
+ }
+ String type = getEngineName(typeAndAlg[0]);
+ String aliasAlg = typeAndAlg[1].intern();
+ ServiceKey key = new ServiceKey(type, stdAlg, true);
+ Service s = legacyMap.get(key);
+ if (s == null) {
+ s = new Service(this);
+ s.type = type;
+ s.algorithm = stdAlg;
+ legacyMap.put(key, s);
+ }
+ legacyMap.put(new ServiceKey(type, aliasAlg, true), s);
+ s.addAlias(aliasAlg);
+ } else {
+ String[] typeAndAlg = getTypeAndAlgorithm(name);
+ if (typeAndAlg == null) {
+ return;
+ }
+ int i = typeAndAlg[1].indexOf(' ');
+ if (i == -1) {
+ // e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA");
+ String type = getEngineName(typeAndAlg[0]);
+ String stdAlg = typeAndAlg[1].intern();
+ String className = value;
+ ServiceKey key = new ServiceKey(type, stdAlg, true);
+ Service s = legacyMap.get(key);
+ if (s == null) {
+ s = new Service(this);
+ s.type = type;
+ s.algorithm = stdAlg;
+ legacyMap.put(key, s);
+ }
+ s.className = className;
+ } else { // attribute
+ // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software");
+ String attributeValue = value;
+ String type = getEngineName(typeAndAlg[0]);
+ String attributeString = typeAndAlg[1];
+ String stdAlg = attributeString.substring(0, i).intern();
+ String attributeName = attributeString.substring(i + 1);
+ // kill additional spaces
+ while (attributeName.startsWith(" ")) {
+ attributeName = attributeName.substring(1);
+ }
+ attributeName = attributeName.intern();
+ ServiceKey key = new ServiceKey(type, stdAlg, true);
+ Service s = legacyMap.get(key);
+ if (s == null) {
+ s = new Service(this);
+ s.type = type;
+ s.algorithm = stdAlg;
+ legacyMap.put(key, s);
+ }
+ s.addAttribute(attributeName, attributeValue);
+ }
+ }
+ }
+
+ /**
+ * Get the service describing this Provider's implementation of the
+ * specified type of this algorithm or alias. If no such
+ * implementation exists, this method returns null. If there are two
+ * matching services, one added to this provider using
+ * {@link #putService putService()} and one added via {@link #put put()},
+ * the service added via {@link #putService putService()} is returned.
+ *
+ * @param type the type of {@link Service service} requested
+ * (for example, {@code MessageDigest})
+ * @param algorithm the case insensitive algorithm name (or alternate
+ * alias) of the service requested (for example, {@code SHA-1})
+ *
+ * @return the service describing this Provider's matching service
+ * or null if no such service exists
+ *
+ * @throws NullPointerException if type or algorithm is null
+ *
+ * @since 1.5
+ */
+ public synchronized Service getService(String type, String algorithm) {
+ checkInitialized();
+ // avoid allocating a new key object if possible
+ ServiceKey key = previousKey;
+ if (key.matches(type, algorithm) == false) {
+ key = new ServiceKey(type, algorithm, false);
+ previousKey = key;
+ }
+ if (serviceMap != null) {
+ Service service = serviceMap.get(key);
+ if (service != null) {
+ return service;
+ }
+ }
+ ensureLegacyParsed();
+ return (legacyMap != null) ? legacyMap.get(key) : null;
+ }
+
+ // ServiceKey from previous getService() call
+ // by re-using it if possible we avoid allocating a new object
+ // and the toUpperCase() call.
+ // re-use will occur e.g. as the framework traverses the provider
+ // list and queries each provider with the same values until it finds
+ // a matching service
+ private static volatile ServiceKey previousKey =
+ new ServiceKey("", "", false);
+
+ /**
+ * Get an unmodifiable Set of all services supported by
+ * this Provider.
+ *
+ * @return an unmodifiable Set of all services supported by
+ * this Provider
+ *
+ * @since 1.5
+ */
+ public synchronized Set<Service> getServices() {
+ checkInitialized();
+ if (legacyChanged || servicesChanged) {
+ serviceSet = null;
+ }
+ if (serviceSet == null) {
+ ensureLegacyParsed();
+ Set<Service> set = new LinkedHashSet<>();
+ if (serviceMap != null) {
+ set.addAll(serviceMap.values());
+ }
+ if (legacyMap != null) {
+ set.addAll(legacyMap.values());
+ }
+ serviceSet = Collections.unmodifiableSet(set);
+ servicesChanged = false;
+ }
+ return serviceSet;
+ }
+
+ /**
+ * Add a service. If a service of the same type with the same algorithm
+ * name exists and it was added using {@link #putService putService()},
+ * it is replaced by the new service.
+ * This method also places information about this service
+ * in the provider's Hashtable values in the format described in the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * Java Cryptography Architecture API Specification & Reference </a>.
+ *
+ * <p>Also, if there is a security manager, its
+ * {@code checkSecurityAccess} method is called with the string
+ * {@code "putProviderProperty."+name}, where {@code name} is
+ * the provider name, to see if it's ok to set this provider's property
+ * values. If the default implementation of {@code checkSecurityAccess}
+ * is used (that is, that method is not overriden), then this results in
+ * a call to the security manager's {@code checkPermission} method with
+ * a {@code SecurityPermission("putProviderProperty."+name)}
+ * permission.
+ *
+ * @param s the Service to add
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method denies
+ * access to set property values.
+ * @throws NullPointerException if s is null
+ *
+ * @since 1.5
+ */
+ protected synchronized void putService(Service s) {
+ check("putProviderProperty." + name);
+ if (debug != null) {
+ debug.println(name + ".putService(): " + s);
+ }
+ if (s == null) {
+ throw new NullPointerException();
+ }
+ if (s.getProvider() != this) {
+ throw new IllegalArgumentException
+ ("service.getProvider() must match this Provider object");
+ }
+ if (serviceMap == null) {
+ serviceMap = new LinkedHashMap<ServiceKey,Service>();
+ }
+ servicesChanged = true;
+ String type = s.getType();
+ String algorithm = s.getAlgorithm();
+ ServiceKey key = new ServiceKey(type, algorithm, true);
+ // remove existing service
+ implRemoveService(serviceMap.get(key));
+ serviceMap.put(key, s);
+ for (String alias : s.getAliases()) {
+ serviceMap.put(new ServiceKey(type, alias, true), s);
+ }
+ putPropertyStrings(s);
+ }
+
+ /**
+ * Put the string properties for this Service in this Provider's
+ * Hashtable.
+ */
+ private void putPropertyStrings(Service s) {
+ String type = s.getType();
+ String algorithm = s.getAlgorithm();
+ // use super() to avoid permission check and other processing
+ super.put(type + "." + algorithm, s.getClassName());
+ for (String alias : s.getAliases()) {
+ super.put(ALIAS_PREFIX + type + "." + alias, algorithm);
+ }
+ for (Map.Entry<UString,String> entry : s.attributes.entrySet()) {
+ String key = type + "." + algorithm + " " + entry.getKey();
+ super.put(key, entry.getValue());
+ }
+ // Android-added: Provider registration
+ if (registered) {
+ Security.increaseVersion();
+ }
+ }
+
+ /**
+ * Remove the string properties for this Service from this Provider's
+ * Hashtable.
+ */
+ private void removePropertyStrings(Service s) {
+ String type = s.getType();
+ String algorithm = s.getAlgorithm();
+ // use super() to avoid permission check and other processing
+ super.remove(type + "." + algorithm);
+ for (String alias : s.getAliases()) {
+ super.remove(ALIAS_PREFIX + type + "." + alias);
+ }
+ for (Map.Entry<UString,String> entry : s.attributes.entrySet()) {
+ String key = type + "." + algorithm + " " + entry.getKey();
+ super.remove(key);
+ }
+ // Android-added: Provider registration
+ if (registered) {
+ Security.increaseVersion();
+ }
+ }
+
+ /**
+ * Remove a service previously added using
+ * {@link #putService putService()}. The specified service is removed from
+ * this provider. It will no longer be returned by
+ * {@link #getService getService()} and its information will be removed
+ * from this provider's Hashtable.
+ *
+ * <p>Also, if there is a security manager, its
+ * {@code checkSecurityAccess} method is called with the string
+ * {@code "removeProviderProperty."+name}, where {@code name} is
+ * the provider name, to see if it's ok to remove this provider's
+ * properties. If the default implementation of
+ * {@code checkSecurityAccess} is used (that is, that method is not
+ * overriden), then this results in a call to the security manager's
+ * {@code checkPermission} method with a
+ * {@code SecurityPermission("removeProviderProperty."+name)}
+ * permission.
+ *
+ * @param s the Service to be removed
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method denies
+ * access to remove this provider's properties.
+ * @throws NullPointerException if s is null
+ *
+ * @since 1.5
+ */
+ protected synchronized void removeService(Service s) {
+ check("removeProviderProperty." + name);
+ if (debug != null) {
+ debug.println(name + ".removeService(): " + s);
+ }
+ if (s == null) {
+ throw new NullPointerException();
+ }
+ implRemoveService(s);
+ }
+
+ private void implRemoveService(Service s) {
+ if ((s == null) || (serviceMap == null)) {
+ return;
+ }
+ String type = s.getType();
+ String algorithm = s.getAlgorithm();
+ ServiceKey key = new ServiceKey(type, algorithm, false);
+ Service oldService = serviceMap.get(key);
+ if (s != oldService) {
+ return;
+ }
+ servicesChanged = true;
+ serviceMap.remove(key);
+ for (String alias : s.getAliases()) {
+ serviceMap.remove(new ServiceKey(type, alias, false));
+ }
+ removePropertyStrings(s);
+ }
+
+ // Wrapped String that behaves in a case insensitive way for equals/hashCode
+ private static class UString {
+ final String string;
+ final String lowerString;
+
+ UString(String s) {
+ this.string = s;
+ this.lowerString = s.toLowerCase(ENGLISH);
+ }
+
+ public int hashCode() {
+ return lowerString.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof UString == false) {
+ return false;
+ }
+ UString other = (UString)obj;
+ return lowerString.equals(other.lowerString);
+ }
+
+ public String toString() {
+ return string;
+ }
+ }
+
+ // describe relevant properties of a type of engine
+ private static class EngineDescription {
+ final String name;
+ final boolean supportsParameter;
+ final String constructorParameterClassName;
+ private volatile Class<?> constructorParameterClass;
+
+ EngineDescription(String name, boolean sp, String paramName) {
+ this.name = name;
+ this.supportsParameter = sp;
+ this.constructorParameterClassName = paramName;
+ }
+ Class<?> getConstructorParameterClass() throws ClassNotFoundException {
+ Class<?> clazz = constructorParameterClass;
+ if (clazz == null) {
+ clazz = Class.forName(constructorParameterClassName);
+ constructorParameterClass = clazz;
+ }
+ return clazz;
+ }
+ }
+
+ // built in knowledge of the engine types shipped as part of the JDK
+ private static final Map<String,EngineDescription> knownEngines;
+
+ private static void addEngine(String name, boolean sp, String paramName) {
+ EngineDescription ed = new EngineDescription(name, sp, paramName);
+ // also index by canonical name to avoid toLowerCase() for some lookups
+ knownEngines.put(name.toLowerCase(ENGLISH), ed);
+ knownEngines.put(name, ed);
+ }
+
+ static {
+ knownEngines = new HashMap<String,EngineDescription>();
+ // JCA
+ addEngine("AlgorithmParameterGenerator", false, null);
+ addEngine("AlgorithmParameters", false, null);
+ addEngine("KeyFactory", false, null);
+ addEngine("KeyPairGenerator", false, null);
+ addEngine("KeyStore", false, null);
+ addEngine("MessageDigest", false, null);
+ addEngine("SecureRandom", false, null);
+ addEngine("Signature", true, null);
+ addEngine("CertificateFactory", false, null);
+ addEngine("CertPathBuilder", false, null);
+ addEngine("CertPathValidator", false, null);
+ addEngine("CertStore", false,
+ "java.security.cert.CertStoreParameters");
+ // JCE
+ addEngine("Cipher", true, null);
+ addEngine("ExemptionMechanism", false, null);
+ addEngine("Mac", true, null);
+ addEngine("KeyAgreement", true, null);
+ addEngine("KeyGenerator", false, null);
+ addEngine("SecretKeyFactory", false, null);
+ // JSSE
+ addEngine("KeyManagerFactory", false, null);
+ addEngine("SSLContext", false, null);
+ addEngine("TrustManagerFactory", false, null);
+ // JGSS
+ addEngine("GssApiMechanism", false, null);
+ // SASL
+ addEngine("SaslClientFactory", false, null);
+ addEngine("SaslServerFactory", false, null);
+ // POLICY
+ addEngine("Policy", false,
+ "java.security.Policy$Parameters");
+ // CONFIGURATION
+ addEngine("Configuration", false,
+ "javax.security.auth.login.Configuration$Parameters");
+ // XML DSig
+ addEngine("XMLSignatureFactory", false, null);
+ addEngine("KeyInfoFactory", false, null);
+ addEngine("TransformService", false, null);
+ // Smart Card I/O
+ addEngine("TerminalFactory", false,
+ "java.lang.Object");
+ }
+
+ // get the "standard" (mixed-case) engine name for arbitary case engine name
+ // if there is no known engine by that name, return s
+ private static String getEngineName(String s) {
+ // try original case first, usually correct
+ EngineDescription e = knownEngines.get(s);
+ if (e == null) {
+ e = knownEngines.get(s.toLowerCase(ENGLISH));
+ }
+ return (e == null) ? s : e.name;
+ }
+
+ /**
+ * The description of a security service. It encapsulates the properties
+ * of a service and contains a factory method to obtain new implementation
+ * instances of this service.
+ *
+ * <p>Each service has a provider that offers the service, a type,
+ * an algorithm name, and the name of the class that implements the
+ * service. Optionally, it also includes a list of alternate algorithm
+ * names for this service (aliases) and attributes, which are a map of
+ * (name, value) String pairs.
+ *
+ * <p>This class defines the methods {@link #supportsParameter
+ * supportsParameter()} and {@link #newInstance newInstance()}
+ * which are used by the Java security framework when it searches for
+ * suitable services and instantiates them. The valid arguments to those
+ * methods depend on the type of service. For the service types defined
+ * within Java SE, see the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * Java Cryptography Architecture API Specification & Reference </a>
+ * for the valid values.
+ * Note that components outside of Java SE can define additional types of
+ * services and their behavior.
+ *
+ * <p>Instances of this class are immutable.
+ *
+ * @since 1.5
+ */
+ public static class Service {
+
+ private String type, algorithm, className;
+ private final Provider provider;
+ private List<String> aliases;
+ private Map<UString,String> attributes;
+
+ // Reference to the cached implementation Class object
+ private volatile Reference<Class<?>> classRef;
+
+ // flag indicating whether this service has its attributes for
+ // supportedKeyFormats or supportedKeyClasses set
+ // if null, the values have not been initialized
+ // if TRUE, at least one of supportedFormats/Classes is non null
+ private volatile Boolean hasKeyAttributes;
+
+ // supported encoding formats
+ private String[] supportedFormats;
+
+ // names of the supported key (super) classes
+ private Class[] supportedClasses;
+
+ // whether this service has been registered with the Provider
+ private boolean registered;
+
+ private static final Class<?>[] CLASS0 = new Class<?>[0];
+
+ // this constructor and these methods are used for parsing
+ // the legacy string properties.
+
+ private Service(Provider provider) {
+ this.provider = provider;
+ aliases = Collections.<String>emptyList();
+ attributes = Collections.<UString,String>emptyMap();
+ }
+
+ private boolean isValid() {
+ return (type != null) && (algorithm != null) && (className != null);
+ }
+
+ private void addAlias(String alias) {
+ if (aliases.isEmpty()) {
+ aliases = new ArrayList<String>(2);
+ }
+ aliases.add(alias);
+ }
+
+ void addAttribute(String type, String value) {
+ if (attributes.isEmpty()) {
+ attributes = new HashMap<UString,String>(8);
+ }
+ attributes.put(new UString(type), value);
+ }
+
+ /**
+ * Construct a new service.
+ *
+ * @param provider the provider that offers this service
+ * @param type the type of this service
+ * @param algorithm the algorithm name
+ * @param className the name of the class implementing this service
+ * @param aliases List of aliases or null if algorithm has no aliases
+ * @param attributes Map of attributes or null if this implementation
+ * has no attributes
+ *
+ * @throws NullPointerException if provider, type, algorithm, or
+ * className is null
+ */
+ public Service(Provider provider, String type, String algorithm,
+ String className, List<String> aliases,
+ Map<String,String> attributes) {
+ if ((provider == null) || (type == null) ||
+ (algorithm == null) || (className == null)) {
+ throw new NullPointerException();
+ }
+ this.provider = provider;
+ this.type = getEngineName(type);
+ this.algorithm = algorithm;
+ this.className = className;
+ if (aliases == null) {
+ this.aliases = Collections.<String>emptyList();
+ } else {
+ this.aliases = new ArrayList<String>(aliases);
+ }
+ if (attributes == null) {
+ this.attributes = Collections.<UString,String>emptyMap();
+ } else {
+ this.attributes = new HashMap<UString,String>();
+ for (Map.Entry<String,String> entry : attributes.entrySet()) {
+ this.attributes.put(new UString(entry.getKey()), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Get the type of this service. For example, {@code MessageDigest}.
+ *
+ * @return the type of this service
+ */
+ public final String getType() {
+ return type;
+ }
+
+ /**
+ * Return the name of the algorithm of this service. For example,
+ * {@code SHA-1}.
+ *
+ * @return the algorithm of this service
+ */
+ public final String getAlgorithm() {
+ return algorithm;
+ }
+
+ /**
+ * Return the Provider of this service.
+ *
+ * @return the Provider of this service
+ */
+ public final Provider getProvider() {
+ return provider;
+ }
+
+ /**
+ * Return the name of the class implementing this service.
+ *
+ * @return the name of the class implementing this service
+ */
+ public final String getClassName() {
+ return className;
+ }
+
+ // internal only
+ private final List<String> getAliases() {
+ return aliases;
+ }
+
+ /**
+ * Return the value of the specified attribute or null if this
+ * attribute is not set for this Service.
+ *
+ * @param name the name of the requested attribute
+ *
+ * @return the value of the specified attribute or null if the
+ * attribute is not present
+ *
+ * @throws NullPointerException if name is null
+ */
+ public final String getAttribute(String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ return attributes.get(new UString(name));
+ }
+
+ /**
+ * Return a new instance of the implementation described by this
+ * service. The security provider framework uses this method to
+ * construct implementations. Applications will typically not need
+ * to call it.
+ *
+ * <p>The default implementation uses reflection to invoke the
+ * standard constructor for this type of service.
+ * Security providers can override this method to implement
+ * instantiation in a different way.
+ * For details and the values of constructorParameter that are
+ * valid for the various types of services see the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * Java Cryptography Architecture API Specification &
+ * Reference</a>.
+ *
+ * @param constructorParameter the value to pass to the constructor,
+ * or null if this type of service does not use a constructorParameter.
+ *
+ * @return a new implementation of this service
+ *
+ * @throws InvalidParameterException if the value of
+ * constructorParameter is invalid for this type of service.
+ * @throws NoSuchAlgorithmException if instantiation failed for
+ * any other reason.
+ */
+ public Object newInstance(Object constructorParameter)
+ throws NoSuchAlgorithmException {
+ if (registered == false) {
+ if (provider.getService(type, algorithm) != this) {
+ throw new NoSuchAlgorithmException
+ ("Service not registered with Provider "
+ + provider.getName() + ": " + this);
+ }
+ registered = true;
+ }
+ try {
+ EngineDescription cap = knownEngines.get(type);
+ if (cap == null) {
+ // unknown engine type, use generic code
+ // this is the code path future for non-core
+ // optional packages
+ return newInstanceGeneric(constructorParameter);
+ }
+ if (cap.constructorParameterClassName == null) {
+ if (constructorParameter != null) {
+ throw new InvalidParameterException
+ ("constructorParameter not used with " + type
+ + " engines");
+ }
+ Class<?> clazz = getImplClass();
+ Class<?>[] empty = {};
+ Constructor<?> con = clazz.getConstructor(empty);
+ return con.newInstance();
+ } else {
+ Class<?> paramClass = cap.getConstructorParameterClass();
+ if (constructorParameter != null) {
+ Class<?> argClass = constructorParameter.getClass();
+ if (paramClass.isAssignableFrom(argClass) == false) {
+ throw new InvalidParameterException
+ ("constructorParameter must be instanceof "
+ + cap.constructorParameterClassName.replace('$', '.')
+ + " for engine type " + type);
+ }
+ }
+ Class<?> clazz = getImplClass();
+ Constructor<?> cons = clazz.getConstructor(paramClass);
+ return cons.newInstance(constructorParameter);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ throw e;
+ } catch (InvocationTargetException e) {
+ throw new NoSuchAlgorithmException
+ ("Error constructing implementation (algorithm: "
+ + algorithm + ", provider: " + provider.getName()
+ + ", class: " + className + ")", e.getCause());
+ } catch (Exception e) {
+ throw new NoSuchAlgorithmException
+ ("Error constructing implementation (algorithm: "
+ + algorithm + ", provider: " + provider.getName()
+ + ", class: " + className + ")", e);
+ }
+ }
+
+ // return the implementation Class object for this service
+ private Class<?> getImplClass() throws NoSuchAlgorithmException {
+ try {
+ Reference<Class<?>> ref = classRef;
+ Class<?> clazz = (ref == null) ? null : ref.get();
+ if (clazz == null) {
+ ClassLoader cl = provider.getClass().getClassLoader();
+ if (cl == null) {
+ clazz = Class.forName(className);
+ } else {
+ clazz = cl.loadClass(className);
+ }
+ if (!Modifier.isPublic(clazz.getModifiers())) {
+ throw new NoSuchAlgorithmException
+ ("class configured for " + type + " (provider: " +
+ provider.getName() + ") is not public.");
+ }
+ classRef = new WeakReference<Class<?>>(clazz);
+ }
+ return clazz;
+ } catch (ClassNotFoundException e) {
+ throw new NoSuchAlgorithmException
+ ("class configured for " + type + " (provider: " +
+ provider.getName() + ") cannot be found.", e);
+ }
+ }
+
+ /**
+ * Generic code path for unknown engine types. Call the
+ * no-args constructor if constructorParameter is null, otherwise
+ * use the first matching constructor.
+ */
+ private Object newInstanceGeneric(Object constructorParameter)
+ throws Exception {
+ Class<?> clazz = getImplClass();
+ if (constructorParameter == null) {
+ // create instance with public no-arg constructor if it exists
+ try {
+ Class<?>[] empty = {};
+ Constructor<?> con = clazz.getConstructor(empty);
+ return con.newInstance();
+ } catch (NoSuchMethodException e) {
+ throw new NoSuchAlgorithmException("No public no-arg "
+ + "constructor found in class " + className);
+ }
+ }
+ Class<?> argClass = constructorParameter.getClass();
+ Constructor[] cons = clazz.getConstructors();
+ // find first public constructor that can take the
+ // argument as parameter
+ for (Constructor<?> con : cons) {
+ Class<?>[] paramTypes = con.getParameterTypes();
+ if (paramTypes.length != 1) {
+ continue;
+ }
+ if (paramTypes[0].isAssignableFrom(argClass) == false) {
+ continue;
+ }
+ return con.newInstance(constructorParameter);
+ }
+ throw new NoSuchAlgorithmException("No public constructor matching "
+ + argClass.getName() + " found in class " + className);
+ }
+
+ /**
+ * Test whether this Service can use the specified parameter.
+ * Returns false if this service cannot use the parameter. Returns
+ * true if this service can use the parameter, if a fast test is
+ * infeasible, or if the status is unknown.
+ *
+ * <p>The security provider framework uses this method with
+ * some types of services to quickly exclude non-matching
+ * implementations for consideration.
+ * Applications will typically not need to call it.
+ *
+ * <p>For details and the values of parameter that are valid for the
+ * various types of services see the top of this class and the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * Java Cryptography Architecture API Specification &
+ * Reference</a>.
+ * Security providers can override it to implement their own test.
+ *
+ * @param parameter the parameter to test
+ *
+ * @return false if this this service cannot use the specified
+ * parameter; true if it can possibly use the parameter
+ *
+ * @throws InvalidParameterException if the value of parameter is
+ * invalid for this type of service or if this method cannot be
+ * used with this type of service
+ */
+ public boolean supportsParameter(Object parameter) {
+ EngineDescription cap = knownEngines.get(type);
+ if (cap == null) {
+ // unknown engine type, return true by default
+ return true;
+ }
+ if (cap.supportsParameter == false) {
+ throw new InvalidParameterException("supportsParameter() not "
+ + "used with " + type + " engines");
+ }
+ // allow null for keys without attributes for compatibility
+ if ((parameter != null) && (parameter instanceof Key == false)) {
+ throw new InvalidParameterException
+ ("Parameter must be instanceof Key for engine " + type);
+ }
+ if (hasKeyAttributes() == false) {
+ return true;
+ }
+ if (parameter == null) {
+ return false;
+ }
+ Key key = (Key)parameter;
+ if (supportsKeyFormat(key)) {
+ return true;
+ }
+ if (supportsKeyClass(key)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Return whether this service has its Supported* properties for
+ * keys defined. Parses the attributes if not yet initialized.
+ */
+ private boolean hasKeyAttributes() {
+ Boolean b = hasKeyAttributes;
+ if (b == null) {
+ synchronized (this) {
+ String s;
+ s = getAttribute("SupportedKeyFormats");
+ if (s != null) {
+ supportedFormats = s.split("\\|");
+ }
+ s = getAttribute("SupportedKeyClasses");
+ if (s != null) {
+ String[] classNames = s.split("\\|");
+ List<Class<?>> classList =
+ new ArrayList<>(classNames.length);
+ for (String className : classNames) {
+ Class<?> clazz = getKeyClass(className);
+ if (clazz != null) {
+ classList.add(clazz);
+ }
+ }
+ supportedClasses = classList.toArray(CLASS0);
+ }
+ boolean bool = (supportedFormats != null)
+ || (supportedClasses != null);
+ b = Boolean.valueOf(bool);
+ hasKeyAttributes = b;
+ }
+ }
+ return b.booleanValue();
+ }
+
+ // get the key class object of the specified name
+ private Class<?> getKeyClass(String name) {
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ // ignore
+ }
+ try {
+ ClassLoader cl = provider.getClass().getClassLoader();
+ if (cl != null) {
+ return cl.loadClass(name);
+ }
+ } catch (ClassNotFoundException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ private boolean supportsKeyFormat(Key key) {
+ if (supportedFormats == null) {
+ return false;
+ }
+ String format = key.getFormat();
+ if (format == null) {
+ return false;
+ }
+ for (String supportedFormat : supportedFormats) {
+ if (supportedFormat.equals(format)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean supportsKeyClass(Key key) {
+ if (supportedClasses == null) {
+ return false;
+ }
+ Class<?> keyClass = key.getClass();
+ for (Class<?> clazz : supportedClasses) {
+ if (clazz.isAssignableFrom(keyClass)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return a String representation of this service.
+ *
+ * @return a String representation of this service.
+ */
+ public String toString() {
+ String aString = aliases.isEmpty()
+ ? "" : "\r\n aliases: " + aliases.toString();
+ String attrs = attributes.isEmpty()
+ ? "" : "\r\n attributes: " + attributes.toString();
+ return provider.getName() + ": " + type + "." + algorithm
+ + " -> " + className + aString + attrs + "\r\n";
+ }
+
+ }
+
+ // BEGIN Android-added: Provider registration
+ /**
+ * @hide
+ */
+ public void setRegistered() {
+ registered = true;
+ }
+
+ /**
+ * @hide
+ */
+ public void setUnregistered() {
+ registered = false;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isRegistered() {
+ return registered;
+ }
+
+ /**
+ * Ensure the values cached by {@link #getServices} and {@link #getService} are already computed
+ *
+ * Used by the zygote so that initialization is performed during preload for the providers
+ * available at that point.
+ *
+ * @hide
+ */
+ public synchronized void warmUpServiceProvision() {
+ checkInitialized();
+ // Further calls do nothing if the services didn't change. If not called here, it would
+ // parse legacy strings the first time that a service is requested.
+ ensureLegacyParsed();
+ // This call to getServices will update fields so that further calls will just return a
+ // stored field, if the services didn't change in the meantime.
+ getServices();
+ }
+ // END Android-added: Provider registration
+}
diff --git a/java/security/ProviderException.java b/java/security/ProviderException.java
new file mode 100644
index 0000000..b372ee7
--- /dev/null
+++ b/java/security/ProviderException.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * A runtime exception for Provider exceptions (such as
+ * misconfiguration errors or unrecoverable internal errors),
+ * which may be subclassed by Providers to
+ * throw specialized, provider-specific runtime errors.
+ *
+ * @author Benjamin Renaud
+ */
+public class ProviderException extends RuntimeException {
+
+ private static final long serialVersionUID = 5256023526693665674L;
+
+ /**
+ * Constructs a ProviderException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public ProviderException() {
+ super();
+ }
+
+ /**
+ * Constructs a ProviderException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param s the detail message.
+ */
+ public ProviderException(String s) {
+ super(s);
+ }
+
+ /**
+ * Creates a {@code ProviderException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public ProviderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code ProviderException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public ProviderException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/PublicKey.java b/java/security/PublicKey.java
new file mode 100644
index 0000000..df49807
--- /dev/null
+++ b/java/security/PublicKey.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * <p>A public key. This interface contains no methods or constants.
+ * It merely serves to group (and provide type safety for) all public key
+ * interfaces.
+ *
+ * Note: The specialized public key interfaces extend this interface.
+ * See, for example, the DSAPublicKey interface in
+ * {@code java.security.interfaces}.
+ *
+ * @see Key
+ * @see PrivateKey
+ * @see Certificate
+ * @see Signature#initVerify
+ * @see java.security.interfaces.DSAPublicKey
+ * @see java.security.interfaces.RSAPublicKey
+ *
+ */
+
+public interface PublicKey extends Key {
+ // Declare serialVersionUID to be compatible with JDK1.1
+ /**
+ * The class fingerprint that is set to indicate serialization
+ * compatibility with a previous version of the class.
+ */
+ static final long serialVersionUID = 7187392471159151072L;
+}
diff --git a/java/security/SecureClassLoader.java b/java/security/SecureClassLoader.java
new file mode 100644
index 0000000..145f4fc
--- /dev/null
+++ b/java/security/SecureClassLoader.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.net.URL;
+
+import sun.security.util.Debug;
+
+/**
+ * This class extends ClassLoader with additional support for defining
+ * classes with an associated code source and permissions which are
+ * retrieved by the system policy by default.
+ *
+ * @author Li Gong
+ * @author Roland Schemers
+ */
+public class SecureClassLoader extends ClassLoader {
+ /*
+ * If initialization succeed this is set to true and security checks will
+ * succeed. Otherwise the object is not initialized and the object is
+ * useless.
+ */
+ private final boolean initialized;
+
+ // HashMap that maps CodeSource to ProtectionDomain
+ // @GuardedBy("pdcache")
+ private final HashMap<CodeSource, ProtectionDomain> pdcache =
+ new HashMap<>(11);
+
+ private static final Debug debug = Debug.getInstance("scl");
+
+ static {
+ ClassLoader.registerAsParallelCapable();
+ }
+
+ /**
+ * Creates a new SecureClassLoader using the specified parent
+ * class loader for delegation.
+ *
+ * <p>If there is a security manager, this method first
+ * calls the security manager's {@code checkCreateClassLoader}
+ * method to ensure creation of a class loader is allowed.
+ * <p>
+ * @param parent the parent ClassLoader
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkCreateClassLoader} method doesn't allow
+ * creation of a class loader.
+ * @see SecurityManager#checkCreateClassLoader
+ */
+ protected SecureClassLoader(ClassLoader parent) {
+ super(parent);
+ // this is to make the stack depth consistent with 1.1
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkCreateClassLoader();
+ }
+ initialized = true;
+ }
+
+ /**
+ * Creates a new SecureClassLoader using the default parent class
+ * loader for delegation.
+ *
+ * <p>If there is a security manager, this method first
+ * calls the security manager's {@code checkCreateClassLoader}
+ * method to ensure creation of a class loader is allowed.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkCreateClassLoader} method doesn't allow
+ * creation of a class loader.
+ * @see SecurityManager#checkCreateClassLoader
+ */
+ protected SecureClassLoader() {
+ super();
+ // this is to make the stack depth consistent with 1.1
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkCreateClassLoader();
+ }
+ initialized = true;
+ }
+
+ /**
+ * Converts an array of bytes into an instance of class Class,
+ * with an optional CodeSource. Before the
+ * class can be used it must be resolved.
+ * <p>
+ * If a non-null CodeSource is supplied a ProtectionDomain is
+ * constructed and associated with the class being defined.
+ * <p>
+ * @param name the expected name of the class, or {@code null}
+ * if not known, using '.' and not '/' as the separator
+ * and without a trailing ".class" suffix.
+ * @param b the bytes that make up the class data. The bytes in
+ * positions {@code off} through {@code off+len-1}
+ * should have the format of a valid class file as defined by
+ * <cite>The Java™ Virtual Machine Specification</cite>.
+ * @param off the start offset in {@code b} of the class data
+ * @param len the length of the class data
+ * @param cs the associated CodeSource, or {@code null} if none
+ * @return the {@code Class} object created from the data,
+ * and optional CodeSource.
+ * @exception ClassFormatError if the data did not contain a valid class
+ * @exception IndexOutOfBoundsException if either {@code off} or
+ * {@code len} is negative, or if
+ * {@code off+len} is greater than {@code b.length}.
+ *
+ * @exception SecurityException if an attempt is made to add this class
+ * to a package that contains classes that were signed by
+ * a different set of certificates than this class, or if
+ * the class name begins with "java.".
+ */
+ protected final Class<?> defineClass(String name,
+ byte[] b, int off, int len,
+ CodeSource cs)
+ {
+ return defineClass(name, b, off, len, getProtectionDomain(cs));
+ }
+
+ /**
+ * Converts a {@link java.nio.ByteBuffer ByteBuffer}
+ * into an instance of class {@code Class}, with an optional CodeSource.
+ * Before the class can be used it must be resolved.
+ * <p>
+ * If a non-null CodeSource is supplied a ProtectionDomain is
+ * constructed and associated with the class being defined.
+ * <p>
+ * @param name the expected name of the class, or {@code null}
+ * if not known, using '.' and not '/' as the separator
+ * and without a trailing ".class" suffix.
+ * @param b the bytes that make up the class data. The bytes from positions
+ * {@code b.position()} through {@code b.position() + b.limit() -1}
+ * should have the format of a valid class file as defined by
+ * <cite>The Java™ Virtual Machine Specification</cite>.
+ * @param cs the associated CodeSource, or {@code null} if none
+ * @return the {@code Class} object created from the data,
+ * and optional CodeSource.
+ * @exception ClassFormatError if the data did not contain a valid class
+ * @exception SecurityException if an attempt is made to add this class
+ * to a package that contains classes that were signed by
+ * a different set of certificates than this class, or if
+ * the class name begins with "java.".
+ *
+ * @since 1.5
+ */
+ protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
+ CodeSource cs)
+ {
+ return defineClass(name, b, getProtectionDomain(cs));
+ }
+
+ /**
+ * Returns the permissions for the given CodeSource object.
+ * <p>
+ * This method is invoked by the defineClass method which takes
+ * a CodeSource as an argument when it is constructing the
+ * ProtectionDomain for the class being defined.
+ * <p>
+ * @param codesource the codesource.
+ *
+ * @return the permissions granted to the codesource.
+ *
+ */
+ protected PermissionCollection getPermissions(CodeSource codesource)
+ {
+ check();
+ return new Permissions(); // ProtectionDomain defers the binding
+ }
+
+ /*
+ * Returned cached ProtectionDomain for the specified CodeSource.
+ */
+ private ProtectionDomain getProtectionDomain(CodeSource cs) {
+ if (cs == null)
+ return null;
+
+ ProtectionDomain pd = null;
+ synchronized (pdcache) {
+ pd = pdcache.get(cs);
+ if (pd == null) {
+ PermissionCollection perms = getPermissions(cs);
+ pd = new ProtectionDomain(cs, perms, this, null);
+ pdcache.put(cs, pd);
+ if (debug != null) {
+ debug.println(" getPermissions "+ pd);
+ debug.println("");
+ }
+ }
+ }
+ return pd;
+ }
+
+ /*
+ * Check to make sure the class loader has been initialized.
+ */
+ private void check() {
+ if (!initialized) {
+ throw new SecurityException("ClassLoader object not initialized");
+ }
+ }
+
+}
diff --git a/java/security/SecureRandom.java b/java/security/SecureRandom.java
new file mode 100644
index 0000000..0852cbd
--- /dev/null
+++ b/java/security/SecureRandom.java
@@ -0,0 +1,777 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+import java.util.regex.*;
+
+import java.security.Provider.Service;
+import java.util.function.Function;
+
+import dalvik.system.VMRuntime;
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class provides a cryptographically strong random number
+ * generator (RNG).
+ *
+ * <p>A cryptographically strong random number
+ * minimally complies with the statistical random number generator tests
+ * specified in <a href="http://csrc.nist.gov/cryptval/140-2.htm">
+ * <i>FIPS 140-2, Security Requirements for Cryptographic Modules</i></a>,
+ * section 4.9.1.
+ * Additionally, SecureRandom must produce non-deterministic output.
+ * Therefore any seed material passed to a SecureRandom object must be
+ * unpredictable, and all SecureRandom output sequences must be
+ * cryptographically strong, as described in
+ * <a href="http://www.ietf.org/rfc/rfc1750.txt">
+ * <i>RFC 1750: Randomness Recommendations for Security</i></a>.
+ *
+ * <p>A caller obtains a SecureRandom instance via the
+ * no-argument constructor or one of the {@code getInstance} methods:
+ *
+ * <pre>
+ * SecureRandom random = new SecureRandom();
+ * </pre>
+ *
+ * <p> Many SecureRandom implementations are in the form of a pseudo-random
+ * number generator (PRNG), which means they use a deterministic algorithm
+ * to produce a pseudo-random sequence from a true random seed.
+ * Other implementations may produce true random numbers,
+ * and yet others may use a combination of both techniques.
+ *
+ * <p> Typical callers of SecureRandom invoke the following methods
+ * to retrieve random bytes:
+ *
+ * <pre>
+ * SecureRandom random = new SecureRandom();
+ * byte bytes[] = new byte[20];
+ * random.nextBytes(bytes);
+ * </pre>
+ *
+ * <p> Callers may also invoke the {@code generateSeed} method
+ * to generate a given number of seed bytes (to seed other random number
+ * generators, for example):
+ * <pre>
+ * byte seed[] = random.generateSeed(20);
+ * </pre>
+ *
+ * Note: Depending on the implementation, the {@code generateSeed} and
+ * {@code nextBytes} methods may block as entropy is being gathered,
+ * for example, if they need to read from /dev/random on various Unix-like
+ * operating systems.
+ *
+ * The SHA1PRNG algorithm from the Crypto provider has been deprecated as it was insecure, and also
+ * incorrectly used by some apps as a key derivation function. See
+ * <a href="http://android-developers.blogspot.com/2016/06/security-crypto-provider-deprecated-in.html">
+ * Security "Crypto" provider deprecated in Android N</a> for details.
+ *
+ * @see java.security.SecureRandomSpi
+ * @see java.util.Random
+ *
+ * @author Benjamin Renaud
+ * @author Josh Bloch
+ */
+
+public class SecureRandom extends java.util.Random {
+
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
+ private static final Debug pdebug =
+ Debug.getInstance("provider", "Provider");
+ private static final boolean skipDebug =
+ Debug.isOn("engine=") && !Debug.isOn("securerandom");
+ */
+ // END Android-removed
+
+ /**
+ * The provider.
+ *
+ * @serial
+ * @since 1.2
+ */
+ private Provider provider = null;
+
+ /**
+ * The provider implementation.
+ *
+ * @serial
+ * @since 1.2
+ */
+ private SecureRandomSpi secureRandomSpi = null;
+
+ /*
+ * The algorithm name of null if unknown.
+ *
+ * @serial
+ * @since 1.5
+ */
+ private String algorithm;
+
+ // Seed Generator
+ private static volatile SecureRandom seedGenerator = null;
+
+ /**
+ * Constructs a secure random number generator (RNG) implementing the
+ * default random number algorithm.
+ *
+ * <p> This constructor traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new SecureRandom object encapsulating the
+ * SecureRandomSpi implementation from the first
+ * Provider that supports a SecureRandom (RNG) algorithm is returned.
+ * If none of the Providers support a RNG algorithm,
+ * then an implementation-specific default is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p> See the SecureRandom section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard RNG algorithm names.
+ *
+ * <p> The returned SecureRandom object has not been seeded. To seed the
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
+ * previously called.
+ */
+ public SecureRandom() {
+ /*
+ * This call to our superclass constructor will result in a call
+ * to our own {@code setSeed} method, which will return
+ * immediately when it is passed zero.
+ */
+ super(0);
+ getDefaultPRNG(false, null);
+ }
+
+ /**
+ * Constructs a secure random number generator (RNG) implementing the
+ * default random number algorithm.
+ * The SecureRandom instance is seeded with the specified seed bytes.
+ *
+ * <p> This constructor traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new SecureRandom object encapsulating the
+ * SecureRandomSpi implementation from the first
+ * Provider that supports a SecureRandom (RNG) algorithm is returned.
+ * If none of the Providers support a RNG algorithm,
+ * then an implementation-specific default is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p> See the SecureRandom section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard RNG algorithm names.
+ *
+ * @param seed the seed.
+ */
+ public SecureRandom(byte seed[]) {
+ super(0);
+ getDefaultPRNG(true, seed);
+ }
+
+ private void getDefaultPRNG(boolean setSeed, byte[] seed) {
+ String prng = getPrngAlgorithm();
+ if (prng == null) {
+ // Android-changed: This should never happen, we always provide a SecureRandom
+ throw new IllegalStateException("No SecureRandom implementation!");
+ } else {
+ try {
+ SecureRandom random = SecureRandom.getInstance(prng);
+ this.secureRandomSpi = random.getSecureRandomSpi();
+ this.provider = random.getProvider();
+ if (setSeed) {
+ this.secureRandomSpi.engineSetSeed(seed);
+ }
+ } catch (NoSuchAlgorithmException nsae) {
+ // never happens, because we made sure the algorithm exists
+ throw new RuntimeException(nsae);
+ }
+ }
+ // JDK 1.1 based implementations subclass SecureRandom instead of
+ // SecureRandomSpi. They will also go through this code path because
+ // they must call a SecureRandom constructor as it is their superclass.
+ // If we are dealing with such an implementation, do not set the
+ // algorithm value as it would be inaccurate.
+ if (getClass() == SecureRandom.class) {
+ this.algorithm = prng;
+ }
+ }
+
+ /**
+ * Creates a SecureRandom object.
+ *
+ * @param secureRandomSpi the SecureRandom implementation.
+ * @param provider the provider.
+ */
+ protected SecureRandom(SecureRandomSpi secureRandomSpi,
+ Provider provider) {
+ this(secureRandomSpi, provider, null);
+ }
+
+ private SecureRandom(SecureRandomSpi secureRandomSpi, Provider provider,
+ String algorithm) {
+ super(0);
+ this.secureRandomSpi = secureRandomSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("SecureRandom." + algorithm +
+ " algorithm from: " + this.provider.getName());
+ }
+ */
+ // END Android-removed
+ }
+
+ /**
+ * Returns a SecureRandom object that implements the specified
+ * Random Number Generator (RNG) algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new SecureRandom object encapsulating the
+ * SecureRandomSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p> The returned SecureRandom object has not been seeded. To seed the
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
+ * previously called.
+ *
+ * @param algorithm the name of the RNG algorithm.
+ * See the SecureRandom section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard RNG algorithm names.
+ *
+ * @return the new SecureRandom object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * SecureRandomSpi implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ *
+ * @since 1.2
+ */
+ public static SecureRandom getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("SecureRandom",
+ SecureRandomSpi.class, algorithm);
+ return new SecureRandom((SecureRandomSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ // BEGIN Android-added: Support for Crypto provider workaround
+ /**
+ * Maximum SDK version for which the workaround for the Crypto provider is in place.
+ *
+ * <p> We provide instances from the Crypto provider (although the provider is not installed) to
+ * apps targeting M or earlier versions of the SDK.
+ *
+ * <p> Default is 23 (M). We have it as a field for testability and it shouldn't be changed.
+ *
+ * @hide
+ */
+ public static final int DEFAULT_SDK_TARGET_FOR_CRYPTO_PROVIDER_WORKAROUND = 23;
+
+ private static int sdkTargetForCryptoProviderWorkaround =
+ DEFAULT_SDK_TARGET_FOR_CRYPTO_PROVIDER_WORKAROUND;
+
+ /**
+ * Only for testing.
+ *
+ * @hide
+ */
+ public static void setSdkTargetForCryptoProviderWorkaround(int sdkTargetVersion) {
+ sdkTargetForCryptoProviderWorkaround = sdkTargetVersion;
+ }
+
+ /**
+ * Only for testing.
+ *
+ * @hide
+ */
+ public static int getSdkTargetForCryptoProviderWorkaround() {
+ return sdkTargetForCryptoProviderWorkaround;
+ }
+ // END Android-added: Support for Crypto provider workaround
+
+ /**
+ * Returns a SecureRandom object that implements the specified
+ * Random Number Generator (RNG) algorithm.
+ *
+ * <p> A new SecureRandom object encapsulating the
+ * SecureRandomSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p> The returned SecureRandom object has not been seeded. To seed the
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
+ * previously called.
+ *
+ * @param algorithm the name of the RNG algorithm.
+ * See the SecureRandom section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard RNG algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new SecureRandom object.
+ *
+ * @exception NoSuchAlgorithmException if a SecureRandomSpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ *
+ * @since 1.2
+ */
+ public static SecureRandom getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ try {
+ Instance instance = GetInstance.getInstance("SecureRandom",
+ SecureRandomSpi.class, algorithm, provider);
+ return new SecureRandom((SecureRandomSpi) instance.impl,
+ instance.provider, algorithm);
+ // BEGIN Android-added: Crypto provider deprecation
+ } catch (NoSuchProviderException nspe) {
+ if ("Crypto".equals(provider)) {
+ System.logE(" ********** PLEASE READ ************ ");
+ System.logE(" * ");
+ System.logE(" * New versions of the Android SDK no longer support the Crypto provider.");
+ System.logE(" * If your app was relying on setSeed() to derive keys from strings, you");
+ System.logE(" * should switch to using SecretKeySpec to load raw key bytes directly OR");
+ System.logE(" * use a real key derivation function (KDF). See advice here : ");
+ System.logE(" * http://android-developers.blogspot.com/2016/06/security-crypto-provider-deprecated-in.html ");
+ System.logE(" *********************************** ");
+ if (VMRuntime.getRuntime().getTargetSdkVersion()
+ <= sdkTargetForCryptoProviderWorkaround) {
+ System.logE(" Returning an instance of SecureRandom from the Crypto provider");
+ System.logE(" as a temporary measure so that the apps targeting earlier SDKs");
+ System.logE(" keep working. Please do not rely on the presence of the Crypto");
+ System.logE(" provider in the codebase, as our plan is to delete it");
+ System.logE(" completely in the future.");
+ return getInstanceFromCryptoProvider(algorithm);
+ }
+ }
+
+ throw nspe;
+ }
+ }
+
+ private static SecureRandom getInstanceFromCryptoProvider(String algorithm)
+ throws NoSuchAlgorithmException {
+ Provider cryptoProvider;
+ try {
+ cryptoProvider = (Provider) SecureRandom.class.getClassLoader()
+ .loadClass(
+ "org.apache.harmony.security.provider.crypto.CryptoProvider")
+ .newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ Service service = cryptoProvider.getService("SecureRandom", algorithm);
+ Instance instance = GetInstance.getInstance(service, SecureRandomSpi.class);
+ return new SecureRandom(
+ (SecureRandomSpi) instance.impl, instance.provider, algorithm);
+ }
+ // END Android-added: Crypto provider deprecation
+
+ /**
+ * Returns a SecureRandom object that implements the specified
+ * Random Number Generator (RNG) algorithm.
+ *
+ * <p> A new SecureRandom object encapsulating the
+ * SecureRandomSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * <p> The returned SecureRandom object has not been seeded. To seed the
+ * returned object, call the {@code setSeed} method.
+ * If {@code setSeed} is not called, the first call to
+ * {@code nextBytes} will force the SecureRandom object to seed itself.
+ * This self-seeding will not occur if {@code setSeed} was
+ * previously called.
+ *
+ * @param algorithm the name of the RNG algorithm.
+ * See the SecureRandom section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#SecureRandom">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard RNG algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new SecureRandom object.
+ *
+ * @exception NoSuchAlgorithmException if a SecureRandomSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the specified provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static SecureRandom getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("SecureRandom",
+ SecureRandomSpi.class, algorithm, provider);
+ return new SecureRandom((SecureRandomSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the SecureRandomSpi of this SecureRandom object.
+ */
+ SecureRandomSpi getSecureRandomSpi() {
+ return secureRandomSpi;
+ }
+
+ /**
+ * Returns the provider of this SecureRandom object.
+ *
+ * @return the provider of this SecureRandom object.
+ */
+ public final Provider getProvider() {
+ return provider;
+ }
+
+ /**
+ * Returns the name of the algorithm implemented by this SecureRandom
+ * object.
+ *
+ * @return the name of the algorithm or {@code unknown}
+ * if the algorithm name cannot be determined.
+ * @since 1.5
+ */
+ public String getAlgorithm() {
+ return (algorithm != null) ? algorithm : "unknown";
+ }
+
+ /**
+ * Reseeds this random object. The given seed supplements, rather than
+ * replaces, the existing seed. Thus, repeated calls are guaranteed
+ * never to reduce randomness.
+ *
+ * @param seed the seed.
+ *
+ * @see #getSeed
+ */
+ synchronized public void setSeed(byte[] seed) {
+ secureRandomSpi.engineSetSeed(seed);
+ }
+
+ /**
+ * Reseeds this random object, using the eight bytes contained
+ * in the given {@code long seed}. The given seed supplements,
+ * rather than replaces, the existing seed. Thus, repeated calls
+ * are guaranteed never to reduce randomness.
+ *
+ * <p>This method is defined for compatibility with
+ * {@code java.util.Random}.
+ *
+ * @param seed the seed.
+ *
+ * @see #getSeed
+ */
+ @Override
+ public void setSeed(long seed) {
+ /*
+ * Ignore call from super constructor (as well as any other calls
+ * unfortunate enough to be passing 0). It's critical that we
+ * ignore call from superclass constructor, as digest has not
+ * yet been initialized at that point.
+ */
+ if (seed != 0) {
+ secureRandomSpi.engineSetSeed(longToByteArray(seed));
+ }
+ }
+
+ /**
+ * Generates a user-specified number of random bytes.
+ *
+ * <p> If a call to {@code setSeed} had not occurred previously,
+ * the first call to this method forces this SecureRandom object
+ * to seed itself. This self-seeding will not occur if
+ * {@code setSeed} was previously called.
+ *
+ * @param bytes the array to be filled in with random bytes.
+ */
+ @Override
+ // Android-changed: Added synchronized
+ // This method has been synchronized at least since Cupcake, so it would probably
+ // lead to problems if it was removed.
+ synchronized public void nextBytes(byte[] bytes) {
+ secureRandomSpi.engineNextBytes(bytes);
+ }
+
+ /**
+ * Generates an integer containing the user-specified number of
+ * pseudo-random bits (right justified, with leading zeros). This
+ * method overrides a {@code java.util.Random} method, and serves
+ * to provide a source of random bits to all of the methods inherited
+ * from that class (for example, {@code nextInt},
+ * {@code nextLong}, and {@code nextFloat}).
+ *
+ * @param numBits number of pseudo-random bits to be generated, where
+ * {@code 0 <= numBits <= 32}.
+ *
+ * @return an {@code int} containing the user-specified number
+ * of pseudo-random bits (right justified, with leading zeros).
+ */
+ @Override
+ final protected int next(int numBits) {
+ int numBytes = (numBits+7)/8;
+ byte b[] = new byte[numBytes];
+ int next = 0;
+
+ nextBytes(b);
+ for (int i = 0; i < numBytes; i++) {
+ next = (next << 8) + (b[i] & 0xFF);
+ }
+
+ return next >>> (numBytes*8 - numBits);
+ }
+
+ /**
+ * Returns the given number of seed bytes, computed using the seed
+ * generation algorithm that this class uses to seed itself. This
+ * call may be used to seed other random number generators.
+ *
+ * <p>This method is only included for backwards compatibility.
+ * The caller is encouraged to use one of the alternative
+ * {@code getInstance} methods to obtain a SecureRandom object, and
+ * then call the {@code generateSeed} method to obtain seed bytes
+ * from that object.
+ *
+ * @param numBytes the number of seed bytes to generate.
+ *
+ * @return the seed bytes.
+ *
+ * @see #setSeed
+ */
+ public static byte[] getSeed(int numBytes) {
+ if (seedGenerator == null) {
+ seedGenerator = new SecureRandom();
+ }
+ return seedGenerator.generateSeed(numBytes);
+ }
+
+ /**
+ * Returns the given number of seed bytes, computed using the seed
+ * generation algorithm that this class uses to seed itself. This
+ * call may be used to seed other random number generators.
+ *
+ * @param numBytes the number of seed bytes to generate.
+ *
+ * @return the seed bytes.
+ */
+ public byte[] generateSeed(int numBytes) {
+ return secureRandomSpi.engineGenerateSeed(numBytes);
+ }
+
+ /**
+ * Helper function to convert a long into a byte array (least significant
+ * byte first).
+ */
+ private static byte[] longToByteArray(long l) {
+ byte[] retVal = new byte[8];
+
+ for (int i = 0; i < 8; i++) {
+ retVal[i] = (byte) l;
+ l >>= 8;
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Gets a default PRNG algorithm by looking through all registered
+ * providers. Returns the first PRNG algorithm of the first provider that
+ * has registered a SecureRandom implementation, or null if none of the
+ * registered providers supplies a SecureRandom implementation.
+ */
+ private static String getPrngAlgorithm() {
+ for (Provider p : Providers.getProviderList().providers()) {
+ for (Service s : p.getServices()) {
+ if (s.getType().equals("SecureRandom")) {
+ return s.getAlgorithm();
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Lazily initialize since Pattern.compile() is heavy.
+ * Effective Java (2nd Edition), Item 71.
+ */
+ private static final class StrongPatternHolder {
+ /*
+ * Entries are alg:prov separated by ,
+ * Allow for prepended/appended whitespace between entries.
+ *
+ * Capture groups:
+ * 1 - alg
+ * 2 - :prov (optional)
+ * 3 - prov (optional)
+ * 4 - ,nextEntry (optional)
+ * 5 - nextEntry (optional)
+ */
+ private static Pattern pattern =
+ Pattern.compile(
+ "\\s*([\\S&&[^:,]]*)(\\:([\\S&&[^,]]*))?\\s*(\\,(.*))?");
+ }
+
+ /**
+ * Returns a {@code SecureRandom} object.
+ *
+ * In Android this is equivalent to get a SHA1PRNG from OpenSSLProvider.
+ *
+ * Some situations require strong random values, such as when
+ * creating high-value/long-lived secrets like RSA public/private
+ * keys. To help guide applications in selecting a suitable strong
+ * {@code SecureRandom} implementation, Java distributions
+ * include a list of known strong {@code SecureRandom}
+ * implementations in the {@code securerandom.strongAlgorithms}
+ * Security property.
+ * <p>
+ * Every implementation of the Java platform is required to
+ * support at least one strong {@code SecureRandom} implementation.
+ *
+ * @return a strong {@code SecureRandom} implementation
+ *
+ * @throws NoSuchAlgorithmException if no algorithm is available
+ *
+ * @see Security#getProperty(String)
+ *
+ * @since 1.8
+ */
+ public static SecureRandom getInstanceStrong()
+ throws NoSuchAlgorithmException {
+
+ String property = AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return Security.getProperty(
+ "securerandom.strongAlgorithms");
+ }
+ });
+
+ if ((property == null) || (property.length() == 0)) {
+ throw new NoSuchAlgorithmException(
+ "Null/empty securerandom.strongAlgorithms Security Property");
+ }
+
+ String remainder = property;
+ while (remainder != null) {
+ Matcher m;
+ if ((m = StrongPatternHolder.pattern.matcher(
+ remainder)).matches()) {
+
+ String alg = m.group(1);
+ String prov = m.group(3);
+
+ try {
+ if (prov == null) {
+ return SecureRandom.getInstance(alg);
+ } else {
+ return SecureRandom.getInstance(alg, prov);
+ }
+ } catch (NoSuchAlgorithmException |
+ NoSuchProviderException e) {
+ }
+ remainder = m.group(5);
+ } else {
+ remainder = null;
+ }
+ }
+
+ throw new NoSuchAlgorithmException(
+ "No strong SecureRandom impls available: " + property);
+ }
+
+ // Declare serialVersionUID to be compatible with JDK1.1
+ static final long serialVersionUID = 4940670005562187L;
+
+ // Retain unused values serialized from JDK1.1
+ /**
+ * @serial
+ */
+ private byte[] state;
+ /**
+ * @serial
+ */
+ private MessageDigest digest = null;
+ /**
+ * @serial
+ *
+ * We know that the MessageDigest class does not implement
+ * java.io.Serializable. However, since this field is no longer
+ * used, it will always be NULL and won't affect the serialization
+ * of the SecureRandom class itself.
+ */
+ private byte[] randomBytes;
+ /**
+ * @serial
+ */
+ private int randomBytesUsed;
+ /**
+ * @serial
+ */
+ private long counter;
+}
diff --git a/java/security/SecureRandomSpi.java b/java/security/SecureRandomSpi.java
new file mode 100644
index 0000000..ef6c243
--- /dev/null
+++ b/java/security/SecureRandomSpi.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code SecureRandom} class.
+ * All the abstract methods in this class must be implemented by each
+ * service provider who wishes to supply the implementation
+ * of a cryptographically strong pseudo-random number generator.
+ *
+ *
+ * @see SecureRandom
+ * @since 1.2
+ */
+
+public abstract class SecureRandomSpi implements java.io.Serializable {
+
+ private static final long serialVersionUID = -2991854161009191830L;
+
+ /**
+ * Reseeds this random object. The given seed supplements, rather than
+ * replaces, the existing seed. Thus, repeated calls are guaranteed
+ * never to reduce randomness.
+ *
+ * @param seed the seed.
+ */
+ protected abstract void engineSetSeed(byte[] seed);
+
+ /**
+ * Generates a user-specified number of random bytes.
+ *
+ * <p> If a call to {@code engineSetSeed} had not occurred previously,
+ * the first call to this method forces this SecureRandom implementation
+ * to seed itself. This self-seeding will not occur if
+ * {@code engineSetSeed} was previously called.
+ *
+ * @param bytes the array to be filled in with random bytes.
+ */
+ protected abstract void engineNextBytes(byte[] bytes);
+
+ /**
+ * Returns the given number of seed bytes. This call may be used to
+ * seed other random number generators.
+ *
+ * @param numBytes the number of seed bytes to generate.
+ *
+ * @return the seed bytes.
+ */
+ protected abstract byte[] engineGenerateSeed(int numBytes);
+}
diff --git a/java/security/Security.java b/java/security/Security.java
new file mode 100644
index 0000000..743cf36
--- /dev/null
+++ b/java/security/Security.java
@@ -0,0 +1,1081 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.io.*;
+import sun.security.jca.GetInstance;
+import sun.security.jca.ProviderList;
+import sun.security.jca.Providers;
+
+/**
+ * <p>This class centralizes all security properties and common security
+ * methods. One of its primary uses is to manage providers.
+ *
+ * <p>The default values of security properties are read from an
+ * implementation-specific location, which is typically the properties file
+ * {@code lib/security/java.security} in the Java installation directory.
+ *
+ * @author Benjamin Renaud
+ */
+
+public final class Security {
+
+ // Android-added: Track the version to allow callers know when something has changed.
+ private static final AtomicInteger version = new AtomicInteger();
+
+ // Android-removed: Debug is stubbed and disabled on Android.
+ // /* Are we debugging? -- for developers */
+ // private static final Debug sdebug =
+ // Debug.getInstance("properties");
+
+ /* The java.security properties */
+ // Android-changed: Added final.
+ private static final Properties props;
+
+ // An element in the cache
+ private static class ProviderProperty {
+ String className;
+ Provider provider;
+ }
+
+ static {
+// BEGIN Android-changed: doPrivileged is stubbed on Android.
+// Also, because props is final it must be assigned in the static block, not a method.
+ /*
+ // doPrivileged here because there are multiple
+ // things in initialize that might require privs.
+ // (the FileInputStream call and the File.exists call,
+ // the securityPropFile call, etc)
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ initialize();
+ return null;
+ }
+ });
+ }
+
+ private static void initialize() {
+ */
+// END Android-changed: doPrivileged is stubbed on Android.
+ props = new Properties();
+ boolean loadedProps = false;
+ // BEGIN Android-changed: Use a resource file, Android logging, and only one file.
+ InputStream is = null;
+ try {
+ /*
+ * Android keeps the property file in a resource file.
+ */
+ InputStream propStream = Security.class.getResourceAsStream("security.properties");
+ if (propStream == null) {
+ System.logE("Could not find 'security.properties'.");
+ } else {
+ is = new BufferedInputStream(propStream);
+ props.load(is);
+ loadedProps = true;
+ }
+ } catch (IOException ex) {
+ System.logE("Could not load 'security.properties'", ex);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ignored) {}
+ }
+ }
+ // END Android-changed: Use a resource file, Android logging, and only one file.
+
+ if (!loadedProps) {
+ initializeStatic();
+ }
+ }
+
+ /*
+ * Initialize to default values, if <java.home>/lib/java.security
+ * is not found.
+ */
+ private static void initializeStatic() {
+ // Android-changed: Use Conscrypt and BC, not the sun.security providers.
+ /*
+ props.put("security.provider.1", "sun.security.provider.Sun");
+ props.put("security.provider.2", "sun.security.rsa.SunRsaSign");
+ props.put("security.provider.3", "com.sun.net.ssl.internal.ssl.Provider");
+ props.put("security.provider.4", "com.sun.crypto.provider.SunJCE");
+ props.put("security.provider.5", "sun.security.jgss.SunProvider");
+ props.put("security.provider.6", "com.sun.security.sasl.Provider");
+ */
+ props.put("security.provider.1", "com.android.org.conscrypt.OpenSSLProvider");
+ props.put("security.provider.2", "sun.security.provider.CertPathProvider");
+ props.put("security.provider.3", "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");
+ props.put("security.provider.4", "com.android.org.conscrypt.JSSEProvider");
+ }
+
+ /**
+ * Don't let anyone instantiate this.
+ */
+ private Security() {
+ }
+
+ /**
+ * Looks up providers, and returns the property (and its associated
+ * provider) mapping the key, if any.
+ * The order in which the providers are looked up is the
+ * provider-preference order, as specificed in the security
+ * properties file.
+ */
+ private static ProviderProperty getProviderProperty(String key) {
+ ProviderProperty entry = null;
+
+ List<Provider> providers = Providers.getProviderList().providers();
+ for (int i = 0; i < providers.size(); i++) {
+
+ String matchKey = null;
+ Provider prov = providers.get(i);
+ String prop = prov.getProperty(key);
+
+ if (prop == null) {
+ // Is there a match if we do a case-insensitive property name
+ // comparison? Let's try ...
+ for (Enumeration<Object> e = prov.keys();
+ e.hasMoreElements() && prop == null; ) {
+ matchKey = (String)e.nextElement();
+ if (key.equalsIgnoreCase(matchKey)) {
+ prop = prov.getProperty(matchKey);
+ break;
+ }
+ }
+ }
+
+ if (prop != null) {
+ ProviderProperty newEntry = new ProviderProperty();
+ newEntry.className = prop;
+ newEntry.provider = prov;
+ return newEntry;
+ }
+ }
+
+ return entry;
+ }
+
+ /**
+ * Returns the property (if any) mapping the key for the given provider.
+ */
+ private static String getProviderProperty(String key, Provider provider) {
+ String prop = provider.getProperty(key);
+ if (prop == null) {
+ // Is there a match if we do a case-insensitive property name
+ // comparison? Let's try ...
+ for (Enumeration<Object> e = provider.keys();
+ e.hasMoreElements() && prop == null; ) {
+ String matchKey = (String)e.nextElement();
+ if (key.equalsIgnoreCase(matchKey)) {
+ prop = provider.getProperty(matchKey);
+ break;
+ }
+ }
+ }
+ return prop;
+ }
+
+ /**
+ * Gets a specified property for an algorithm. The algorithm name
+ * should be a standard name. See the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * One possible use is by specialized algorithm parsers, which may map
+ * classes to algorithms which they understand (much like Key parsers
+ * do).
+ *
+ * @param algName the algorithm name.
+ *
+ * @param propName the name of the property to get.
+ *
+ * @return the value of the specified property.
+ *
+ * @deprecated This method used to return the value of a proprietary
+ * property in the master file of the "SUN" Cryptographic Service
+ * Provider in order to determine how to parse algorithm-specific
+ * parameters. Use the new provider-based and algorithm-independent
+ * {@code AlgorithmParameters} and {@code KeyFactory} engine
+ * classes (introduced in the J2SE version 1.2 platform) instead.
+ */
+ @Deprecated
+ public static String getAlgorithmProperty(String algName,
+ String propName) {
+ ProviderProperty entry = getProviderProperty("Alg." + propName
+ + "." + algName);
+ if (entry != null) {
+ return entry.className;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Adds a new provider, at a specified position. The position is
+ * the preference order in which providers are searched for
+ * requested algorithms. The position is 1-based, that is,
+ * 1 is most preferred, followed by 2, and so on.
+ *
+ * <p>If the given provider is installed at the requested position,
+ * the provider that used to be at that position, and all providers
+ * with a position greater than {@code position}, are shifted up
+ * one position (towards the end of the list of installed providers).
+ *
+ * <p>A provider cannot be added if it is already installed.
+ *
+ * <p>If there is a security manager, the
+ * {@link java.lang.SecurityManager#checkSecurityAccess} method is called
+ * with the {@code "insertProvider"} permission target name to see if
+ * it's ok to add a new provider. If this permission check is denied,
+ * {@code checkSecurityAccess} is called again with the
+ * {@code "insertProvider."+provider.getName()} permission target name. If
+ * both checks are denied, a {@code SecurityException} is thrown.
+ *
+ * @param provider the provider to be added.
+ *
+ * @param position the preference position that the caller would
+ * like for this provider.
+ *
+ * @return the actual preference position in which the provider was
+ * added, or -1 if the provider was not added because it is
+ * already installed.
+ *
+ * @throws NullPointerException if provider is null
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to add a new provider
+ *
+ * @see #getProvider
+ * @see #removeProvider
+ * @see java.security.SecurityPermission
+ */
+ public static synchronized int insertProviderAt(Provider provider,
+ int position) {
+ String providerName = provider.getName();
+ // Android-removed: Checks using SecurityManager, which is not functional in Android.
+ // checkInsertProvider(providerName);
+ ProviderList list = Providers.getFullProviderList();
+ ProviderList newList = ProviderList.insertAt(list, provider, position - 1);
+ if (list == newList) {
+ return -1;
+ }
+ // Android-added: Version tracking call.
+ increaseVersion();
+ Providers.setProviderList(newList);
+ return newList.getIndex(providerName) + 1;
+ }
+
+ /**
+ * Adds a provider to the next position available.
+ *
+ * <p>If there is a security manager, the
+ * {@link java.lang.SecurityManager#checkSecurityAccess} method is called
+ * with the {@code "insertProvider"} permission target name to see if
+ * it's ok to add a new provider. If this permission check is denied,
+ * {@code checkSecurityAccess} is called again with the
+ * {@code "insertProvider."+provider.getName()} permission target name. If
+ * both checks are denied, a {@code SecurityException} is thrown.
+ *
+ * @param provider the provider to be added.
+ *
+ * @return the preference position in which the provider was
+ * added, or -1 if the provider was not added because it is
+ * already installed.
+ *
+ * @throws NullPointerException if provider is null
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies access to add a new provider
+ *
+ * @see #getProvider
+ * @see #removeProvider
+ * @see java.security.SecurityPermission
+ */
+ public static int addProvider(Provider provider) {
+ /*
+ * We can't assign a position here because the statically
+ * registered providers may not have been installed yet.
+ * insertProviderAt() will fix that value after it has
+ * loaded the static providers.
+ */
+ return insertProviderAt(provider, 0);
+ }
+
+ /**
+ * Removes the provider with the specified name.
+ *
+ * <p>When the specified provider is removed, all providers located
+ * at a position greater than where the specified provider was are shifted
+ * down one position (towards the head of the list of installed
+ * providers).
+ *
+ * <p>This method returns silently if the provider is not installed or
+ * if name is null.
+ *
+ * <p>First, if there is a security manager, its
+ * {@code checkSecurityAccess}
+ * method is called with the string {@code "removeProvider."+name}
+ * to see if it's ok to remove the provider.
+ * If the default implementation of {@code checkSecurityAccess}
+ * is used (i.e., that method is not overriden), then this will result in
+ * a call to the security manager's {@code checkPermission} method
+ * with a {@code SecurityPermission("removeProvider."+name)}
+ * permission.
+ *
+ * @param name the name of the provider to remove.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkSecurityAccess} method
+ * denies
+ * access to remove the provider
+ *
+ * @see #getProvider
+ * @see #addProvider
+ */
+ public static synchronized void removeProvider(String name) {
+ // Android-removed: Checks using SecurityManager, which is not functional in Android.
+ // check("removeProvider." + name);
+ ProviderList list = Providers.getFullProviderList();
+ ProviderList newList = ProviderList.remove(list, name);
+ Providers.setProviderList(newList);
+ // Android-added: Version tracking call.
+ increaseVersion();
+ }
+
+ /**
+ * Returns an array containing all the installed providers. The order of
+ * the providers in the array is their preference order.
+ *
+ * @return an array of all the installed providers.
+ */
+ public static Provider[] getProviders() {
+ return Providers.getFullProviderList().toArray();
+ }
+
+ /**
+ * Returns the provider installed with the specified name, if
+ * any. Returns null if no provider with the specified name is
+ * installed or if name is null.
+ *
+ * @param name the name of the provider to get.
+ *
+ * @return the provider of the specified name.
+ *
+ * @see #removeProvider
+ * @see #addProvider
+ */
+ public static Provider getProvider(String name) {
+ return Providers.getProviderList().getProvider(name);
+ }
+
+ /**
+ * Returns an array containing all installed providers that satisfy the
+ * specified selection criterion, or null if no such providers have been
+ * installed. The returned providers are ordered
+ * according to their
+ * {@linkplain #insertProviderAt(java.security.Provider, int) preference order}.
+ *
+ * <p> A cryptographic service is always associated with a particular
+ * algorithm or type. For example, a digital signature service is
+ * always associated with a particular algorithm (e.g., DSA),
+ * and a CertificateFactory service is always associated with
+ * a particular certificate type (e.g., X.509).
+ *
+ * <p>The selection criterion must be specified in one of the following two
+ * formats:
+ * <ul>
+ * <li> <i>{@literal <crypto_service>.<algorithm_or_type>}</i>
+ * <p> The cryptographic service name must not contain any dots.
+ * <p> A
+ * provider satisfies the specified selection criterion iff the provider
+ * implements the
+ * specified algorithm or type for the specified cryptographic service.
+ * <p> For example, "CertificateFactory.X.509"
+ * would be satisfied by any provider that supplied
+ * a CertificateFactory implementation for X.509 certificates.
+ * <li> <i>{@literal <crypto_service>.<algorithm_or_type>
+ * <attribute_name>:<attribute_value>}</i>
+ * <p> The cryptographic service name must not contain any dots. There
+ * must be one or more space characters between the
+ * <i>{@literal <algorithm_or_type>}</i> and the
+ * <i>{@literal <attribute_name>}</i>.
+ * <p> A provider satisfies this selection criterion iff the
+ * provider implements the specified algorithm or type for the specified
+ * cryptographic service and its implementation meets the
+ * constraint expressed by the specified attribute name/value pair.
+ * <p> For example, "Signature.SHA1withDSA KeySize:1024" would be
+ * satisfied by any provider that implemented
+ * the SHA1withDSA signature algorithm with a keysize of 1024 (or larger).
+ *
+ * </ul>
+ *
+ * <p> See the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard cryptographic service names, standard
+ * algorithm names and standard attribute names.
+ *
+ * @param filter the criterion for selecting
+ * providers. The filter is case-insensitive.
+ *
+ * @return all the installed providers that satisfy the selection
+ * criterion, or null if no such providers have been installed.
+ *
+ * @throws InvalidParameterException
+ * if the filter is not in the required format
+ * @throws NullPointerException if filter is null
+ *
+ * @see #getProviders(java.util.Map)
+ * @since 1.3
+ */
+ public static Provider[] getProviders(String filter) {
+ String key = null;
+ String value = null;
+ int index = filter.indexOf(':');
+
+ if (index == -1) {
+ key = filter;
+ value = "";
+ } else {
+ key = filter.substring(0, index);
+ value = filter.substring(index + 1);
+ }
+
+ Hashtable<String, String> hashtableFilter = new Hashtable<>(1);
+ hashtableFilter.put(key, value);
+
+ return (getProviders(hashtableFilter));
+ }
+
+ /**
+ * Returns an array containing all installed providers that satisfy the
+ * specified* selection criteria, or null if no such providers have been
+ * installed. The returned providers are ordered
+ * according to their
+ * {@linkplain #insertProviderAt(java.security.Provider, int)
+ * preference order}.
+ *
+ * <p>The selection criteria are represented by a map.
+ * Each map entry represents a selection criterion.
+ * A provider is selected iff it satisfies all selection
+ * criteria. The key for any entry in such a map must be in one of the
+ * following two formats:
+ * <ul>
+ * <li> <i>{@literal <crypto_service>.<algorithm_or_type>}</i>
+ * <p> The cryptographic service name must not contain any dots.
+ * <p> The value associated with the key must be an empty string.
+ * <p> A provider
+ * satisfies this selection criterion iff the provider implements the
+ * specified algorithm or type for the specified cryptographic service.
+ * <li> <i>{@literal <crypto_service>}.
+ * {@literal <algorithm_or_type> <attribute_name>}</i>
+ * <p> The cryptographic service name must not contain any dots. There
+ * must be one or more space characters between the
+ * <i>{@literal <algorithm_or_type>}</i>
+ * and the <i>{@literal <attribute_name>}</i>.
+ * <p> The value associated with the key must be a non-empty string.
+ * A provider satisfies this selection criterion iff the
+ * provider implements the specified algorithm or type for the specified
+ * cryptographic service and its implementation meets the
+ * constraint expressed by the specified attribute name/value pair.
+ * </ul>
+ *
+ * <p> See the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard cryptographic service names, standard
+ * algorithm names and standard attribute names.
+ *
+ * @param filter the criteria for selecting
+ * providers. The filter is case-insensitive.
+ *
+ * @return all the installed providers that satisfy the selection
+ * criteria, or null if no such providers have been installed.
+ *
+ * @throws InvalidParameterException
+ * if the filter is not in the required format
+ * @throws NullPointerException if filter is null
+ *
+ * @see #getProviders(java.lang.String)
+ * @since 1.3
+ */
+ public static Provider[] getProviders(Map<String,String> filter) {
+ // Get all installed providers first.
+ // Then only return those providers who satisfy the selection criteria.
+ Provider[] allProviders = Security.getProviders();
+ Set<String> keySet = filter.keySet();
+ LinkedHashSet<Provider> candidates = new LinkedHashSet<>(5);
+
+ // Returns all installed providers
+ // if the selection criteria is null.
+ if ((keySet == null) || (allProviders == null)) {
+ return allProviders;
+ }
+
+ boolean firstSearch = true;
+
+ // For each selection criterion, remove providers
+ // which don't satisfy the criterion from the candidate set.
+ for (Iterator<String> ite = keySet.iterator(); ite.hasNext(); ) {
+ String key = ite.next();
+ String value = filter.get(key);
+
+ LinkedHashSet<Provider> newCandidates = getAllQualifyingCandidates(key, value,
+ allProviders);
+ if (firstSearch) {
+ candidates = newCandidates;
+ firstSearch = false;
+ }
+
+ if ((newCandidates != null) && !newCandidates.isEmpty()) {
+ // For each provider in the candidates set, if it
+ // isn't in the newCandidate set, we should remove
+ // it from the candidate set.
+ for (Iterator<Provider> cansIte = candidates.iterator();
+ cansIte.hasNext(); ) {
+ Provider prov = cansIte.next();
+ if (!newCandidates.contains(prov)) {
+ cansIte.remove();
+ }
+ }
+ } else {
+ candidates = null;
+ break;
+ }
+ }
+
+ if ((candidates == null) || (candidates.isEmpty()))
+ return null;
+
+ Object[] candidatesArray = candidates.toArray();
+ Provider[] result = new Provider[candidatesArray.length];
+
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (Provider)candidatesArray[i];
+ }
+
+ return result;
+ }
+
+ // Map containing cached Spi Class objects of the specified type
+ private static final Map<String, Class<?>> spiMap =
+ new ConcurrentHashMap<>();
+
+ /**
+ * Return the Class object for the given engine type
+ * (e.g. "MessageDigest"). Works for Spis in the java.security package
+ * only.
+ */
+ private static Class<?> getSpiClass(String type) {
+ Class<?> clazz = spiMap.get(type);
+ if (clazz != null) {
+ return clazz;
+ }
+ try {
+ clazz = Class.forName("java.security." + type + "Spi");
+ spiMap.put(type, clazz);
+ return clazz;
+ } catch (ClassNotFoundException e) {
+ throw new AssertionError("Spi class not found", e);
+ }
+ }
+
+ /*
+ * Returns an array of objects: the first object in the array is
+ * an instance of an implementation of the requested algorithm
+ * and type, and the second object in the array identifies the provider
+ * of that implementation.
+ * The {@code provider} argument can be null, in which case all
+ * configured providers will be searched in order of preference.
+ */
+ static Object[] getImpl(String algorithm, String type, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ if (provider == null) {
+ return GetInstance.getInstance
+ (type, getSpiClass(type), algorithm).toArray();
+ } else {
+ return GetInstance.getInstance
+ (type, getSpiClass(type), algorithm, provider).toArray();
+ }
+ }
+
+ static Object[] getImpl(String algorithm, String type, String provider,
+ Object params) throws NoSuchAlgorithmException,
+ NoSuchProviderException, InvalidAlgorithmParameterException {
+ if (provider == null) {
+ return GetInstance.getInstance
+ (type, getSpiClass(type), algorithm, params).toArray();
+ } else {
+ return GetInstance.getInstance
+ (type, getSpiClass(type), algorithm, params, provider).toArray();
+ }
+ }
+
+ /*
+ * Returns an array of objects: the first object in the array is
+ * an instance of an implementation of the requested algorithm
+ * and type, and the second object in the array identifies the provider
+ * of that implementation.
+ * The {@code provider} argument cannot be null.
+ */
+ static Object[] getImpl(String algorithm, String type, Provider provider)
+ throws NoSuchAlgorithmException {
+ return GetInstance.getInstance
+ (type, getSpiClass(type), algorithm, provider).toArray();
+ }
+
+ static Object[] getImpl(String algorithm, String type, Provider provider,
+ Object params) throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException {
+ return GetInstance.getInstance
+ (type, getSpiClass(type), algorithm, params, provider).toArray();
+ }
+
+ /**
+ * Gets a security property value.
+ *
+ * <p>First, if there is a security manager, its
+ * {@code checkPermission} method is called with a
+ * {@code java.security.SecurityPermission("getProperty."+key)}
+ * permission to see if it's ok to retrieve the specified
+ * security property value..
+ *
+ * @param key the key of the property being retrieved.
+ *
+ * @return the value of the security property corresponding to key.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkPermission} method
+ * denies
+ * access to retrieve the specified security property value
+ * @throws NullPointerException is key is null
+ *
+ * @see #setProperty
+ * @see java.security.SecurityPermission
+ */
+ public static String getProperty(String key) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new SecurityPermission("getProperty."+
+ key));
+ }
+ String name = props.getProperty(key);
+ if (name != null)
+ name = name.trim(); // could be a class name with trailing ws
+ return name;
+ }
+
+ /**
+ * Sets a security property value.
+ *
+ * <p>First, if there is a security manager, its
+ * {@code checkPermission} method is called with a
+ * {@code java.security.SecurityPermission("setProperty."+key)}
+ * permission to see if it's ok to set the specified
+ * security property value.
+ *
+ * @param key the name of the property to be set.
+ *
+ * @param datum the value of the property to be set.
+ *
+ * @throws SecurityException
+ * if a security manager exists and its {@link
+ * java.lang.SecurityManager#checkPermission} method
+ * denies access to set the specified security property value
+ * @throws NullPointerException if key or datum is null
+ *
+ * @see #getProperty
+ * @see java.security.SecurityPermission
+ */
+ public static void setProperty(String key, String datum) {
+ // Android-removed: Checks using SecurityManager, which is not functional in Android.
+ // check("setProperty."+key);
+ props.put(key, datum);
+ // Android-added: Version tracking call.
+ increaseVersion();
+ invalidateSMCache(key); /* See below. */
+ }
+
+ /*
+ * Implementation detail: If the property we just set in
+ * setProperty() was either "package.access" or
+ * "package.definition", we need to signal to the SecurityManager
+ * class that the value has just changed, and that it should
+ * invalidate it's local cache values.
+ *
+ * Rather than create a new API entry for this function,
+ * we use reflection to set a private variable.
+ */
+ private static void invalidateSMCache(String key) {
+
+ final boolean pa = key.equals("package.access");
+ final boolean pd = key.equals("package.definition");
+
+ if (pa || pd) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ try {
+ /* Get the class via the bootstrap class loader. */
+ Class<?> cl = Class.forName(
+ "java.lang.SecurityManager", false, null);
+ Field f = null;
+ boolean accessible = false;
+
+ if (pa) {
+ f = cl.getDeclaredField("packageAccessValid");
+ accessible = f.isAccessible();
+ f.setAccessible(true);
+ } else {
+ f = cl.getDeclaredField("packageDefinitionValid");
+ accessible = f.isAccessible();
+ f.setAccessible(true);
+ }
+ f.setBoolean(f, false);
+ f.setAccessible(accessible);
+ }
+ catch (Exception e1) {
+ /* If we couldn't get the class, it hasn't
+ * been loaded yet. If there is no such
+ * field, we shouldn't try to set it. There
+ * shouldn't be a security execption, as we
+ * are loaded by boot class loader, and we
+ * are inside a doPrivileged() here.
+ *
+ * NOOP: don't do anything...
+ */
+ }
+ return null;
+ } /* run */
+ }); /* PrivilegedAction */
+ } /* if */
+ }
+
+ // BEGIN Android-removed: SecurityManager is stubbed on Android.
+ /*
+ private static void check(String directive) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkSecurityAccess(directive);
+ }
+ }
+
+ private static void checkInsertProvider(String name) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ try {
+ security.checkSecurityAccess("insertProvider");
+ } catch (SecurityException se1) {
+ try {
+ security.checkSecurityAccess("insertProvider." + name);
+ } catch (SecurityException se2) {
+ // throw first exception, but add second to suppressed
+ se1.addSuppressed(se2);
+ throw se1;
+ }
+ }
+ }
+ }
+ */
+ // END Android-removed: SecurityManager is stubbed on Android.
+
+ /*
+ * Returns all providers who satisfy the specified
+ * criterion.
+ */
+ private static LinkedHashSet<Provider> getAllQualifyingCandidates(
+ String filterKey,
+ String filterValue,
+ Provider[] allProviders) {
+ String[] filterComponents = getFilterComponents(filterKey,
+ filterValue);
+
+ // The first component is the service name.
+ // The second is the algorithm name.
+ // If the third isn't null, that is the attrinute name.
+ String serviceName = filterComponents[0];
+ String algName = filterComponents[1];
+ String attrName = filterComponents[2];
+
+ return getProvidersNotUsingCache(serviceName, algName, attrName,
+ filterValue, allProviders);
+ }
+
+ private static LinkedHashSet<Provider> getProvidersNotUsingCache(
+ String serviceName,
+ String algName,
+ String attrName,
+ String filterValue,
+ Provider[] allProviders) {
+ LinkedHashSet<Provider> candidates = new LinkedHashSet<>(5);
+ for (int i = 0; i < allProviders.length; i++) {
+ if (isCriterionSatisfied(allProviders[i], serviceName,
+ algName,
+ attrName, filterValue)) {
+ candidates.add(allProviders[i]);
+ }
+ }
+ return candidates;
+ }
+
+ /*
+ * Returns true if the given provider satisfies
+ * the selection criterion key:value.
+ */
+ private static boolean isCriterionSatisfied(Provider prov,
+ String serviceName,
+ String algName,
+ String attrName,
+ String filterValue) {
+ String key = serviceName + '.' + algName;
+
+ if (attrName != null) {
+ key += ' ' + attrName;
+ }
+ // Check whether the provider has a property
+ // whose key is the same as the given key.
+ String propValue = getProviderProperty(key, prov);
+
+ if (propValue == null) {
+ // Check whether we have an alias instead
+ // of a standard name in the key.
+ String standardName = getProviderProperty("Alg.Alias." +
+ serviceName + "." +
+ algName,
+ prov);
+ if (standardName != null) {
+ key = serviceName + "." + standardName;
+
+ if (attrName != null) {
+ key += ' ' + attrName;
+ }
+
+ propValue = getProviderProperty(key, prov);
+ }
+
+ if (propValue == null) {
+ // The provider doesn't have the given
+ // key in its property list.
+ return false;
+ }
+ }
+
+ // If the key is in the format of:
+ // <crypto_service>.<algorithm_or_type>,
+ // there is no need to check the value.
+
+ if (attrName == null) {
+ return true;
+ }
+
+ // If we get here, the key must be in the
+ // format of <crypto_service>.<algorithm_or_provider> <attribute_name>.
+ if (isStandardAttr(attrName)) {
+ return isConstraintSatisfied(attrName, filterValue, propValue);
+ } else {
+ return filterValue.equalsIgnoreCase(propValue);
+ }
+ }
+
+ /*
+ * Returns true if the attribute is a standard attribute;
+ * otherwise, returns false.
+ */
+ private static boolean isStandardAttr(String attribute) {
+ // For now, we just have two standard attributes:
+ // KeySize and ImplementedIn.
+ if (attribute.equalsIgnoreCase("KeySize"))
+ return true;
+
+ if (attribute.equalsIgnoreCase("ImplementedIn"))
+ return true;
+
+ return false;
+ }
+
+ /*
+ * Returns true if the requested attribute value is supported;
+ * otherwise, returns false.
+ */
+ private static boolean isConstraintSatisfied(String attribute,
+ String value,
+ String prop) {
+ // For KeySize, prop is the max key size the
+ // provider supports for a specific <crypto_service>.<algorithm>.
+ if (attribute.equalsIgnoreCase("KeySize")) {
+ int requestedSize = Integer.parseInt(value);
+ int maxSize = Integer.parseInt(prop);
+ if (requestedSize <= maxSize) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // For Type, prop is the type of the implementation
+ // for a specific <crypto service>.<algorithm>.
+ if (attribute.equalsIgnoreCase("ImplementedIn")) {
+ return value.equalsIgnoreCase(prop);
+ }
+
+ return false;
+ }
+
+ static String[] getFilterComponents(String filterKey, String filterValue) {
+ int algIndex = filterKey.indexOf('.');
+
+ if (algIndex < 0) {
+ // There must be a dot in the filter, and the dot
+ // shouldn't be at the beginning of this string.
+ throw new InvalidParameterException("Invalid filter");
+ }
+
+ String serviceName = filterKey.substring(0, algIndex);
+ String algName = null;
+ String attrName = null;
+
+ if (filterValue.length() == 0) {
+ // The filterValue is an empty string. So the filterKey
+ // should be in the format of <crypto_service>.<algorithm_or_type>.
+ algName = filterKey.substring(algIndex + 1).trim();
+ if (algName.length() == 0) {
+ // There must be a algorithm or type name.
+ throw new InvalidParameterException("Invalid filter");
+ }
+ } else {
+ // The filterValue is a non-empty string. So the filterKey must be
+ // in the format of
+ // <crypto_service>.<algorithm_or_type> <attribute_name>
+ int attrIndex = filterKey.indexOf(' ');
+
+ if (attrIndex == -1) {
+ // There is no attribute name in the filter.
+ throw new InvalidParameterException("Invalid filter");
+ } else {
+ attrName = filterKey.substring(attrIndex + 1).trim();
+ if (attrName.length() == 0) {
+ // There is no attribute name in the filter.
+ throw new InvalidParameterException("Invalid filter");
+ }
+ }
+
+ // There must be an algorithm name in the filter.
+ if ((attrIndex < algIndex) ||
+ (algIndex == attrIndex - 1)) {
+ throw new InvalidParameterException("Invalid filter");
+ } else {
+ algName = filterKey.substring(algIndex + 1, attrIndex);
+ }
+ }
+
+ String[] result = new String[3];
+ result[0] = serviceName;
+ result[1] = algName;
+ result[2] = attrName;
+
+ return result;
+ }
+
+ /**
+ * Returns a Set of Strings containing the names of all available
+ * algorithms or types for the specified Java cryptographic service
+ * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns
+ * an empty Set if there is no provider that supports the
+ * specified service or if serviceName is null. For a complete list
+ * of Java cryptographic services, please see the
+ * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">Java
+ * Cryptography Architecture API Specification & Reference</a>.
+ * Note: the returned set is immutable.
+ *
+ * @param serviceName the name of the Java cryptographic
+ * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore).
+ * Note: this parameter is case-insensitive.
+ *
+ * @return a Set of Strings containing the names of all available
+ * algorithms or types for the specified Java cryptographic service
+ * or an empty set if no provider supports the specified service.
+ *
+ * @since 1.4
+ **/
+ public static Set<String> getAlgorithms(String serviceName) {
+
+ if ((serviceName == null) || (serviceName.length() == 0) ||
+ (serviceName.endsWith("."))) {
+ return Collections.emptySet();
+ }
+
+ HashSet<String> result = new HashSet<>();
+ Provider[] providers = Security.getProviders();
+
+ for (int i = 0; i < providers.length; i++) {
+ // Check the keys for each provider.
+ for (Enumeration<Object> e = providers[i].keys();
+ e.hasMoreElements(); ) {
+ String currentKey =
+ ((String)e.nextElement()).toUpperCase(Locale.ENGLISH);
+ if (currentKey.startsWith(
+ serviceName.toUpperCase(Locale.ENGLISH))) {
+ // We should skip the currentKey if it contains a
+ // whitespace. The reason is: such an entry in the
+ // provider property contains attributes for the
+ // implementation of an algorithm. We are only interested
+ // in entries which lead to the implementation
+ // classes.
+ if (currentKey.indexOf(" ") < 0) {
+ result.add(currentKey.substring(
+ serviceName.length() + 1));
+ }
+ }
+ }
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ // BEGIN Android-added: Methods for version handling.
+ /**
+ * @hide
+ */
+ public static void increaseVersion() {
+ version.incrementAndGet();
+ }
+ /**
+ * @hide
+ */
+ public static int getVersion() {
+ return version.get();
+ }
+ // END Android-added: Methods for version handling.
+}
diff --git a/java/security/SecurityPermission.java b/java/security/SecurityPermission.java
new file mode 100644
index 0000000..f02755c
--- /dev/null
+++ b/java/security/SecurityPermission.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public final class SecurityPermission extends BasicPermission {
+
+ public SecurityPermission(String name) { super(""); }
+ public SecurityPermission(String name, String actions) { super("", ""); }
+}
diff --git a/java/security/Signature.java b/java/security/Signature.java
new file mode 100644
index 0000000..5a0e6a8
--- /dev/null
+++ b/java/security/Signature.java
@@ -0,0 +1,1560 @@
+/*
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (C) 2014 The Android Open Source Project
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.io.*;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import java.nio.ByteBuffer;
+
+import java.security.Provider.Service;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.BadPaddingException;
+import javax.crypto.NoSuchPaddingException;
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * The Signature class is used to provide applications the functionality
+ * of a digital signature algorithm. Digital signatures are used for
+ * authentication and integrity assurance of digital data.
+ *
+ * <p> The signature algorithm can be, among others, the NIST standard
+ * DSA, using DSA and SHA-1. The DSA algorithm using the
+ * SHA-1 message digest algorithm can be specified as {@code SHA1withDSA}.
+ * In the case of RSA, there are multiple choices for the message digest
+ * algorithm, so the signing algorithm could be specified as, for example,
+ * {@code MD2withRSA}, {@code MD5withRSA}, or {@code SHA1withRSA}.
+ * The algorithm name must be specified, as there is no default.
+ *
+ * <p> A Signature object can be used to generate and verify digital
+ * signatures.
+ *
+ * <p> There are three phases to the use of a Signature object for
+ * either signing data or verifying a signature:<ol>
+ *
+ * <li>Initialization, with either
+ *
+ * <ul>
+ *
+ * <li>a public key, which initializes the signature for
+ * verification (see {@link #initVerify(PublicKey) initVerify}), or
+ *
+ * <li>a private key (and optionally a Secure Random Number Generator),
+ * which initializes the signature for signing
+ * (see {@link #initSign(PrivateKey)}
+ * and {@link #initSign(PrivateKey, SecureRandom)}).
+ *
+ * </ul>
+ *
+ * <li>Updating
+ *
+ * <p>Depending on the type of initialization, this will update the
+ * bytes to be signed or verified. See the
+ * {@link #update(byte) update} methods.
+ *
+ * <li>Signing or Verifying a signature on all updated bytes. See the
+ * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
+ * method.
+ *
+ * </ol>
+ *
+ * <p>Note that this class is abstract and extends from
+ * {@code SignatureSpi} for historical reasons.
+ * Application developers should only take notice of the methods defined in
+ * this {@code Signature} class; all the methods in
+ * the superclass are intended for cryptographic service providers who wish to
+ * supply their own implementations of digital signature algorithms.
+ *
+ * <p> Android provides the following {@code Signature} algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>DSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>DSAwithSHA1</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>DSS</td>
+ * <td>1-19</td>
+ * </tr>
+ * <tr>
+ * <td>ECDSA</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>ECDSAwithSHA1</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>MD2withRSA</td>
+ * <td>1-3</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>MD4withRSA</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>MD5withRSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>MD5withRSA/ISO9796-2</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>NONEwithDSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>NONEwithECDSA</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>NONEwithRSA</td>
+ * <td>17+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>RSASSA-PSS</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>SHA1withDSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA1withECDSA</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA1withRSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SHA1withRSA/ISO9796-2</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>SHA1withRSA/PSS</td>
+ * <td>23+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA224withDSA</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA224withECDSA</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA224withRSA</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA224withRSA/PSS</td>
+ * <td>23+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA256withDSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA256withECDSA</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA256withRSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA256withRSA/PSS</td>
+ * <td>23+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA384withECDSA</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA384withRSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA384withRSA/PSS</td>
+ * <td>23+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA512withECDSA</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA512withRSA</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>SHA512withRSA/PSS</td>
+ * <td>23+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * These algorithms are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#Signature">
+ * Signature section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Benjamin Renaud
+ *
+ */
+
+public abstract class Signature extends SignatureSpi {
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ private static final Debug debug =
+ Debug.getInstance("jca", "Signature");
+
+ private static final Debug pdebug =
+ Debug.getInstance("provider", "Provider");
+ private static final boolean skipDebug =
+ Debug.isOn("engine=") && !Debug.isOn("signature");
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ */
+
+ /*
+ * The algorithm for this signature object.
+ * This value is used to map an OID to the particular algorithm.
+ * The mapping is done in AlgorithmObject.algOID(String algorithm)
+ */
+ private String algorithm;
+
+ // The provider
+ Provider provider;
+
+ /**
+ * Possible {@link #state} value, signifying that
+ * this signature object has not yet been initialized.
+ */
+ protected final static int UNINITIALIZED = 0;
+
+ /**
+ * Possible {@link #state} value, signifying that
+ * this signature object has been initialized for signing.
+ */
+ protected final static int SIGN = 2;
+
+ /**
+ * Possible {@link #state} value, signifying that
+ * this signature object has been initialized for verification.
+ */
+ protected final static int VERIFY = 3;
+
+ /**
+ * Current state of this signature object.
+ */
+ protected int state = UNINITIALIZED;
+
+ /**
+ * Creates a Signature object for the specified algorithm.
+ *
+ * @param algorithm the standard string name of the algorithm.
+ * See the Signature section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#Signature">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ */
+ protected Signature(String algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ // name of the special signature alg
+ private final static String RSA_SIGNATURE = "NONEwithRSA";
+
+ // name of the equivalent cipher alg
+ private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
+
+ // all the services we need to lookup for compatibility with Cipher
+ private final static List<ServiceId> rsaIds = Arrays.asList(
+ new ServiceId[] {
+ new ServiceId("Signature", "NONEwithRSA"),
+ new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
+ new ServiceId("Cipher", "RSA/ECB"),
+ new ServiceId("Cipher", "RSA//PKCS1Padding"),
+ new ServiceId("Cipher", "RSA"),
+ }
+ );
+
+ /**
+ * Returns a Signature object that implements the specified signature
+ * algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new Signature object encapsulating the
+ * SignatureSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> 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 algorithm requested.
+ * See the Signature section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#Signature">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return the new Signature object.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * Signature implementation for the
+ * specified algorithm.
+ *
+ * @see Provider
+ */
+ public static Signature getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ List<Service> list;
+ if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
+ list = GetInstance.getServices(rsaIds);
+ } else {
+ list = GetInstance.getServices("Signature", algorithm);
+ }
+ Iterator<Service> t = list.iterator();
+ if (t.hasNext() == false) {
+ throw new NoSuchAlgorithmException
+ (algorithm + " Signature not available");
+ }
+ // try services until we find an Spi or a working Signature subclass
+ NoSuchAlgorithmException failure;
+ do {
+ Service s = t.next();
+ if (isSpi(s)) {
+ // Android-changed: Delegate constructor only takes algorithm.
+ // return new Delegate(s, t, algorithm);
+ return new Delegate(algorithm);
+ } else {
+ // must be a subclass of Signature, disable dynamic selection
+ try {
+ Instance instance =
+ GetInstance.getInstance(s, SignatureSpi.class);
+ return getInstance(instance, algorithm);
+ } catch (NoSuchAlgorithmException e) {
+ failure = e;
+ }
+ }
+ } while (t.hasNext());
+ throw failure;
+ }
+
+ private static Signature getInstance(Instance instance, String algorithm) {
+ Signature sig;
+ if (instance.impl instanceof Signature) {
+ sig = (Signature)instance.impl;
+ sig.algorithm = algorithm;
+ } else {
+ SignatureSpi spi = (SignatureSpi)instance.impl;
+ sig = new Delegate(spi, algorithm);
+ }
+ sig.provider = instance.provider;
+ return sig;
+ }
+
+ private final static Map<String,Boolean> signatureInfo;
+
+ static {
+ signatureInfo = new ConcurrentHashMap<String,Boolean>();
+ Boolean TRUE = Boolean.TRUE;
+ // pre-initialize with values for our SignatureSpi implementations
+ signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
+ signatureInfo.put("sun.security.provider.DSA$SHA1withDSA", TRUE);
+ signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA", TRUE);
+ signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA", TRUE);
+ signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA", TRUE);
+ signatureInfo.put("sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
+ signatureInfo.put("sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
+ signatureInfo.put("sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
+ signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature", TRUE);
+ signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
+ }
+
+ private static boolean isSpi(Service s) {
+ if (s.getType().equals("Cipher")) {
+ // must be a CipherSpi, which we can wrap with the CipherAdapter
+ return true;
+ }
+ String className = s.getClassName();
+ Boolean result = signatureInfo.get(className);
+ if (result == null) {
+ try {
+ Object instance = s.newInstance(null);
+ // Signature extends SignatureSpi
+ // so it is a "real" Spi if it is an
+ // instance of SignatureSpi but not Signature
+ boolean r = (instance instanceof SignatureSpi)
+ && (instance instanceof Signature == false);
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if ((debug != null) && (r == false)) {
+ debug.println("Not a SignatureSpi " + className);
+ debug.println("Delayed provider selection may not be "
+ + "available for algorithm " + s.getAlgorithm());
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ result = Boolean.valueOf(r);
+ signatureInfo.put(className, result);
+ } catch (Exception e) {
+ // something is wrong, assume not an SPI
+ return false;
+ }
+ }
+ return result.booleanValue();
+ }
+
+ /**
+ * Returns a Signature object that implements the specified signature
+ * algorithm.
+ *
+ * <p> A new Signature object encapsulating the
+ * SignatureSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the algorithm requested.
+ * See the Signature section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#Signature">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return the new Signature object.
+ *
+ * @exception NoSuchAlgorithmException if a SignatureSpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see Provider
+ */
+ public static Signature getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
+ // exception compatibility with existing code
+ 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 getInstanceRSA(p);
+ }
+ Instance instance = GetInstance.getInstance
+ ("Signature", SignatureSpi.class, algorithm, provider);
+ return getInstance(instance, algorithm);
+ }
+
+ /**
+ * Returns a Signature object that implements the specified
+ * signature algorithm.
+ *
+ * <p> A new Signature object encapsulating the
+ * SignatureSpi 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 name of the algorithm requested.
+ * See the Signature section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#Signature">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return the new Signature object.
+ *
+ * @exception NoSuchAlgorithmException if a SignatureSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the provider is null.
+ *
+ * @see Provider
+ *
+ * @since 1.4
+ */
+ public static Signature getInstance(String algorithm, Provider provider)
+ throws NoSuchAlgorithmException {
+ if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
+ // exception compatibility with existing code
+ if (provider == null) {
+ throw new IllegalArgumentException("missing provider");
+ }
+ return getInstanceRSA(provider);
+ }
+ Instance instance = GetInstance.getInstance
+ ("Signature", SignatureSpi.class, algorithm, provider);
+ return getInstance(instance, algorithm);
+ }
+
+ // return an implementation for NONEwithRSA, which is a special case
+ // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper
+ private static Signature getInstanceRSA(Provider p)
+ throws NoSuchAlgorithmException {
+ // try Signature first
+ Service s = p.getService("Signature", RSA_SIGNATURE);
+ if (s != null) {
+ Instance instance = GetInstance.getInstance(s, SignatureSpi.class);
+ return getInstance(instance, RSA_SIGNATURE);
+ }
+ // check Cipher
+ try {
+ Cipher c = Cipher.getInstance(RSA_CIPHER, p);
+ return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
+ } catch (GeneralSecurityException e) {
+ // throw Signature style exception message to avoid confusion,
+ // but append Cipher exception as cause
+ throw new NoSuchAlgorithmException("no such algorithm: "
+ + RSA_SIGNATURE + " for provider " + p.getName(), e);
+ }
+ }
+
+ /**
+ * Returns the provider of this signature object.
+ *
+ * @return the provider of this signature object
+ */
+ public final Provider getProvider() {
+ chooseFirstProvider();
+ return this.provider;
+ }
+
+ void chooseFirstProvider() {
+ // empty, overridden in Delegate
+ }
+
+ /**
+ * Initializes this object for verification. If this method is called
+ * again with a different argument, it negates the effect
+ * of this call.
+ *
+ * @param publicKey the public key of the identity whose signature is
+ * going to be verified.
+ *
+ * @exception InvalidKeyException if the key is invalid.
+ */
+ public final void initVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ engineInitVerify(publicKey);
+ state = VERIFY;
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " verification algorithm from: " + this.provider.getName());
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ }
+
+ /**
+ * Initializes this object for verification, using the public key from
+ * the given certificate.
+ * <p>If the certificate is of type X.509 and has a <i>key usage</i>
+ * extension field marked as critical, and the value of the <i>key usage</i>
+ * extension field implies that the public key in
+ * the certificate and its corresponding private key are not
+ * supposed to be used for digital signatures, an
+ * {@code InvalidKeyException} is thrown.
+ *
+ * @param certificate the certificate of the identity whose signature is
+ * going to be verified.
+ *
+ * @exception InvalidKeyException if the public key in the certificate
+ * is not encoded properly or does not include required parameter
+ * information or cannot be used for digital signature purposes.
+ * @since 1.3
+ */
+ public final void initVerify(Certificate certificate)
+ throws InvalidKeyException {
+ // If the certificate is of type X509Certificate,
+ // we should check whether it has a Key Usage
+ // extension marked as critical.
+ if (certificate instanceof java.security.cert.X509Certificate) {
+ // Check whether the cert has a key usage extension
+ // marked as a critical extension.
+ // The OID for KeyUsage extension is 2.5.29.15.
+ X509Certificate cert = (X509Certificate)certificate;
+ Set<String> critSet = cert.getCriticalExtensionOIDs();
+
+ if (critSet != null && !critSet.isEmpty()
+ && critSet.contains("2.5.29.15")) {
+ boolean[] keyUsageInfo = cert.getKeyUsage();
+ // keyUsageInfo[0] is for digitalSignature.
+ if ((keyUsageInfo != null) && (keyUsageInfo[0] == false))
+ throw new InvalidKeyException("Wrong key usage");
+ }
+ }
+
+ PublicKey publicKey = certificate.getPublicKey();
+ engineInitVerify(publicKey);
+ state = VERIFY;
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " verification algorithm from: " + this.provider.getName());
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ }
+
+ /**
+ * Initialize this object for signing. If this method is called
+ * again with a different argument, it negates the effect
+ * of this call.
+ *
+ * @param privateKey the private key of the identity whose signature
+ * is going to be generated.
+ *
+ * @exception InvalidKeyException if the key is invalid.
+ */
+ public final void initSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ engineInitSign(privateKey);
+ state = SIGN;
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " signing algorithm from: " + this.provider.getName());
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ }
+
+ /**
+ * Initialize this object for signing. If this method is called
+ * again with a different argument, it negates the effect
+ * of this call.
+ *
+ * @param privateKey the private key of the identity whose signature
+ * is going to be generated.
+ *
+ * @param random the source of randomness for this signature.
+ *
+ * @exception InvalidKeyException if the key is invalid.
+ */
+ public final void initSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException {
+ engineInitSign(privateKey, random);
+ state = SIGN;
+
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (!skipDebug && pdebug != null) {
+ pdebug.println("Signature." + algorithm +
+ " signing algorithm from: " + this.provider.getName());
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ }
+
+ /**
+ * Returns the signature bytes of all the data updated.
+ * The format of the signature depends on the underlying
+ * signature scheme.
+ *
+ * <p>A call to this method resets this signature object to the state
+ * it was in when previously initialized for signing via a
+ * call to {@code initSign(PrivateKey)}. That is, the object is
+ * reset and available to generate another signature from the same
+ * signer, if desired, via new calls to {@code update} and
+ * {@code sign}.
+ *
+ * @return the signature bytes of the signing operation's result.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly or if this signature algorithm is unable to
+ * process the input data provided.
+ */
+ public final byte[] sign() throws SignatureException {
+ if (state == SIGN) {
+ return engineSign();
+ }
+ throw new SignatureException("object not initialized for " +
+ "signing");
+ }
+
+ /**
+ * Finishes the signature operation and stores the resulting signature
+ * bytes in the provided buffer {@code outbuf}, starting at
+ * {@code offset}.
+ * The format of the signature depends on the underlying
+ * signature scheme.
+ *
+ * <p>This signature object is reset to its initial state (the state it
+ * was in after a call to one of the {@code initSign} methods) and
+ * can be reused to generate further signatures with the same private key.
+ *
+ * @param outbuf buffer for the signature result.
+ *
+ * @param offset offset into {@code outbuf} where the signature is
+ * stored.
+ *
+ * @param len number of bytes within {@code outbuf} allotted for the
+ * signature.
+ *
+ * @return the number of bytes placed into {@code outbuf}.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly, if this signature algorithm is unable to
+ * process the input data provided, or if {@code len} is less
+ * than the actual signature length.
+ *
+ * @since 1.2
+ */
+ public final int sign(byte[] outbuf, int offset, int len)
+ throws SignatureException {
+ if (outbuf == null) {
+ throw new IllegalArgumentException("No output buffer given");
+ }
+ if (offset < 0 || len < 0) {
+ throw new IllegalArgumentException("offset or len is less than 0");
+ }
+ if (outbuf.length - offset < len) {
+ throw new IllegalArgumentException
+ ("Output buffer too small for specified offset and length");
+ }
+ if (state != SIGN) {
+ throw new SignatureException("object not initialized for " +
+ "signing");
+ }
+ return engineSign(outbuf, offset, len);
+ }
+
+ /**
+ * Verifies the passed-in signature.
+ *
+ * <p>A call to this method resets this signature object to the state
+ * it was in when previously initialized for verification via a
+ * call to {@code initVerify(PublicKey)}. That is, the object is
+ * reset and available to verify another signature from the identity
+ * whose public key was specified in the call to {@code initVerify}.
+ *
+ * @param signature the signature bytes to be verified.
+ *
+ * @return true if the signature was verified, false if not.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly, the passed-in signature is improperly
+ * encoded or of the wrong type, if this signature algorithm is unable to
+ * process the input data provided, etc.
+ */
+ public final boolean verify(byte[] signature) throws SignatureException {
+ if (state == VERIFY) {
+ return engineVerify(signature);
+ }
+ throw new SignatureException("object not initialized for " +
+ "verification");
+ }
+
+ /**
+ * Verifies the passed-in signature in the specified array
+ * of bytes, starting at the specified offset.
+ *
+ * <p>A call to this method resets this signature object to the state
+ * it was in when previously initialized for verification via a
+ * call to {@code initVerify(PublicKey)}. That is, the object is
+ * reset and available to verify another signature from the identity
+ * whose public key was specified in the call to {@code initVerify}.
+ *
+ *
+ * @param signature the signature bytes to be verified.
+ * @param offset the offset to start from in the array of bytes.
+ * @param length the number of bytes to use, starting at offset.
+ *
+ * @return true if the signature was verified, false if not.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly, the passed-in signature is improperly
+ * encoded or of the wrong type, if this signature algorithm is unable to
+ * process the input data provided, etc.
+ * @exception IllegalArgumentException if the {@code signature}
+ * byte array is null, or the {@code offset} or {@code length}
+ * is less than 0, or the sum of the {@code offset} and
+ * {@code length} is greater than the length of the
+ * {@code signature} byte array.
+ * @since 1.4
+ */
+ public final boolean verify(byte[] signature, int offset, int length)
+ throws SignatureException {
+ if (state == VERIFY) {
+ if (signature == null) {
+ throw new IllegalArgumentException("signature is null");
+ }
+ if (offset < 0 || length < 0) {
+ throw new IllegalArgumentException
+ ("offset or length is less than 0");
+ }
+ if (signature.length - offset < length) {
+ throw new IllegalArgumentException
+ ("signature too small for specified offset and length");
+ }
+
+ return engineVerify(signature, offset, length);
+ }
+ throw new SignatureException("object not initialized for " +
+ "verification");
+ }
+
+ /**
+ * Updates the data to be signed or verified by a byte.
+ *
+ * @param b the byte to use for the update.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly.
+ */
+ public final void update(byte b) throws SignatureException {
+ if (state == VERIFY || state == SIGN) {
+ engineUpdate(b);
+ } else {
+ throw new SignatureException("object not initialized for "
+ + "signature or verification");
+ }
+ }
+
+ /**
+ * Updates the data to be signed or verified, using the specified
+ * array of bytes.
+ *
+ * @param data the byte array to use for the update.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly.
+ */
+ public final void update(byte[] data) throws SignatureException {
+ update(data, 0, data.length);
+ }
+
+ /**
+ * Updates the data to be signed or verified, using the specified
+ * array of bytes, starting at the specified offset.
+ *
+ * @param data the array of bytes.
+ * @param off the offset to start from in the array of bytes.
+ * @param len the number of bytes to use, starting at offset.
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly.
+ */
+ public final void update(byte[] data, int off, int len)
+ throws SignatureException {
+ if (state == SIGN || state == VERIFY) {
+ if (data == null) {
+ throw new IllegalArgumentException("data is null");
+ }
+ if (off < 0 || len < 0) {
+ throw new IllegalArgumentException("off or len is less than 0");
+ }
+ if (data.length - off < len) {
+ throw new IllegalArgumentException
+ ("data too small for specified offset and length");
+ }
+ engineUpdate(data, off, len);
+ } else {
+ throw new SignatureException("object not initialized for "
+ + "signature or verification");
+ }
+ }
+
+ /**
+ * Updates the data to be signed or verified using the specified
+ * ByteBuffer. Processes the {@code data.remaining()} bytes
+ * starting at at {@code data.position()}.
+ * Upon return, the buffer's position will be equal to its limit;
+ * its limit will not have changed.
+ *
+ * @param data the ByteBuffer
+ *
+ * @exception SignatureException if this signature object is not
+ * initialized properly.
+ * @since 1.5
+ */
+ public final void update(ByteBuffer data) throws SignatureException {
+ if ((state != SIGN) && (state != VERIFY)) {
+ throw new SignatureException("object not initialized for "
+ + "signature or verification");
+ }
+ if (data == null) {
+ throw new NullPointerException();
+ }
+ engineUpdate(data);
+ }
+
+ /**
+ * Returns the name of the algorithm for this signature object.
+ *
+ * @return the name of the algorithm for this signature object.
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Returns a string representation of this signature object,
+ * providing information that includes the state of the object
+ * and the name of the algorithm used.
+ *
+ * @return a string representation of this signature object.
+ */
+ public String toString() {
+ String initState = "";
+ switch (state) {
+ case UNINITIALIZED:
+ initState = "<not initialized>";
+ break;
+ case VERIFY:
+ initState = "<initialized for verifying>";
+ break;
+ case SIGN:
+ initState = "<initialized for signing>";
+ break;
+ }
+ return "Signature object: " + getAlgorithm() + initState;
+ }
+
+ /**
+ * Sets the specified algorithm parameter to the specified value.
+ * This method supplies a general-purpose mechanism through
+ * which it is possible to set the various parameters of this object.
+ * A parameter may be any settable parameter for the algorithm, such as
+ * a parameter size, or a source of random bits for signature generation
+ * (if appropriate), or an indication of whether or not to perform
+ * a specific but optional computation. A uniform algorithm-specific
+ * naming scheme for each parameter is desirable but left unspecified
+ * at this time.
+ *
+ * @param param the string identifier of the parameter.
+ * @param value the parameter value.
+ *
+ * @exception InvalidParameterException if {@code param} is an
+ * invalid parameter for this signature algorithm engine,
+ * the parameter is already set
+ * and cannot be set again, a security exception occurs, and so on.
+ *
+ * @see #getParameter
+ *
+ * @deprecated Use
+ * {@link #setParameter(java.security.spec.AlgorithmParameterSpec)
+ * setParameter}.
+ */
+ @Deprecated
+ public final void setParameter(String param, Object value)
+ throws InvalidParameterException {
+ engineSetParameter(param, value);
+ }
+
+ /**
+ * Initializes this signature engine with the specified parameter set.
+ *
+ * @param params the parameters
+ *
+ * @exception InvalidAlgorithmParameterException if the given parameters
+ * are inappropriate for this signature engine
+ *
+ * @see #getParameters
+ */
+ public final void setParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ engineSetParameter(params);
+ }
+
+ /**
+ * Returns the parameters used with this signature object.
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this signature, or may contain a combination of default and randomly
+ * generated parameter values used by the underlying signature
+ * implementation if this signature requires algorithm parameters but
+ * was not initialized with any.
+ *
+ * @return the parameters used with this signature, or null if this
+ * signature does not use any parameters.
+ *
+ * @see #setParameter(AlgorithmParameterSpec)
+ * @since 1.4
+ */
+ public final AlgorithmParameters getParameters() {
+ return engineGetParameters();
+ }
+
+ /**
+ * Gets the value of the specified algorithm parameter. This method
+ * supplies a general-purpose mechanism through which it is possible to
+ * get the various parameters of this object. A parameter may be any
+ * settable parameter for the algorithm, such as a parameter size, or
+ * a source of random bits for signature generation (if appropriate),
+ * or an indication of whether or not to perform a specific but optional
+ * computation. A uniform algorithm-specific naming scheme for each
+ * parameter is desirable but left unspecified at this time.
+ *
+ * @param param the string name of the parameter.
+ *
+ * @return the object that represents the parameter value, or null if
+ * there is none.
+ *
+ * @exception InvalidParameterException if {@code param} is an invalid
+ * parameter for this engine, or another exception occurs while
+ * trying to get this parameter.
+ *
+ * @see #setParameter(String, Object)
+ *
+ * @deprecated Deprecated.
+ */
+ @Deprecated
+ // Android-changed: add "Deprecated."
+ public final Object getParameter(String param)
+ throws InvalidParameterException {
+ return engineGetParameter(param);
+ }
+
+ /**
+ * 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 {@code Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ if (this instanceof Cloneable) {
+ return super.clone();
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+ // BEGIN Android-added: Allow access to the current SPI for testing purposes.
+ /**
+ * Returns the {@code SignatureSpi} backing this {@code Signature}.
+ *
+ * @hide
+ */
+ public SignatureSpi getCurrentSpi() {
+ return null;
+ }
+ // END Android-added: Allow access to the current SPI for testing purposes.
+
+ /*
+ * The following class allows providers to extend from SignatureSpi
+ * rather than from Signature. It represents a Signature with an
+ * encapsulated, provider-supplied SPI object (of type SignatureSpi).
+ * If the provider implementation is an instance of SignatureSpi, the
+ * getInstance() methods above return an instance of this class, with
+ * the SPI object encapsulated.
+ *
+ * Note: All SPI methods from the original Signature class have been
+ * moved up the hierarchy into a new class (SignatureSpi), which has
+ * been interposed in the hierarchy between the API (Signature)
+ * and its original parent (Object).
+ */
+
+ @SuppressWarnings("deprecation")
+ private static class Delegate extends Signature {
+
+ // The provider implementation (delegate)
+ // filled in once the provider is selected
+ // BEGIN Android-note: Note on sigSpi invariants.
+ // (Not necessarily Android specific)
+ // Invariant to be preserved: sigSpi cannot be changed once it was assigned to something
+ // different than null and lock is null. That is only the case when sigSpi is specified
+ // in the constructor.
+ // END Android-note: Note on sigSpi invariants.
+ private SignatureSpi sigSpi;
+
+ // lock for mutex during provider selection
+ private final Object lock;
+
+ // BEGIN Android-removed: Redo the provider selection logic to allow reselecting provider.
+ // When only the algorithm is specified, we want to allow the Signature provider for that
+ // algorithm to change if multiple providers exist and they support different subsets of
+ // keys. To that end, we don't hold an iterator and exhaust it when we need to choose
+ // a provider like the upstream implementation, we reestablish the list of providers
+ // each time.
+ /*
+ // 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<Service> serviceIterator;
+ */
+ // END Android-removed: Redo the provider selection logic to allow reselecting provider.
+
+ // constructor
+ Delegate(SignatureSpi sigSpi, String algorithm) {
+ super(algorithm);
+ this.sigSpi = sigSpi;
+ this.lock = null; // no lock needed
+ }
+
+ // used with delayed provider selection
+ // Android-changed: Remove Service and Iterator from constructor args.
+ Delegate(String algorithm) {
+ super(algorithm);
+ this.lock = new Object();
+ }
+
+ /**
+ * Returns a clone if the delegate is cloneable.
+ *
+ * @return a clone if the delegate is cloneable.
+ *
+ * @exception CloneNotSupportedException if this is called on a
+ * delegate that does not support {@code Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ chooseFirstProvider();
+ if (sigSpi instanceof Cloneable) {
+ SignatureSpi sigSpiClone = (SignatureSpi)sigSpi.clone();
+ // Because 'algorithm' and 'provider' are private
+ // members of our supertype, we must perform a cast to
+ // access them.
+ Signature that =
+ new Delegate(sigSpiClone, ((Signature)this).algorithm);
+ that.provider = ((Signature)this).provider;
+ return that;
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+
+ private static SignatureSpi newInstance(Service s)
+ throws NoSuchAlgorithmException {
+ if (s.getType().equals("Cipher")) {
+ // must be NONEwithRSA
+ try {
+ Cipher c = Cipher.getInstance(RSA_CIPHER, s.getProvider());
+ return new CipherAdapter(c);
+ } catch (NoSuchPaddingException e) {
+ throw new NoSuchAlgorithmException(e);
+ }
+ } else {
+ Object o = s.newInstance(null);
+ if (o instanceof SignatureSpi == false) {
+ throw new NoSuchAlgorithmException
+ ("Not a SignatureSpi: " + o.getClass().getName());
+ }
+ return (SignatureSpi)o;
+ }
+ }
+
+ // 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 initSign()/
+ * initVerify() is not the first method called.
+ */
+ void chooseFirstProvider() {
+ if (sigSpi != null) {
+ return;
+ }
+ synchronized (lock) {
+ if (sigSpi != null) {
+ return;
+ }
+ // BEGIN Android-removed: this debugging mechanism is not supported in Android.
+ /*
+ if (debug != null) {
+ int w = --warnCount;
+ if (w >= 0) {
+ debug.println("Signature.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();
+ }
+ }
+ */
+ // END Android-removed: this debugging mechanism is not supported in Android.
+ Exception lastException = null;
+// BEGIN Android-changed: Provider selection; loop over a new list each time.
+ List<Service> list;
+ if (((Signature)this).algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
+ list = GetInstance.getServices(rsaIds);
+ } else {
+ list = GetInstance.getServices("Signature",
+ ((Signature)this).algorithm);
+ }
+ for (Service s : list) {
+// END Android-changed: Provider selection; loop over a new list each time.
+ if (isSpi(s) == false) {
+ continue;
+ }
+ try {
+ sigSpi = newInstance(s);
+ provider = s.getProvider();
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ // not needed any more
+ firstService = null;
+ serviceIterator = null;
+ */
+ return;
+ } catch (NoSuchAlgorithmException e) {
+ lastException = e;
+ }
+ }
+ ProviderException e = new ProviderException
+ ("Could not construct SignatureSpi instance");
+ if (lastException != null) {
+ e.initCause(lastException);
+ }
+ throw e;
+ }
+ }
+
+ private void chooseProvider(int type, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ synchronized (lock) {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
+ if (sigSpi != null && key == null) {
+ init(sigSpi, type, key, random);
+ return;
+ }
+ Exception lastException = null;
+// BEGIN Android-changed: Provider selection; loop over a new list each time.
+ List<Service> list;
+ if (((Signature)this).algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
+ list = GetInstance.getServices(rsaIds);
+ } else {
+ list = GetInstance.getServices("Signature",
+ ((Signature)this).algorithm);
+ }
+ for (Service s : list) {
+// END Android-changed: Provider selection; loop over a new list each time.
+ // if provider says it does not support this key, ignore it
+ if (s.supportsParameter(key) == false) {
+ continue;
+ }
+ // if instance is not a SignatureSpi, ignore it
+ if (isSpi(s) == false) {
+ continue;
+ }
+ try {
+ SignatureSpi spi = newInstance(s);
+ init(spi, type, key, random);
+ provider = s.getProvider();
+ sigSpi = spi;
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ firstService = null;
+ serviceIterator = null;
+ */
+ return;
+ } catch (Exception e) {
+ // NoSuchAlgorithmException from newInstance()
+ // InvalidKeyException from init()
+ // RuntimeException (ProviderException) from init()
+ if (lastException == null) {
+ lastException = e;
+ }
+ // Android-added: Throw InvalidKeyException immediately.
+ if (lastException instanceof InvalidKeyException) {
+ throw (InvalidKeyException)lastException;
+ }
+ }
+ }
+ // no working provider found, fail
+ if (lastException instanceof InvalidKeyException) {
+ throw (InvalidKeyException)lastException;
+ }
+ if (lastException instanceof RuntimeException) {
+ throw (RuntimeException)lastException;
+ }
+ String k = (key != null) ? key.getClass().getName() : "(null)";
+ throw new InvalidKeyException
+ ("No installed provider supports this key: "
+ + k, lastException);
+ }
+ }
+
+ private final static int I_PUB = 1;
+ private final static int I_PRIV = 2;
+ private final static int I_PRIV_SR = 3;
+
+ private void init(SignatureSpi spi, int type, Key key,
+ SecureRandom random) throws InvalidKeyException {
+ switch (type) {
+ case I_PUB:
+ spi.engineInitVerify((PublicKey)key);
+ break;
+ case I_PRIV:
+ spi.engineInitSign((PrivateKey)key);
+ break;
+ case I_PRIV_SR:
+ spi.engineInitSign((PrivateKey)key, random);
+ break;
+ default:
+ throw new AssertionError("Internal error: " + type);
+ }
+ }
+
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
+ if (sigSpi != null && (lock == null || publicKey == null)) {
+ sigSpi.engineInitVerify(publicKey);
+ } else {
+ chooseProvider(I_PUB, publicKey, null);
+ }
+ }
+
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
+ if (sigSpi != null && (lock == null || privateKey == null)) {
+ sigSpi.engineInitSign(privateKey);
+ } else {
+ chooseProvider(I_PRIV, privateKey, null);
+ }
+ }
+
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom sr)
+ throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
+ if (sigSpi != null && (lock == null || privateKey == null)) {
+ sigSpi.engineInitSign(privateKey, sr);
+ } else {
+ chooseProvider(I_PRIV_SR, privateKey, sr);
+ }
+ }
+
+ protected void engineUpdate(byte b) throws SignatureException {
+ chooseFirstProvider();
+ sigSpi.engineUpdate(b);
+ }
+
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ chooseFirstProvider();
+ sigSpi.engineUpdate(b, off, len);
+ }
+
+ protected void engineUpdate(ByteBuffer data) {
+ chooseFirstProvider();
+ sigSpi.engineUpdate(data);
+ }
+
+ protected byte[] engineSign() throws SignatureException {
+ chooseFirstProvider();
+ return sigSpi.engineSign();
+ }
+
+ protected int engineSign(byte[] outbuf, int offset, int len)
+ throws SignatureException {
+ chooseFirstProvider();
+ return sigSpi.engineSign(outbuf, offset, len);
+ }
+
+ protected boolean engineVerify(byte[] sigBytes)
+ throws SignatureException {
+ chooseFirstProvider();
+ return sigSpi.engineVerify(sigBytes);
+ }
+
+ protected boolean engineVerify(byte[] sigBytes, int offset, int length)
+ throws SignatureException {
+ chooseFirstProvider();
+ return sigSpi.engineVerify(sigBytes, offset, length);
+ }
+
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ chooseFirstProvider();
+ sigSpi.engineSetParameter(param, value);
+ }
+
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ chooseFirstProvider();
+ sigSpi.engineSetParameter(params);
+ }
+
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException {
+ chooseFirstProvider();
+ return sigSpi.engineGetParameter(param);
+ }
+
+ protected AlgorithmParameters engineGetParameters() {
+ chooseFirstProvider();
+ return sigSpi.engineGetParameters();
+ }
+
+ // BEGIN Android-added: Allow access to the current SPI for testing purposes.
+ @Override
+ public SignatureSpi getCurrentSpi() {
+ if (lock == null) {
+ return sigSpi;
+ }
+ synchronized (lock) {
+ return sigSpi;
+ }
+ }
+ // END Android-added: Allow access to the current SPI for testing purposes.
+ }
+
+ // adapter for RSA/ECB/PKCS1Padding ciphers
+ @SuppressWarnings("deprecation")
+ private static class CipherAdapter extends SignatureSpi {
+
+ private final Cipher cipher;
+
+ private ByteArrayOutputStream data;
+
+ CipherAdapter(Cipher cipher) {
+ this.cipher = cipher;
+ }
+
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ cipher.init(Cipher.DECRYPT_MODE, publicKey);
+ if (data == null) {
+ data = new ByteArrayOutputStream(128);
+ } else {
+ data.reset();
+ }
+ }
+
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+ data = null;
+ }
+
+ protected void engineInitSign(PrivateKey privateKey,
+ SecureRandom random) throws InvalidKeyException {
+ cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
+ data = null;
+ }
+
+ protected void engineUpdate(byte b) throws SignatureException {
+ engineUpdate(new byte[] {b}, 0, 1);
+ }
+
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ if (data != null) {
+ data.write(b, off, len);
+ return;
+ }
+ byte[] out = cipher.update(b, off, len);
+ if ((out != null) && (out.length != 0)) {
+ throw new SignatureException
+ ("Cipher unexpectedly returned data");
+ }
+ }
+
+ protected byte[] engineSign() throws SignatureException {
+ try {
+ return cipher.doFinal();
+ } catch (IllegalBlockSizeException e) {
+ throw new SignatureException("doFinal() failed", e);
+ } catch (BadPaddingException e) {
+ throw new SignatureException("doFinal() failed", e);
+ }
+ }
+
+ protected boolean engineVerify(byte[] sigBytes)
+ throws SignatureException {
+ try {
+ byte[] out = cipher.doFinal(sigBytes);
+ byte[] dataBytes = data.toByteArray();
+ data.reset();
+ return MessageDigest.isEqual(out, dataBytes);
+ } catch (BadPaddingException e) {
+ // e.g. wrong public key used
+ // return false rather than throwing exception
+ return false;
+ } catch (IllegalBlockSizeException e) {
+ throw new SignatureException("doFinal() failed", e);
+ }
+ }
+
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException {
+ throw new InvalidParameterException("Parameters not supported");
+ }
+
+ }
+
+}
diff --git a/java/security/SignatureException.java b/java/security/SignatureException.java
new file mode 100644
index 0000000..2e1fa59
--- /dev/null
+++ b/java/security/SignatureException.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This is the generic Signature exception.
+ *
+ * @author Benjamin Renaud
+ */
+
+public class SignatureException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 7509989324975124438L;
+
+ /**
+ * Constructs a SignatureException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public SignatureException() {
+ super();
+ }
+
+ /**
+ * Constructs a SignatureException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public SignatureException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code SignatureException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public SignatureException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code SignatureException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public SignatureException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/SignatureSpi.java b/java/security/SignatureSpi.java
new file mode 100644
index 0000000..86107a1
--- /dev/null
+++ b/java/security/SignatureSpi.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 1997, 2006, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.*;
+import java.io.*;
+
+import java.nio.ByteBuffer;
+
+import sun.security.jca.JCAUtil;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code Signature} class, which is used to provide the
+ * functionality of a digital signature algorithm. Digital signatures are used
+ * for authentication and integrity assurance of digital data.
+ *.
+ * <p> All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a particular signature algorithm.
+ *
+ * @author Benjamin Renaud
+ *
+ *
+ * @see Signature
+ */
+
+public abstract class SignatureSpi {
+
+ /**
+ * Application-specified source of randomness.
+ */
+ protected SecureRandom appRandom = null;
+
+ /**
+ * Initializes this signature object with the specified
+ * public key for verification operations.
+ *
+ * @param publicKey the public key of the identity whose signature is
+ * going to be verified.
+ *
+ * @exception InvalidKeyException if the key is improperly
+ * encoded, parameters are missing, and so on.
+ */
+ protected abstract void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException;
+
+ /**
+ * Initializes this signature object with the specified
+ * private key for signing operations.
+ *
+ * @param privateKey the private key of the identity whose signature
+ * will be generated.
+ *
+ * @exception InvalidKeyException if the key is improperly
+ * encoded, parameters are missing, and so on.
+ */
+ protected abstract void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException;
+
+ /**
+ * Initializes this signature object with the specified
+ * private key and source of randomness for signing operations.
+ *
+ * <p>This concrete method has been added to this previously-defined
+ * abstract class. (For backwards compatibility, it cannot be abstract.)
+ *
+ * @param privateKey the private key of the identity whose signature
+ * will be generated.
+ * @param random the source of randomness
+ *
+ * @exception InvalidKeyException if the key is improperly
+ * encoded, parameters are missing, and so on.
+ */
+ protected void engineInitSign(PrivateKey privateKey,
+ SecureRandom random)
+ throws InvalidKeyException {
+ this.appRandom = random;
+ engineInitSign(privateKey);
+ }
+
+ /**
+ * Updates the data to be signed or verified
+ * using the specified byte.
+ *
+ * @param b the byte to use for the update.
+ *
+ * @exception SignatureException if the engine is not initialized
+ * properly.
+ */
+ protected abstract void engineUpdate(byte b) throws SignatureException;
+
+ /**
+ * Updates the data to be signed or verified, using the
+ * specified array of bytes, starting at the specified offset.
+ *
+ * @param b the array of bytes
+ * @param off the offset to start from in the array of bytes
+ * @param len the number of bytes to use, starting at offset
+ *
+ * @exception SignatureException if the engine is not initialized
+ * properly
+ */
+ protected abstract void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException;
+
+ /**
+ * Updates the data to be signed or verified using the specified
+ * ByteBuffer. Processes the {@code data.remaining()} bytes
+ * starting at at {@code data.position()}.
+ * Upon return, the buffer's position will be equal to its limit;
+ * its limit will not have changed.
+ *
+ * @param input the ByteBuffer
+ * @since 1.5
+ */
+ protected void engineUpdate(ByteBuffer input) {
+ if (input.hasRemaining() == false) {
+ return;
+ }
+ try {
+ 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[JCAUtil.getTempArraySize(len)];
+ while (len > 0) {
+ int chunk = Math.min(len, b.length);
+ input.get(b, 0, chunk);
+ engineUpdate(b, 0, chunk);
+ len -= chunk;
+ }
+ }
+ } catch (SignatureException e) {
+ // is specified to only occur when the engine is not initialized
+ // this case should never occur as it is caught in Signature.java
+ throw new ProviderException("update() failed", e);
+ }
+ }
+
+ /**
+ * Returns the signature bytes of all the data
+ * updated so far.
+ * The format of the signature depends on the underlying
+ * signature scheme.
+ *
+ * @return the signature bytes of the signing operation's result.
+ *
+ * @exception SignatureException if the engine is not
+ * initialized properly or if this signature algorithm is unable to
+ * process the input data provided.
+ */
+ protected abstract byte[] engineSign() throws SignatureException;
+
+ /**
+ * Finishes this signature operation and stores the resulting signature
+ * bytes in the provided buffer {@code outbuf}, starting at
+ * {@code offset}.
+ * The format of the signature depends on the underlying
+ * signature scheme.
+ *
+ * <p>The signature implementation is reset to its initial state
+ * (the state it was in after a call to one of the
+ * {@code engineInitSign} methods)
+ * and can be reused to generate further signatures with the same private
+ * key.
+ *
+ * This method should be abstract, but we leave it concrete for
+ * binary compatibility. Knowledgeable providers should override this
+ * method.
+ *
+ * @param outbuf buffer for the signature result.
+ *
+ * @param offset offset into {@code outbuf} where the signature is
+ * stored.
+ *
+ * @param len number of bytes within {@code outbuf} allotted for the
+ * signature.
+ * Both this default implementation and the SUN provider do not
+ * return partial digests. If the value of this parameter is less
+ * than the actual signature length, this method will throw a
+ * SignatureException.
+ * This parameter is ignored if its value is greater than or equal to
+ * the actual signature length.
+ *
+ * @return the number of bytes placed into {@code outbuf}
+ *
+ * @exception SignatureException if the engine is not
+ * initialized properly, if this signature algorithm is unable to
+ * process the input data provided, or if {@code len} is less
+ * than the actual signature length.
+ *
+ * @since 1.2
+ */
+ protected int engineSign(byte[] outbuf, int offset, int len)
+ throws SignatureException {
+ byte[] sig = engineSign();
+ if (len < sig.length) {
+ throw new SignatureException
+ ("partial signatures not returned");
+ }
+ if (outbuf.length - offset < sig.length) {
+ throw new SignatureException
+ ("insufficient space in the output buffer to store the "
+ + "signature");
+ }
+ System.arraycopy(sig, 0, outbuf, offset, sig.length);
+ return sig.length;
+ }
+
+ /**
+ * Verifies the passed-in signature.
+ *
+ * @param sigBytes the signature bytes to be verified.
+ *
+ * @return true if the signature was verified, false if not.
+ *
+ * @exception SignatureException if the engine is not
+ * initialized properly, the passed-in signature is improperly
+ * encoded or of the wrong type, if this signature algorithm is unable to
+ * process the input data provided, etc.
+ */
+ protected abstract boolean engineVerify(byte[] sigBytes)
+ throws SignatureException;
+
+ /**
+ * Verifies the passed-in signature in the specified array
+ * of bytes, starting at the specified offset.
+ *
+ * <p> Note: Subclasses should overwrite the default implementation.
+ *
+ *
+ * @param sigBytes the signature bytes to be verified.
+ * @param offset the offset to start from in the array of bytes.
+ * @param length the number of bytes to use, starting at offset.
+ *
+ * @return true if the signature was verified, false if not.
+ *
+ * @exception SignatureException if the engine is not
+ * initialized properly, the passed-in signature is improperly
+ * encoded or of the wrong type, if this signature algorithm is unable to
+ * process the input data provided, etc.
+ * @since 1.4
+ */
+ protected boolean engineVerify(byte[] sigBytes, int offset, int length)
+ throws SignatureException {
+ byte[] sigBytesCopy = new byte[length];
+ System.arraycopy(sigBytes, offset, sigBytesCopy, 0, length);
+ return engineVerify(sigBytesCopy);
+ }
+
+ /**
+ * Sets the specified algorithm parameter to the specified
+ * value. This method supplies a general-purpose mechanism through
+ * which it is possible to set the various parameters of this object.
+ * A parameter may be any settable parameter for the algorithm, such as
+ * a parameter size, or a source of random bits for signature generation
+ * (if appropriate), or an indication of whether or not to perform
+ * a specific but optional computation. A uniform algorithm-specific
+ * naming scheme for each parameter is desirable but left unspecified
+ * at this time.
+ *
+ * @param param the string identifier of the parameter.
+ *
+ * @param value the parameter value.
+ *
+ * @exception InvalidParameterException if {@code param} is an
+ * invalid parameter for this signature algorithm engine,
+ * the parameter is already set
+ * and cannot be set again, a security exception occurs, and so on.
+ *
+ * @deprecated Replaced by {@link
+ * #engineSetParameter(java.security.spec.AlgorithmParameterSpec)
+ * engineSetParameter}.
+ */
+ @Deprecated
+ protected abstract void engineSetParameter(String param, Object value)
+ throws InvalidParameterException;
+
+ /**
+ * <p>This method is overridden by providers to initialize
+ * this signature engine with the specified parameter set.
+ *
+ * @param params the parameters
+ *
+ * @exception UnsupportedOperationException if this method is not
+ * overridden by a provider
+ *
+ * @exception InvalidAlgorithmParameterException if this method is
+ * overridden by a provider and the given parameters
+ * are inappropriate for this signature engine
+ */
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * <p>This method is overridden by providers to return the
+ * parameters used with this signature engine, or null
+ * if this signature engine does not use any parameters.
+ *
+ * <p>The returned parameters may be the same that were used to initialize
+ * this signature engine, or may contain a combination of default and
+ * randomly generated parameter values used by the underlying signature
+ * implementation if this signature engine requires algorithm parameters
+ * but was not initialized with any.
+ *
+ * @return the parameters used with this signature engine, or null if this
+ * signature engine does not use any parameters
+ *
+ * @exception UnsupportedOperationException if this method is
+ * not overridden by a provider
+ * @since 1.4
+ */
+ protected AlgorithmParameters engineGetParameters() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Gets the value of the specified algorithm parameter.
+ * This method supplies a general-purpose mechanism through which it
+ * is possible to get the various parameters of this object. A parameter
+ * may be any settable parameter for the algorithm, such as a parameter
+ * size, or a source of random bits for signature generation (if
+ * appropriate), or an indication of whether or not to perform a
+ * specific but optional computation. A uniform algorithm-specific
+ * naming scheme for each parameter is desirable but left unspecified
+ * at this time.
+ *
+ * @param param the string name of the parameter.
+ *
+ * @return the object that represents the parameter value, or null if
+ * there is none.
+ *
+ * @exception InvalidParameterException if {@code param} is an
+ * invalid parameter for this engine, or another exception occurs while
+ * trying to get this parameter.
+ *
+ * @deprecated Deprecated.
+ */
+ @Deprecated
+ // Android-changed add "Deprecated."
+ protected abstract Object engineGetParameter(String param)
+ throws InvalidParameterException;
+
+ /**
+ * 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 {@code Cloneable}.
+ */
+ public Object clone() throws CloneNotSupportedException {
+ if (this instanceof Cloneable) {
+ return super.clone();
+ } else {
+ throw new CloneNotSupportedException();
+ }
+ }
+}
diff --git a/java/security/SignedObject.java b/java/security/SignedObject.java
new file mode 100644
index 0000000..9ac864e
--- /dev/null
+++ b/java/security/SignedObject.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+
+/**
+ * <p> SignedObject is a class for the purpose of creating authentic
+ * runtime objects whose integrity cannot be compromised without being
+ * detected.
+ *
+ * <p> More specifically, a SignedObject contains another Serializable
+ * object, the (to-be-)signed object and its signature.
+ *
+ * <p> The signed object is a "deep copy" (in serialized form) of an
+ * original object. Once the copy is made, further manipulation of
+ * the original object has no side effect on the copy.
+ *
+ * <p> The underlying signing algorithm is designated by the Signature
+ * object passed to the constructor and the {@code verify} method.
+ * A typical usage for signing is the following:
+ *
+ * <pre>{@code
+ * Signature signingEngine = Signature.getInstance(algorithm,
+ * provider);
+ * SignedObject so = new SignedObject(myobject, signingKey,
+ * signingEngine);
+ * }</pre>
+ *
+ * <p> A typical usage for verification is the following (having
+ * received SignedObject {@code so}):
+ *
+ * <pre>{@code
+ * Signature verificationEngine =
+ * Signature.getInstance(algorithm, provider);
+ * if (so.verify(publickey, verificationEngine))
+ * try {
+ * Object myobj = so.getObject();
+ * } catch (java.lang.ClassNotFoundException e) {};
+ * }</pre>
+ *
+ * <p> Several points are worth noting. First, there is no need to
+ * initialize the signing or verification engine, as it will be
+ * re-initialized inside the constructor and the {@code verify}
+ * method. Secondly, for verification to succeed, the specified
+ * public key must be the public key corresponding to the private key
+ * used to generate the SignedObject.
+ *
+ * <p> More importantly, for flexibility reasons, the
+ * constructor and {@code verify} method allow for
+ * customized signature engines, which can implement signature
+ * algorithms that are not installed formally as part of a crypto
+ * provider. However, it is crucial that the programmer writing the
+ * verifier code be aware what {@code Signature} engine is being
+ * used, as its own implementation of the {@code verify} method
+ * is invoked to verify a signature. In other words, a malicious
+ * {@code Signature} may choose to always return true on
+ * verification in an attempt to bypass a security check.
+ *
+ * <p> The signature algorithm can be, among others, the NIST standard
+ * DSA, using DSA and SHA-1. The algorithm is specified using the
+ * same convention as that for signatures. The DSA algorithm using the
+ * SHA-1 message digest algorithm can be specified, for example, as
+ * "SHA/DSA" or "SHA-1/DSA" (they are equivalent). In the case of
+ * RSA, there are multiple choices for the message digest algorithm,
+ * so the signing algorithm could be specified as, for example,
+ * "MD2/RSA", "MD5/RSA" or "SHA-1/RSA". The algorithm name must be
+ * specified, as there is no default.
+ *
+ * <p> The name of the Cryptography Package Provider is designated
+ * also by the Signature parameter to the constructor and the
+ * {@code verify} method. If the provider is not
+ * specified, the default provider is used. Each installation can
+ * be configured to use a particular provider as default.
+ *
+ * <p> Potential applications of SignedObject include:
+ * <ul>
+ * <li> It can be used
+ * internally to any Java runtime as an unforgeable authorization
+ * token -- one that can be passed around without the fear that the
+ * token can be maliciously modified without being detected.
+ * <li> It
+ * can be used to sign and serialize data/object for storage outside
+ * the Java runtime (e.g., storing critical access control data on
+ * disk).
+ * <li> Nested SignedObjects can be used to construct a logical
+ * sequence of signatures, resembling a chain of authorization and
+ * delegation.
+ * </ul>
+ *
+ * @see Signature
+ *
+ * @author Li Gong
+ */
+
+public final class SignedObject implements Serializable {
+
+ private static final long serialVersionUID = 720502720485447167L;
+
+ /*
+ * The original content is "deep copied" in its serialized format
+ * and stored in a byte array. The signature field is also in the
+ * form of byte array.
+ */
+
+ private byte[] content;
+ private byte[] signature;
+ private String thealgorithm;
+
+ /**
+ * Constructs a SignedObject from any Serializable object.
+ * The given object is signed with the given signing key, using the
+ * designated signature engine.
+ *
+ * @param object the object to be signed.
+ * @param signingKey the private key for signing.
+ * @param signingEngine the signature signing engine.
+ *
+ * @exception IOException if an error occurs during serialization
+ * @exception InvalidKeyException if the key is invalid.
+ * @exception SignatureException if signing fails.
+ */
+ public SignedObject(Serializable object, PrivateKey signingKey,
+ Signature signingEngine)
+ throws IOException, InvalidKeyException, SignatureException {
+ // creating a stream pipe-line, from a to b
+ ByteArrayOutputStream b = new ByteArrayOutputStream();
+ ObjectOutput a = new ObjectOutputStream(b);
+
+ // write and flush the object content to byte array
+ a.writeObject(object);
+ a.flush();
+ a.close();
+ this.content = b.toByteArray();
+ b.close();
+
+ // now sign the encapsulated object
+ this.sign(signingKey, signingEngine);
+ }
+
+ /**
+ * Retrieves the encapsulated object.
+ * The encapsulated object is de-serialized before it is returned.
+ *
+ * @return the encapsulated object.
+ *
+ * @exception IOException if an error occurs during de-serialization
+ * @exception ClassNotFoundException if an error occurs during
+ * de-serialization
+ */
+ public Object getObject()
+ throws IOException, ClassNotFoundException
+ {
+ // creating a stream pipe-line, from b to a
+ ByteArrayInputStream b = new ByteArrayInputStream(this.content);
+ ObjectInput a = new ObjectInputStream(b);
+ Object obj = a.readObject();
+ b.close();
+ a.close();
+ return obj;
+ }
+
+ /**
+ * Retrieves the signature on the signed object, in the form of a
+ * byte array.
+ *
+ * @return the signature. Returns a new array each time this
+ * method is called.
+ */
+ public byte[] getSignature() {
+ return this.signature.clone();
+ }
+
+ /**
+ * Retrieves the name of the signature algorithm.
+ *
+ * @return the signature algorithm name.
+ */
+ public String getAlgorithm() {
+ return this.thealgorithm;
+ }
+
+ /**
+ * Verifies that the signature in this SignedObject is the valid
+ * signature for the object stored inside, with the given
+ * verification key, using the designated verification engine.
+ *
+ * @param verificationKey the public key for verification.
+ * @param verificationEngine the signature verification engine.
+ *
+ * @exception SignatureException if signature verification failed.
+ * @exception InvalidKeyException if the verification key is invalid.
+ *
+ * @return {@code true} if the signature
+ * is valid, {@code false} otherwise
+ */
+ public boolean verify(PublicKey verificationKey,
+ Signature verificationEngine)
+ throws InvalidKeyException, SignatureException {
+ verificationEngine.initVerify(verificationKey);
+ verificationEngine.update(this.content.clone());
+ return verificationEngine.verify(this.signature.clone());
+ }
+
+ /*
+ * Signs the encapsulated object with the given signing key, using the
+ * designated signature engine.
+ *
+ * @param signingKey the private key for signing.
+ * @param signingEngine the signature signing engine.
+ *
+ * @exception InvalidKeyException if the key is invalid.
+ * @exception SignatureException if signing fails.
+ */
+ private void sign(PrivateKey signingKey, Signature signingEngine)
+ throws InvalidKeyException, SignatureException {
+ // initialize the signing engine
+ signingEngine.initSign(signingKey);
+ signingEngine.update(this.content.clone());
+ this.signature = signingEngine.sign().clone();
+ this.thealgorithm = signingEngine.getAlgorithm();
+ }
+
+ /**
+ * readObject is called to restore the state of the SignedObject from
+ * a stream.
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ java.io.ObjectInputStream.GetField fields = s.readFields();
+ content = ((byte[])fields.get("content", null)).clone();
+ signature = ((byte[])fields.get("signature", null)).clone();
+ thealgorithm = (String)fields.get("thealgorithm", null);
+ }
+}
diff --git a/java/security/Signer.java b/java/security/Signer.java
new file mode 100644
index 0000000..077538d
--- /dev/null
+++ b/java/security/Signer.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+
+/**
+ * This class is used to represent an Identity that can also digitally
+ * sign data.
+ *
+ * <p>The management of a signer's private keys is an important and
+ * sensitive issue that should be handled by subclasses as appropriate
+ * to their intended use.
+ *
+ * @see Identity
+ *
+ * @author Benjamin Renaud
+ *
+ * @deprecated This class is no longer used. Its functionality has been
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
+ */
+@Deprecated
+public abstract class Signer extends Identity {
+
+ private static final long serialVersionUID = -1763464102261361480L;
+
+ /**
+ * The signer's private key.
+ *
+ * @serial
+ */
+ private PrivateKey privateKey;
+
+ /**
+ * Creates a signer. This constructor should only be used for
+ * serialization.
+ */
+ protected Signer() {
+ super();
+ }
+
+
+ /**
+ * Creates a signer with the specified identity name.
+ *
+ * @param name the identity name.
+ */
+ public Signer(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a signer with the specified identity name and scope.
+ *
+ * @param name the identity name.
+ *
+ * @param scope the scope of the identity.
+ *
+ * @exception KeyManagementException if there is already an identity
+ * with the same name in the scope.
+ */
+ public Signer(String name, IdentityScope scope)
+ throws KeyManagementException {
+ super(name, scope);
+ }
+
+ /**
+ * Returns this signer's private key.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "getSignerPrivateKey"}
+ * as its argument to see if it's ok to return the private key.
+ *
+ * @return this signer's private key, or null if the private key has
+ * not yet been set.
+ *
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * returning the private key.
+ *
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public PrivateKey getPrivateKey() {
+ check("getSignerPrivateKey");
+ return privateKey;
+ }
+
+ /**
+ * Sets the key pair (public key and private key) for this signer.
+ *
+ * <p>First, if there is a security manager, its {@code checkSecurityAccess}
+ * method is called with {@code "setSignerKeyPair"}
+ * as its argument to see if it's ok to set the key pair.
+ *
+ * @param pair an initialized key pair.
+ *
+ * @exception InvalidParameterException if the key pair is not
+ * properly initialized.
+ * @exception KeyException if the key pair cannot be set for any
+ * other reason.
+ * @exception SecurityException if a security manager exists and its
+ * {@code checkSecurityAccess} method doesn't allow
+ * setting the key pair.
+ *
+ * @see SecurityManager#checkSecurityAccess
+ */
+ public final void setKeyPair(KeyPair pair)
+ throws InvalidParameterException, KeyException {
+ check("setSignerKeyPair");
+ final PublicKey pub = pair.getPublic();
+ PrivateKey priv = pair.getPrivate();
+
+ if (pub == null || priv == null) {
+ throw new InvalidParameterException();
+ }
+ try {
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction<Void>() {
+ public Void run() throws KeyManagementException {
+ setPublicKey(pub);
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException pae) {
+ throw (KeyManagementException) pae.getException();
+ }
+ privateKey = priv;
+ }
+
+ String printKeys() {
+ String keys = "";
+ PublicKey publicKey = getPublicKey();
+ if (publicKey != null && privateKey != null) {
+ keys = "\tpublic and private keys initialized";
+
+ } else {
+ keys = "\tno keys";
+ }
+ return keys;
+ }
+
+ /**
+ * Returns a string of information about the signer.
+ *
+ * @return a string of information about the signer.
+ */
+ public String toString() {
+ return "[Signer]" + super.toString();
+ }
+
+ private static void check(String directive) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkSecurityAccess(directive);
+ }
+ }
+
+}
diff --git a/java/security/Timestamp.java b/java/security/Timestamp.java
new file mode 100644
index 0000000..f66d288
--- /dev/null
+++ b/java/security/Timestamp.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.*;
+import java.security.cert.Certificate;
+import java.security.cert.CertPath;
+import java.security.cert.X509Extension;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * This class encapsulates information about a signed timestamp.
+ * It is immutable.
+ * It includes the timestamp's date and time as well as information about the
+ * Timestamping Authority (TSA) which generated and signed the timestamp.
+ *
+ * @since 1.5
+ * @author Vincent Ryan
+ */
+
+public final class Timestamp implements Serializable {
+
+ private static final long serialVersionUID = -5502683707821851294L;
+
+ /**
+ * The timestamp's date and time
+ *
+ * @serial
+ */
+ private Date timestamp;
+
+ /**
+ * The TSA's certificate path.
+ *
+ * @serial
+ */
+ private CertPath signerCertPath;
+
+ /*
+ * Hash code for this timestamp.
+ */
+ private transient int myhash = -1;
+
+ /**
+ * Constructs a Timestamp.
+ *
+ * @param timestamp is the timestamp's date and time. It must not be null.
+ * @param signerCertPath is the TSA's certificate path. It must not be null.
+ * @throws NullPointerException if timestamp or signerCertPath is null.
+ */
+ public Timestamp(Date timestamp, CertPath signerCertPath) {
+ if (timestamp == null || signerCertPath == null) {
+ throw new NullPointerException();
+ }
+ this.timestamp = new Date(timestamp.getTime()); // clone
+ this.signerCertPath = signerCertPath;
+ }
+
+ /**
+ * Returns the date and time when the timestamp was generated.
+ *
+ * @return The timestamp's date and time.
+ */
+ public Date getTimestamp() {
+ return new Date(timestamp.getTime()); // clone
+ }
+
+ /**
+ * Returns the certificate path for the Timestamping Authority.
+ *
+ * @return The TSA's certificate path.
+ */
+ public CertPath getSignerCertPath() {
+ return signerCertPath;
+ }
+
+ /**
+ * Returns the hash code value for this timestamp.
+ * The hash code is generated using the date and time of the timestamp
+ * and the TSA's certificate path.
+ *
+ * @return a hash code value for this timestamp.
+ */
+ public int hashCode() {
+ if (myhash == -1) {
+ myhash = timestamp.hashCode() + signerCertPath.hashCode();
+ }
+ return myhash;
+ }
+
+ /**
+ * Tests for equality between the specified object and this
+ * timestamp. Two timestamps are considered equal if the date and time of
+ * their timestamp's and their signer's certificate paths are equal.
+ *
+ * @param obj the object to test for equality with this timestamp.
+ *
+ * @return true if the timestamp are considered equal, false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == null || (!(obj instanceof Timestamp))) {
+ return false;
+ }
+ Timestamp that = (Timestamp)obj;
+
+ if (this == that) {
+ return true;
+ }
+ return (timestamp.equals(that.getTimestamp()) &&
+ signerCertPath.equals(that.getSignerCertPath()));
+ }
+
+ /**
+ * Returns a string describing this timestamp.
+ *
+ * @return A string comprising the date and time of the timestamp and
+ * its signer's certificate.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("(");
+ sb.append("timestamp: " + timestamp);
+ List<? extends Certificate> certs = signerCertPath.getCertificates();
+ if (!certs.isEmpty()) {
+ sb.append("TSA: " + certs.get(0));
+ } else {
+ sb.append("TSA: <empty>");
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ // Explicitly reset hash code value to -1
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ myhash = -1;
+ timestamp = new Date(timestamp.getTime());
+ }
+}
diff --git a/java/security/UnrecoverableEntryException.java b/java/security/UnrecoverableEntryException.java
new file mode 100644
index 0000000..0314e3d
--- /dev/null
+++ b/java/security/UnrecoverableEntryException.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This exception is thrown if an entry in the keystore cannot be recovered.
+ *
+ *
+ * @since 1.5
+ */
+
+public class UnrecoverableEntryException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -4527142945246286535L;
+
+ /**
+ * Constructs an UnrecoverableEntryException with no detail message.
+ */
+ public UnrecoverableEntryException() {
+ super();
+ }
+
+ /**
+ * Constructs an UnrecoverableEntryException with the specified detail
+ * message, which provides more information about why this exception
+ * has been thrown.
+ *
+ * @param msg the detail message.
+ */
+ public UnrecoverableEntryException(String msg) {
+ super(msg);
+ }
+}
diff --git a/java/security/UnrecoverableKeyException.java b/java/security/UnrecoverableKeyException.java
new file mode 100644
index 0000000..09fcc6e
--- /dev/null
+++ b/java/security/UnrecoverableKeyException.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1997, 2005, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+/**
+ * This exception is thrown if a key in the keystore cannot be recovered.
+ *
+ *
+ * @since 1.2
+ */
+
+public class UnrecoverableKeyException extends UnrecoverableEntryException {
+
+ private static final long serialVersionUID = 7275063078190151277L;
+
+ /**
+ * Constructs an UnrecoverableKeyException with no detail message.
+ */
+ public UnrecoverableKeyException() {
+ super();
+ }
+
+ /**
+ * Constructs an UnrecoverableKeyException with the specified detail
+ * message, which provides more information about why this exception
+ * has been thrown.
+ *
+ * @param msg the detail message.
+ */
+ public UnrecoverableKeyException(String msg) {
+ super(msg);
+ }
+}
diff --git a/java/security/UnresolvedPermission.java b/java/security/UnresolvedPermission.java
new file mode 100644
index 0000000..6f3bf4a
--- /dev/null
+++ b/java/security/UnresolvedPermission.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.lang.reflect.*;
+import java.security.cert.*;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+
+public final class UnresolvedPermission extends Permission
+implements java.io.Serializable
+{
+
+ public UnresolvedPermission(String type,
+ String name,
+ String actions,
+ java.security.cert.Certificate certs[]) { super(""); }
+
+ public boolean implies(Permission p) { return false; }
+
+ public String getActions() { return null; }
+
+ public String getUnresolvedType() { return null; }
+
+ public String getUnresolvedName() { return null; }
+
+ public String getUnresolvedActions() { return null; }
+
+ public java.security.cert.Certificate[] getUnresolvedCerts() { return null; }
+}
diff --git a/java/security/UnresolvedPermissionCollection.java b/java/security/UnresolvedPermissionCollection.java
new file mode 100644
index 0000000..7633648
--- /dev/null
+++ b/java/security/UnresolvedPermissionCollection.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security;
+
+import java.util.*;
+import java.io.ObjectStreamField;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.IOException;
+
+/**
+ * A UnresolvedPermissionCollection stores a collection
+ * of UnresolvedPermission permissions.
+ *
+ * @see java.security.Permission
+ * @see java.security.Permissions
+ * @see java.security.UnresolvedPermission
+ *
+ *
+ * @author Roland Schemers
+ *
+ * @serial include
+ */
+
+final class UnresolvedPermissionCollection
+extends PermissionCollection
+implements java.io.Serializable
+{
+ /**
+ * Key is permission type, value is a list of the UnresolvedPermissions
+ * of the same type.
+ * Not serialized; see serialization section at end of class.
+ */
+ private transient Map<String, List<UnresolvedPermission>> perms;
+
+ /**
+ * Create an empty UnresolvedPermissionCollection object.
+ *
+ */
+ public UnresolvedPermissionCollection() {
+ perms = new HashMap<String, List<UnresolvedPermission>>(11);
+ }
+
+ /**
+ * Adds a permission to this UnresolvedPermissionCollection.
+ * The key for the hash is the unresolved permission's type (class) name.
+ *
+ * @param permission the Permission object to add.
+ */
+
+ public void add(Permission permission)
+ {
+ if (! (permission instanceof UnresolvedPermission))
+ throw new IllegalArgumentException("invalid permission: "+
+ permission);
+ UnresolvedPermission up = (UnresolvedPermission) permission;
+
+ List<UnresolvedPermission> v;
+ synchronized (this) {
+ v = perms.get(up.getName());
+ if (v == null) {
+ v = new ArrayList<UnresolvedPermission>();
+ perms.put(up.getName(), v);
+ }
+ }
+ synchronized (v) {
+ v.add(up);
+ }
+ }
+
+ /**
+ * get any unresolved permissions of the same type as p,
+ * and return the List containing them.
+ */
+ List<UnresolvedPermission> getUnresolvedPermissions(Permission p) {
+ synchronized (this) {
+ return perms.get(p.getClass().getName());
+ }
+ }
+
+ /**
+ * always returns false for unresolved permissions
+ *
+ */
+ public boolean implies(Permission permission)
+ {
+ return false;
+ }
+
+ /**
+ * Returns an enumeration of all the UnresolvedPermission lists in the
+ * container.
+ *
+ * @return an enumeration of all the UnresolvedPermission objects.
+ */
+
+ public Enumeration<Permission> elements() {
+ List<Permission> results =
+ new ArrayList<>(); // where results are stored
+
+ // Get iterator of Map values (which are lists of permissions)
+ synchronized (this) {
+ for (List<UnresolvedPermission> l : perms.values()) {
+ synchronized (l) {
+ results.addAll(l);
+ }
+ }
+ }
+
+ return Collections.enumeration(results);
+ }
+
+ private static final long serialVersionUID = -7176153071733132400L;
+
+ // Need to maintain serialization interoperability with earlier releases,
+ // which had the serializable field:
+ // private Hashtable permissions; // keyed on type
+
+ /**
+ * @serialField permissions java.util.Hashtable
+ * A table of the UnresolvedPermissions keyed on type, value is Vector
+ * of permissions
+ */
+ private static final ObjectStreamField[] serialPersistentFields = {
+ new ObjectStreamField("permissions", Hashtable.class),
+ };
+
+ /**
+ * @serialData Default field.
+ */
+ /*
+ * Writes the contents of the perms field out as a Hashtable
+ * in which the values are Vectors for
+ * serialization compatibility with earlier releases.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ // Don't call out.defaultWriteObject()
+
+ // Copy perms into a Hashtable
+ Hashtable<String, Vector<UnresolvedPermission>> permissions =
+ new Hashtable<>(perms.size()*2);
+
+ // Convert each entry (List) into a Vector
+ synchronized (this) {
+ Set<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet();
+ for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
+ // Convert list into Vector
+ List<UnresolvedPermission> list = e.getValue();
+ Vector<UnresolvedPermission> vec = new Vector<>(list.size());
+ synchronized (list) {
+ vec.addAll(list);
+ }
+
+ // Add to Hashtable being serialized
+ permissions.put(e.getKey(), vec);
+ }
+ }
+
+ // Write out serializable fields
+ ObjectOutputStream.PutField pfields = out.putFields();
+ pfields.put("permissions", permissions);
+ out.writeFields();
+ }
+
+ /*
+ * Reads in a Hashtable in which the values are Vectors of
+ * UnresolvedPermissions and saves them in the perms field.
+ */
+ private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ // Don't call defaultReadObject()
+
+ // Read in serialized fields
+ ObjectInputStream.GetField gfields = in.readFields();
+
+ // Get permissions
+ @SuppressWarnings("unchecked")
+ // writeObject writes a Hashtable<String, Vector<UnresolvedPermission>>
+ // for the permissions key, so this cast is safe, unless the data is corrupt.
+ Hashtable<String, Vector<UnresolvedPermission>> permissions =
+ (Hashtable<String, Vector<UnresolvedPermission>>)
+ gfields.get("permissions", null);
+ perms = new HashMap<String, List<UnresolvedPermission>>(permissions.size()*2);
+
+ // Convert each entry (Vector) into a List
+ Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
+ for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
+ // Convert Vector into ArrayList
+ Vector<UnresolvedPermission> vec = e.getValue();
+ List<UnresolvedPermission> list = new ArrayList<>(vec.size());
+ list.addAll(vec);
+
+ // Add to Hashtable being serialized
+ perms.put(e.getKey(), list);
+ }
+ }
+}
diff --git a/java/security/acl/Acl.java b/java/security/acl/Acl.java
new file mode 100644
index 0000000..b9cf004
--- /dev/null
+++ b/java/security/acl/Acl.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.util.Enumeration;
+import java.security.Principal;
+
+/**
+ * Interface representing an Access Control List (ACL). An Access
+ * Control List is a data structure used to guard access to
+ * resources.<p>
+ *
+ * An ACL can be thought of as a data structure with multiple ACL
+ * entries. Each ACL entry, of interface type AclEntry, contains a
+ * set of permissions associated with a particular principal. (A
+ * principal represents an entity such as an individual user or a
+ * group). Additionally, each ACL entry is specified as being either
+ * positive or negative. If positive, the permissions are to be
+ * granted to the associated principal. If negative, the permissions
+ * are to be denied.<p>
+ *
+ * The ACL Entries in each ACL observe the following rules:
+ *
+ * <ul> <li>Each principal can have at most one positive ACL entry and
+ * one negative entry; that is, multiple positive or negative ACL
+ * entries are not allowed for any principal. Each entry specifies
+ * the set of permissions that are to be granted (if positive) or
+ * denied (if negative).
+ *
+ * <li>If there is no entry for a particular principal, then the
+ * principal is considered to have a null (empty) permission set.
+ *
+ * <li>If there is a positive entry that grants a principal a
+ * particular permission, and a negative entry that denies the
+ * principal the same permission, the result is as though the
+ * permission was never granted or denied.
+ *
+ * <li>Individual permissions always override permissions of the
+ * group(s) to which the individual belongs. That is, individual
+ * negative permissions (specific denial of permissions) override the
+ * groups' positive permissions. And individual positive permissions
+ * override the groups' negative permissions.
+ *
+ * </ul>
+ *
+ * The {@code java.security.acl } package provides the
+ * interfaces to the ACL and related data structures (ACL entries,
+ * groups, permissions, etc.), and the {@code sun.security.acl }
+ * classes provide a default implementation of the interfaces. For
+ * example, {@code java.security.acl.Acl } provides the
+ * interface to an ACL and the {@code sun.security.acl.AclImpl }
+ * class provides the default implementation of the interface.<p>
+ *
+ * The {@code java.security.acl.Acl } interface extends the
+ * {@code java.security.acl.Owner } interface. The Owner
+ * interface is used to maintain a list of owners for each ACL. Only
+ * owners are allowed to modify an ACL. For example, only an owner can
+ * call the ACL's {@code addEntry} method to add a new ACL entry
+ * to the ACL.
+ *
+ * @see java.security.acl.AclEntry
+ * @see java.security.acl.Owner
+ * @see java.security.acl.Acl#getPermissions
+ *
+ * @author Satish Dharmaraj
+ */
+
+public interface Acl extends Owner {
+
+ /**
+ * Sets the name of this ACL.
+ *
+ * @param caller the principal invoking this method. It must be an
+ * owner of this ACL.
+ *
+ * @param name the name to be given to this ACL.
+ *
+ * @exception NotOwnerException if the caller principal
+ * is not an owner of this ACL.
+ *
+ * @see #getName
+ */
+ public void setName(Principal caller, String name)
+ throws NotOwnerException;
+
+ /**
+ * Returns the name of this ACL.
+ *
+ * @return the name of this ACL.
+ *
+ * @see #setName
+ */
+ public String getName();
+
+ /**
+ * Adds an ACL entry to this ACL. An entry associates a principal
+ * (e.g., an individual or a group) with a set of
+ * permissions. Each principal can have at most one positive ACL
+ * entry (specifying permissions to be granted to the principal)
+ * and one negative ACL entry (specifying permissions to be
+ * denied). If there is already an ACL entry of the same type
+ * (negative or positive) already in the ACL, false is returned.
+ *
+ * @param caller the principal invoking this method. It must be an
+ * owner of this ACL.
+ *
+ * @param entry the ACL entry to be added to this ACL.
+ *
+ * @return true on success, false if an entry of the same type
+ * (positive or negative) for the same principal is already
+ * present in this ACL.
+ *
+ * @exception NotOwnerException if the caller principal
+ * is not an owner of this ACL.
+ */
+ public boolean addEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException;
+
+ /**
+ * Removes an ACL entry from this ACL.
+ *
+ * @param caller the principal invoking this method. It must be an
+ * owner of this ACL.
+ *
+ * @param entry the ACL entry to be removed from this ACL.
+ *
+ * @return true on success, false if the entry is not part of this ACL.
+ *
+ * @exception NotOwnerException if the caller principal is not
+ * an owner of this Acl.
+ */
+ public boolean removeEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException;
+
+ /**
+ * Returns an enumeration for the set of allowed permissions for the
+ * specified principal (representing an entity such as an individual or
+ * a group). This set of allowed permissions is calculated as
+ * follows:
+ *
+ * <ul>
+ *
+ * <li>If there is no entry in this Access Control List for the
+ * specified principal, an empty permission set is returned.
+ *
+ * <li>Otherwise, the principal's group permission sets are determined.
+ * (A principal can belong to one or more groups, where a group is a
+ * group of principals, represented by the Group interface.)
+ * The group positive permission set is the union of all
+ * the positive permissions of each group that the principal belongs to.
+ * The group negative permission set is the union of all
+ * the negative permissions of each group that the principal belongs to.
+ * If there is a specific permission that occurs in both
+ * the positive permission set and the negative permission set,
+ * it is removed from both.<p>
+ *
+ * The individual positive and negative permission sets are also
+ * determined. The positive permission set contains the permissions
+ * specified in the positive ACL entry (if any) for the principal.
+ * Similarly, the negative permission set contains the permissions
+ * specified in the negative ACL entry (if any) for the principal.
+ * The individual positive (or negative) permission set is considered
+ * to be null if there is not a positive (negative) ACL entry for the
+ * principal in this ACL.<p>
+ *
+ * The set of permissions granted to the principal is then calculated
+ * using the simple rule that individual permissions always override
+ * the group permissions. That is, the principal's individual negative
+ * permission set (specific denial of permissions) overrides the group
+ * positive permission set, and the principal's individual positive
+ * permission set overrides the group negative permission set.
+ *
+ * </ul>
+ *
+ * @param user the principal whose permission set is to be returned.
+ *
+ * @return the permission set specifying the permissions the principal
+ * is allowed.
+ */
+ public Enumeration<Permission> getPermissions(Principal user);
+
+ /**
+ * Returns an enumeration of the entries in this ACL. Each element in
+ * the enumeration is of type AclEntry.
+ *
+ * @return an enumeration of the entries in this ACL.
+ */
+ public Enumeration<AclEntry> entries();
+
+ /**
+ * Checks whether or not the specified principal has the specified
+ * permission. If it does, true is returned, otherwise false is returned.
+ *
+ * More specifically, this method checks whether the passed permission
+ * is a member of the allowed permission set of the specified principal.
+ * The allowed permission set is determined by the same algorithm as is
+ * used by the {@code getPermissions} method.
+ *
+ * @param principal the principal, assumed to be a valid authenticated
+ * Principal.
+ *
+ * @param permission the permission to be checked for.
+ *
+ * @return true if the principal has the specified permission, false
+ * otherwise.
+ *
+ * @see #getPermissions
+ */
+ public boolean checkPermission(Principal principal, Permission permission);
+
+ /**
+ * Returns a string representation of the
+ * ACL contents.
+ *
+ * @return a string representation of the ACL contents.
+ */
+ public String toString();
+}
diff --git a/java/security/acl/AclEntry.java b/java/security/acl/AclEntry.java
new file mode 100644
index 0000000..cd9675f
--- /dev/null
+++ b/java/security/acl/AclEntry.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.util.Enumeration;
+import java.security.Principal;
+
+/**
+ * This is the interface used for representing one entry in an Access
+ * Control List (ACL).<p>
+ *
+ * An ACL can be thought of as a data structure with multiple ACL entry
+ * objects. Each ACL entry object contains a set of permissions associated
+ * with a particular principal. (A principal represents an entity such as
+ * an individual user or a group). Additionally, each ACL entry is specified
+ * as being either positive or negative. If positive, the permissions are
+ * to be granted to the associated principal. If negative, the permissions
+ * are to be denied. Each principal can have at most one positive ACL entry
+ * and one negative entry; that is, multiple positive or negative ACL
+ * entries are not allowed for any principal.
+ *
+ * Note: ACL entries are by default positive. An entry becomes a
+ * negative entry only if the
+ * {@link #setNegativePermissions() setNegativePermissions}
+ * method is called on it.
+ *
+ * @see java.security.acl.Acl
+ *
+ * @author Satish Dharmaraj
+ */
+public interface AclEntry extends Cloneable {
+
+ /**
+ * Specifies the principal for which permissions are granted or denied
+ * by this ACL entry. If a principal was already set for this ACL entry,
+ * false is returned, otherwise true is returned.
+ *
+ * @param user the principal to be set for this entry.
+ *
+ * @return true if the principal is set, false if there was
+ * already a principal set for this entry.
+ *
+ * @see #getPrincipal
+ */
+ public boolean setPrincipal(Principal user);
+
+ /**
+ * Returns the principal for which permissions are granted or denied by
+ * this ACL entry. Returns null if there is no principal set for this
+ * entry yet.
+ *
+ * @return the principal associated with this entry.
+ *
+ * @see #setPrincipal
+ */
+ public Principal getPrincipal();
+
+ /**
+ * Sets this ACL entry to be a negative one. That is, the associated
+ * principal (e.g., a user or a group) will be denied the permission set
+ * specified in the entry.
+ *
+ * Note: ACL entries are by default positive. An entry becomes a
+ * negative entry only if this {@code setNegativePermissions}
+ * method is called on it.
+ */
+ public void setNegativePermissions();
+
+ /**
+ * Returns true if this is a negative ACL entry (one denying the
+ * associated principal the set of permissions in the entry), false
+ * otherwise.
+ *
+ * @return true if this is a negative ACL entry, false if it's not.
+ */
+ public boolean isNegative();
+
+ /**
+ * Adds the specified permission to this ACL entry. Note: An entry can
+ * have multiple permissions.
+ *
+ * @param permission the permission to be associated with
+ * the principal in this entry.
+ *
+ * @return true if the permission was added, false if the
+ * permission was already part of this entry's permission set.
+ */
+ public boolean addPermission(Permission permission);
+
+ /**
+ * Removes the specified permission from this ACL entry.
+ *
+ * @param permission the permission to be removed from this entry.
+ *
+ * @return true if the permission is removed, false if the
+ * permission was not part of this entry's permission set.
+ */
+ public boolean removePermission(Permission permission);
+
+ /**
+ * Checks if the specified permission is part of the
+ * permission set in this entry.
+ *
+ * @param permission the permission to be checked for.
+ *
+ * @return true if the permission is part of the
+ * permission set in this entry, false otherwise.
+ */
+ public boolean checkPermission(Permission permission);
+
+ /**
+ * Returns an enumeration of the permissions in this ACL entry.
+ *
+ * @return an enumeration of the permissions in this ACL entry.
+ */
+ public Enumeration<Permission> permissions();
+
+ /**
+ * Returns a string representation of the contents of this ACL entry.
+ *
+ * @return a string representation of the contents.
+ */
+ public String toString();
+
+ /**
+ * Clones this ACL entry.
+ *
+ * @return a clone of this ACL entry.
+ */
+ public Object clone();
+}
diff --git a/java/security/acl/AclNotFoundException.java b/java/security/acl/AclNotFoundException.java
new file mode 100644
index 0000000..6f08e17
--- /dev/null
+++ b/java/security/acl/AclNotFoundException.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+/**
+ * This is an exception that is thrown whenever a reference is made to a
+ * non-existent ACL (Access Control List).
+ *
+ * @author Satish Dharmaraj
+ */
+public class AclNotFoundException extends Exception {
+
+ private static final long serialVersionUID = 5684295034092681791L;
+
+ /**
+ * Constructs an AclNotFoundException.
+ */
+ public AclNotFoundException() {
+ }
+
+}
diff --git a/java/security/acl/Group.java b/java/security/acl/Group.java
new file mode 100644
index 0000000..ebd9c44
--- /dev/null
+++ b/java/security/acl/Group.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.util.Enumeration;
+import java.security.Principal;
+
+/**
+ * This interface is used to represent a group of principals. (A principal
+ * represents an entity such as an individual user or a company). <p>
+ *
+ * Note that Group extends Principal. Thus, either a Principal or a Group can
+ * be passed as an argument to methods containing a Principal parameter. For
+ * example, you can add either a Principal or a Group to a Group object by
+ * calling the object's {@code addMember} method, passing it the
+ * Principal or Group.
+ *
+ * @author Satish Dharmaraj
+ */
+public interface Group extends Principal {
+
+ /**
+ * Adds the specified member to the group.
+ *
+ * @param user the principal to add to this group.
+ *
+ * @return true if the member was successfully added,
+ * false if the principal was already a member.
+ */
+ public boolean addMember(Principal user);
+
+ /**
+ * Removes the specified member from the group.
+ *
+ * @param user the principal to remove from this group.
+ *
+ * @return true if the principal was removed, or
+ * false if the principal was not a member.
+ */
+ public boolean removeMember(Principal user);
+
+ /**
+ * Returns true if the passed principal is a member of the group.
+ * This method does a recursive search, so if a principal belongs to a
+ * group which is a member of this group, true is returned.
+ *
+ * @param member the principal whose membership is to be checked.
+ *
+ * @return true if the principal is a member of this group,
+ * false otherwise.
+ */
+ public boolean isMember(Principal member);
+
+
+ /**
+ * Returns an enumeration of the members in the group.
+ * The returned objects can be instances of either Principal
+ * or Group (which is a subclass of Principal).
+ *
+ * @return an enumeration of the group members.
+ */
+ public Enumeration<? extends Principal> members();
+
+}
diff --git a/java/security/acl/LastOwnerException.java b/java/security/acl/LastOwnerException.java
new file mode 100644
index 0000000..196c8f1
--- /dev/null
+++ b/java/security/acl/LastOwnerException.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+/**
+ * This is an exception that is thrown whenever an attempt is made to delete
+ * the last owner of an Access Control List.
+ *
+ * @see java.security.acl.Owner#deleteOwner
+ *
+ * @author Satish Dharmaraj
+ */
+public class LastOwnerException extends Exception {
+
+ private static final long serialVersionUID = -5141997548211140359L;
+
+ /**
+ * Constructs a LastOwnerException.
+ */
+ public LastOwnerException() {
+ }
+}
diff --git a/java/security/acl/NotOwnerException.java b/java/security/acl/NotOwnerException.java
new file mode 100644
index 0000000..0a4b04b
--- /dev/null
+++ b/java/security/acl/NotOwnerException.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+/**
+ * This is an exception that is thrown whenever the modification of an object
+ * (such as an Access Control List) is only allowed to be done by an owner of
+ * the object, but the Principal attempting the modification is not an owner.
+ *
+ * @author Satish Dharmaraj
+ */
+public class NotOwnerException extends Exception {
+
+ private static final long serialVersionUID = -5555597911163362399L;
+
+ /**
+ * Constructs a NotOwnerException.
+ */
+ public NotOwnerException() {
+ }
+}
diff --git a/java/security/acl/Owner.java b/java/security/acl/Owner.java
new file mode 100644
index 0000000..2f649d4
--- /dev/null
+++ b/java/security/acl/Owner.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.security.Principal;
+
+/**
+ * Interface for managing owners of Access Control Lists (ACLs) or ACL
+ * configurations. (Note that the Acl interface in the
+ * {@code java.security.acl} package extends this Owner
+ * interface.) The initial owner Principal should be specified as an
+ * argument to the constructor of the class implementing this interface.
+ *
+ * @see java.security.acl.Acl
+ *
+ */
+public interface Owner {
+
+ /**
+ * Adds an owner. Only owners can modify ACL contents. The caller
+ * principal must be an owner of the ACL in order to invoke this method.
+ * That is, only an owner can add another owner. The initial owner is
+ * configured at ACL construction time.
+ *
+ * @param caller the principal invoking this method. It must be an owner
+ * of the ACL.
+ *
+ * @param owner the owner that should be added to the list of owners.
+ *
+ * @return true if successful, false if owner is already an owner.
+ * @exception NotOwnerException if the caller principal is not an owner
+ * of the ACL.
+ */
+ public boolean addOwner(Principal caller, Principal owner)
+ throws NotOwnerException;
+
+ /**
+ * Deletes an owner. If this is the last owner in the ACL, an exception is
+ * raised.<p>
+ *
+ * The caller principal must be an owner of the ACL in order to invoke
+ * this method.
+ *
+ * @param caller the principal invoking this method. It must be an owner
+ * of the ACL.
+ *
+ * @param owner the owner to be removed from the list of owners.
+ *
+ * @return true if the owner is removed, false if the owner is not part
+ * of the list of owners.
+ *
+ * @exception NotOwnerException if the caller principal is not an owner
+ * of the ACL.
+ *
+ * @exception LastOwnerException if there is only one owner left, so that
+ * deleteOwner would leave the ACL owner-less.
+ */
+ public boolean deleteOwner(Principal caller, Principal owner)
+ throws NotOwnerException, LastOwnerException;
+
+ /**
+ * Returns true if the given principal is an owner of the ACL.
+ *
+ * @param owner the principal to be checked to determine whether or not
+ * it is an owner.
+ *
+ * @return true if the passed principal is in the list of owners, false
+ * if not.
+ */
+ public boolean isOwner(Principal owner);
+
+}
diff --git a/java/security/acl/Permission.java b/java/security/acl/Permission.java
new file mode 100644
index 0000000..72412de
--- /dev/null
+++ b/java/security/acl/Permission.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1996, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
+/**
+ * Legacy security code; do not use.
+ */
+public interface Permission {
+}
diff --git a/java/security/acl/package-info.java b/java/security/acl/package-info.java
new file mode 100644
index 0000000..356c102
--- /dev/null
+++ b/java/security/acl/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * The classes and interfaces in this package have been
+ * superseded by classes in the java.security package.
+ * See that package and, for example, java.security.Permission for details.
+ *
+ * @since JDK1.1
+ */
+package java.security.acl;
diff --git a/java/security/cert/CRL.java b/java/security/cert/CRL.java
new file mode 100644
index 0000000..725d7b5
--- /dev/null
+++ b/java/security/cert/CRL.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1998, 2006, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * This class is an abstraction of certificate revocation lists (CRLs) that
+ * have different formats but important common uses. For example, all CRLs
+ * share the functionality of listing revoked certificates, and can be queried
+ * on whether or not they list a given certificate.
+ * <p>
+ * Specialized CRL types can be defined by subclassing off of this abstract
+ * class.
+ *
+ * @author Hemma Prafullchandra
+ *
+ *
+ * @see X509CRL
+ * @see CertificateFactory
+ *
+ * @since 1.2
+ */
+
+public abstract class CRL {
+
+ // the CRL type
+ private String type;
+
+ /**
+ * Creates a CRL of the specified type.
+ *
+ * @param type the standard name of the CRL type.
+ * See Appendix A in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+ * Java Cryptography Architecture API Specification & Reference </a>
+ * for information about standard CRL types.
+ */
+ protected CRL(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of this CRL.
+ *
+ * @return the type of this CRL.
+ */
+ public final String getType() {
+ return this.type;
+ }
+
+ /**
+ * Returns a string representation of this CRL.
+ *
+ * @return a string representation of this CRL.
+ */
+ public abstract String toString();
+
+ /**
+ * Checks whether the given certificate is on this CRL.
+ *
+ * @param cert the certificate to check for.
+ * @return true if the given certificate is on this CRL,
+ * false otherwise.
+ */
+ public abstract boolean isRevoked(Certificate cert);
+}
diff --git a/java/security/cert/CRLException.java b/java/security/cert/CRLException.java
new file mode 100644
index 0000000..7a85431
--- /dev/null
+++ b/java/security/cert/CRLException.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * CRL (Certificate Revocation List) Exception.
+ *
+ * @author Hemma Prafullchandra
+ */
+public class CRLException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -6694728944094197147L;
+
+ /**
+ * Constructs a CRLException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public CRLException() {
+ super();
+ }
+
+ /**
+ * Constructs a CRLException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param message the detail message.
+ */
+ public CRLException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a {@code CRLException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CRLException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code CRLException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CRLException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/cert/CRLReason.java b/java/security/cert/CRLReason.java
new file mode 100644
index 0000000..ac0b9e9
--- /dev/null
+++ b/java/security/cert/CRLReason.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * The CRLReason enumeration specifies the reason that a certificate
+ * is revoked, as defined in <a href="http://www.ietf.org/rfc/rfc3280.txt">
+ * RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL
+ * Profile</a>.
+ *
+ * @author Sean Mullan
+ * @since 1.7
+ * @see X509CRLEntry#getRevocationReason
+ * @see CertificateRevokedException#getRevocationReason
+ */
+public enum CRLReason {
+ /**
+ * This reason indicates that it is unspecified as to why the
+ * certificate has been revoked.
+ */
+ UNSPECIFIED,
+
+ /**
+ * This reason indicates that it is known or suspected that the
+ * certificate subject's private key has been compromised. It applies
+ * to end-entity certificates only.
+ */
+ KEY_COMPROMISE,
+
+ /**
+ * This reason indicates that it is known or suspected that the
+ * certificate subject's private key has been compromised. It applies
+ * to certificate authority (CA) certificates only.
+ */
+ CA_COMPROMISE,
+
+ /**
+ * This reason indicates that the subject's name or other information
+ * has changed.
+ */
+ AFFILIATION_CHANGED,
+
+ /**
+ * This reason indicates that the certificate has been superseded.
+ */
+ SUPERSEDED,
+
+ /**
+ * This reason indicates that the certificate is no longer needed.
+ */
+ CESSATION_OF_OPERATION,
+
+ /**
+ * This reason indicates that the certificate has been put on hold.
+ */
+ CERTIFICATE_HOLD,
+
+ /**
+ * Unused reason.
+ */
+ UNUSED,
+
+ /**
+ * This reason indicates that the certificate was previously on hold
+ * and should be removed from the CRL. It is for use with delta CRLs.
+ */
+ REMOVE_FROM_CRL,
+
+ /**
+ * This reason indicates that the privileges granted to the subject of
+ * the certificate have been withdrawn.
+ */
+ PRIVILEGE_WITHDRAWN,
+
+ /**
+ * This reason indicates that it is known or suspected that the
+ * certificate subject's private key has been compromised. It applies
+ * to authority attribute (AA) certificates only.
+ */
+ AA_COMPROMISE
+}
diff --git a/java/security/cert/CRLSelector.java b/java/security/cert/CRLSelector.java
new file mode 100644
index 0000000..7ab181d
--- /dev/null
+++ b/java/security/cert/CRLSelector.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * A selector that defines a set of criteria for selecting {@code CRL}s.
+ * Classes that implement this interface are often used to specify
+ * which {@code CRL}s should be retrieved from a {@code CertStore}.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this interface are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CRL
+ * @see CertStore
+ * @see CertStore#getCRLs
+ *
+ * @author Steve Hanna
+ * @since 1.4
+ */
+public interface CRLSelector extends Cloneable {
+
+ /**
+ * Decides whether a {@code CRL} should be selected.
+ *
+ * @param crl the {@code CRL} to be checked
+ * @return {@code true} if the {@code CRL} should be selected,
+ * {@code false} otherwise
+ */
+ boolean match(CRL crl);
+
+ /**
+ * Makes a copy of this {@code CRLSelector}. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this {@code CRLSelector}
+ */
+ Object clone();
+}
diff --git a/java/security/cert/CertPath.java b/java/security/cert/CertPath.java
new file mode 100644
index 0000000..f742664
--- /dev/null
+++ b/java/security/cert/CertPath.java
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.ByteArrayInputStream;
+import java.io.NotSerializableException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An immutable sequence of certificates (a certification path).
+ * <p>
+ * This is an abstract class that defines the methods common to all
+ * {@code CertPath}s. Subclasses can handle different kinds of
+ * certificates (X.509, PGP, etc.).
+ * <p>
+ * All {@code CertPath} objects have a type, a list of
+ * {@code Certificate}s, and one or more supported encodings. Because the
+ * {@code CertPath} class is immutable, a {@code CertPath} cannot
+ * change in any externally visible way after being constructed. This
+ * stipulation applies to all public fields and methods of this class and any
+ * added or overridden by subclasses.
+ * <p>
+ * The type is a {@code String} that identifies the type of
+ * {@code Certificate}s in the certification path. For each
+ * certificate {@code cert} in a certification path {@code certPath},
+ * {@code cert.getType().equals(certPath.getType())} must be
+ * {@code true}.
+ * <p>
+ * The list of {@code Certificate}s is an ordered {@code List} of
+ * zero or more {@code Certificate}s. This {@code List} and all
+ * of the {@code Certificate}s contained in it must be immutable.
+ * <p>
+ * Each {@code CertPath} object must support one or more encodings
+ * so that the object can be translated into a byte array for storage or
+ * transmission to other parties. Preferably, these encodings should be
+ * well-documented standards (such as PKCS#7). One of the encodings supported
+ * by a {@code CertPath} is considered the default encoding. This
+ * encoding is used if no encoding is explicitly requested (for the
+ * {@link #getEncoded() getEncoded()} method, for instance).
+ * <p>
+ * All {@code CertPath} objects are also {@code Serializable}.
+ * {@code CertPath} objects are resolved into an alternate
+ * {@link CertPathRep CertPathRep} object during serialization. This allows
+ * a {@code CertPath} object to be serialized into an equivalent
+ * representation regardless of its underlying implementation.
+ * <p>
+ * {@code CertPath} objects can be created with a
+ * {@code CertificateFactory} or they can be returned by other classes,
+ * such as a {@code CertPathBuilder}.
+ * <p>
+ * By convention, X.509 {@code CertPath}s (consisting of
+ * {@code X509Certificate}s), are ordered starting with the target
+ * certificate and ending with a certificate issued by the trust anchor. That
+ * is, the issuer of one certificate is the subject of the following one. The
+ * certificate representing the {@link TrustAnchor TrustAnchor} should not be
+ * included in the certification path. Unvalidated X.509 {@code CertPath}s
+ * may not follow these conventions. PKIX {@code CertPathValidator}s will
+ * detect any departure from these conventions that cause the certification
+ * path to be invalid and throw a {@code CertPathValidatorException}.
+ *
+ * <p> Every implementation of the Java platform is required to support the
+ * following standard {@code CertPath} encodings:
+ * <ul>
+ * <li>{@code PKCS7}</li>
+ * <li>{@code PkiPath}</li>
+ * </ul>
+ * These encodings are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * CertPath Encodings section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ * Consult the release documentation for your implementation to see if any
+ * other encodings are supported.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * All {@code CertPath} objects must be thread-safe. That is, multiple
+ * threads may concurrently invoke the methods defined in this class on a
+ * single {@code CertPath} object (or more than one) with no
+ * ill effects. This is also true for the {@code List} returned by
+ * {@code CertPath.getCertificates}.
+ * <p>
+ * Requiring {@code CertPath} objects to be immutable and thread-safe
+ * allows them to be passed around to various pieces of code without worrying
+ * about coordinating access. Providing this thread-safety is
+ * generally not difficult, since the {@code CertPath} and
+ * {@code List} objects in question are immutable.
+ *
+ * @see CertificateFactory
+ * @see CertPathBuilder
+ *
+ * @author Yassir Elley
+ * @since 1.4
+ */
+public abstract class CertPath implements Serializable {
+
+ private static final long serialVersionUID = 6068470306649138683L;
+
+ private String type; // the type of certificates in this chain
+
+ /**
+ * Creates a {@code CertPath} of the specified type.
+ * <p>
+ * This constructor is protected because most users should use a
+ * {@code CertificateFactory} to create {@code CertPath}s.
+ *
+ * @param type the standard name of the type of
+ * {@code Certificate}s in this path
+ */
+ protected CertPath(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of {@code Certificate}s in this certification
+ * path. This is the same string that would be returned by
+ * {@link java.security.cert.Certificate#getType() cert.getType()}
+ * for all {@code Certificate}s in the certification path.
+ *
+ * @return the type of {@code Certificate}s in this certification
+ * path (never null)
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns an iteration of the encodings supported by this certification
+ * path, with the default encoding first. Attempts to modify the returned
+ * {@code Iterator} via its {@code remove} method result in an
+ * {@code UnsupportedOperationException}.
+ *
+ * @return an {@code Iterator} over the names of the supported
+ * encodings (as Strings)
+ */
+ public abstract Iterator<String> getEncodings();
+
+ /**
+ * Compares this certification path for equality with the specified
+ * object. Two {@code CertPath}s are equal if and only if their
+ * types are equal and their certificate {@code List}s (and by
+ * implication the {@code Certificate}s in those {@code List}s)
+ * are equal. A {@code CertPath} is never equal to an object that is
+ * not a {@code CertPath}.
+ * <p>
+ * This algorithm is implemented by this method. If it is overridden,
+ * the behavior specified here must be maintained.
+ *
+ * @param other the object to test for equality with this certification path
+ * @return true if the specified object is equal to this certification path,
+ * false otherwise
+ */
+ public boolean equals(Object other) {
+ if (this == other)
+ return true;
+
+ if (! (other instanceof CertPath))
+ return false;
+
+ CertPath otherCP = (CertPath) other;
+ if (! otherCP.getType().equals(type))
+ return false;
+
+ List<? extends Certificate> thisCertList = this.getCertificates();
+ List<? extends Certificate> otherCertList = otherCP.getCertificates();
+ return(thisCertList.equals(otherCertList));
+ }
+
+ /**
+ * Returns the hashcode for this certification path. The hash code of
+ * a certification path is defined to be the result of the following
+ * calculation:
+ * <pre>{@code
+ * hashCode = path.getType().hashCode();
+ * hashCode = 31*hashCode + path.getCertificates().hashCode();
+ * }</pre>
+ * This ensures that {@code path1.equals(path2)} implies that
+ * {@code path1.hashCode()==path2.hashCode()} for any two certification
+ * paths, {@code path1} and {@code path2}, as required by the
+ * general contract of {@code Object.hashCode}.
+ *
+ * @return the hashcode value for this certification path
+ */
+ public int hashCode() {
+ int hashCode = type.hashCode();
+ hashCode = 31*hashCode + getCertificates().hashCode();
+ return hashCode;
+ }
+
+ /**
+ * Returns a string representation of this certification path.
+ * This calls the {@code toString} method on each of the
+ * {@code Certificate}s in the path.
+ *
+ * @return a string representation of this certification path
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ Iterator<? extends Certificate> stringIterator =
+ getCertificates().iterator();
+
+ sb.append("\n" + type + " Cert Path: length = "
+ + getCertificates().size() + ".\n");
+ sb.append("[\n");
+ int i = 1;
+ while (stringIterator.hasNext()) {
+ sb.append("=========================================="
+ + "===============Certificate " + i + " start.\n");
+ Certificate stringCert = stringIterator.next();
+ sb.append(stringCert.toString());
+ sb.append("\n========================================"
+ + "=================Certificate " + i + " end.\n\n\n");
+ i++;
+ }
+
+ sb.append("\n]");
+ return sb.toString();
+ }
+
+ /**
+ * Returns the encoded form of this certification path, using the default
+ * encoding.
+ *
+ * @return the encoded bytes
+ * @exception CertificateEncodingException if an encoding error occurs
+ */
+ public abstract byte[] getEncoded()
+ throws CertificateEncodingException;
+
+ /**
+ * Returns the encoded form of this certification path, using the
+ * specified encoding.
+ *
+ * @param encoding the name of the encoding to use
+ * @return the encoded bytes
+ * @exception CertificateEncodingException if an encoding error occurs or
+ * the encoding requested is not supported
+ */
+ public abstract byte[] getEncoded(String encoding)
+ throws CertificateEncodingException;
+
+ /**
+ * Returns the list of certificates in this certification path.
+ * The {@code List} returned must be immutable and thread-safe.
+ *
+ * @return an immutable {@code List} of {@code Certificate}s
+ * (may be empty, but not null)
+ */
+ public abstract List<? extends Certificate> getCertificates();
+
+ /**
+ * Replaces the {@code CertPath} to be serialized with a
+ * {@code CertPathRep} object.
+ *
+ * @return the {@code CertPathRep} to be serialized
+ *
+ * @throws ObjectStreamException if a {@code CertPathRep} object
+ * representing this certification path could not be created
+ */
+ protected Object writeReplace() throws ObjectStreamException {
+ try {
+ return new CertPathRep(type, getEncoded());
+ } catch (CertificateException ce) {
+ NotSerializableException nse =
+ new NotSerializableException
+ ("java.security.cert.CertPath: " + type);
+ nse.initCause(ce);
+ throw nse;
+ }
+ }
+
+ /**
+ * Alternate {@code CertPath} class for serialization.
+ * @since 1.4
+ */
+ protected static class CertPathRep implements Serializable {
+
+ private static final long serialVersionUID = 3015633072427920915L;
+
+ /** The Certificate type */
+ private String type;
+ /** The encoded form of the cert path */
+ private byte[] data;
+
+ /**
+ * Creates a {@code CertPathRep} with the specified
+ * type and encoded form of a certification path.
+ *
+ * @param type the standard name of a {@code CertPath} type
+ * @param data the encoded form of the certification path
+ */
+ protected CertPathRep(String type, byte[] data) {
+ this.type = type;
+ this.data = data;
+ }
+
+ /**
+ * Returns a {@code CertPath} constructed from the type and data.
+ *
+ * @return the resolved {@code CertPath} object
+ *
+ * @throws ObjectStreamException if a {@code CertPath} could not
+ * be constructed
+ */
+ protected Object readResolve() throws ObjectStreamException {
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance(type);
+ return cf.generateCertPath(new ByteArrayInputStream(data));
+ } catch (CertificateException ce) {
+ NotSerializableException nse =
+ new NotSerializableException
+ ("java.security.cert.CertPath: " + type);
+ nse.initCause(ce);
+ throw nse;
+ }
+ }
+ }
+}
diff --git a/java/security/cert/CertPathBuilder.java b/java/security/cert/CertPathBuilder.java
new file mode 100644
index 0000000..fd6cdc8
--- /dev/null
+++ b/java/security/cert/CertPathBuilder.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+import sun.security.util.Debug;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * A class for building certification paths (also known as certificate chains).
+ * <p>
+ * This class uses a provider-based architecture.
+ * To create a {@code CertPathBuilder}, call
+ * one of the static {@code getInstance} methods, passing in the
+ * algorithm name of the {@code CertPathBuilder} desired and optionally
+ * the name of the provider desired.
+ *
+ * <p>Once a {@code CertPathBuilder} object has been created, certification
+ * paths can be constructed by calling the {@link #build build} method and
+ * passing it an algorithm-specific set of parameters. If successful, the
+ * result (including the {@code CertPath} that was built) is returned
+ * in an object that implements the {@code CertPathBuilderResult}
+ * interface.
+ *
+ * <p>The {@link #getRevocationChecker} method allows an application to specify
+ * additional algorithm-specific parameters and options used by the
+ * {@code CertPathBuilder} when checking the revocation status of certificates.
+ * Here is an example demonstrating how it is used with the PKIX algorithm:
+ *
+ * <pre>
+ * CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
+ * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
+ * rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
+ * params.addCertPathChecker(rc);
+ * CertPathBuilderResult cpbr = cpb.build(params);
+ * </pre>
+ *
+ * <p> Android provides the following {@code CertPathBuilder} algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>PKIX</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * This algorithm is described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
+ * CertPathBuilder section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ * Consult the release documentation for your implementation to see if any
+ * other algorithms are supported.
+ *
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * The static methods of this class are guaranteed to be thread-safe.
+ * Multiple threads may concurrently invoke the static methods defined in
+ * this class with no ill effects.
+ * <p>
+ * However, this is not true for the non-static methods defined by this class.
+ * Unless otherwise documented by a specific provider, threads that need to
+ * access a single {@code CertPathBuilder} instance concurrently should
+ * synchronize amongst themselves and provide the necessary locking. Multiple
+ * threads each manipulating a different {@code CertPathBuilder} instance
+ * need not synchronize.
+ *
+ * @see CertPath
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ * @author Yassir Elley
+ */
+public class CertPathBuilder {
+
+ /*
+ * Constant to lookup in the Security properties file to determine
+ * the default certpathbuilder type. In the Security properties file,
+ * the default certpathbuilder type is given as:
+ * <pre>
+ * certpathbuilder.type=PKIX
+ * </pre>
+ */
+ private static final String CPB_TYPE = "certpathbuilder.type";
+ private final CertPathBuilderSpi builderSpi;
+ private final Provider provider;
+ private final String algorithm;
+
+ /**
+ * Creates a {@code CertPathBuilder} object of the given algorithm,
+ * and encapsulates the given provider implementation (SPI object) in it.
+ *
+ * @param builderSpi the provider implementation
+ * @param provider the provider
+ * @param algorithm the algorithm name
+ */
+ protected CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider,
+ String algorithm)
+ {
+ this.builderSpi = builderSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns a {@code CertPathBuilder} object that implements the
+ * specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new CertPathBuilder object encapsulating the
+ * CertPathBuilderSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the requested {@code CertPathBuilder}
+ * algorithm. See the CertPathBuilder section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return a {@code CertPathBuilder} object that implements the
+ * specified algorithm.
+ *
+ * @throws NoSuchAlgorithmException if no Provider supports a
+ * CertPathBuilderSpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static CertPathBuilder getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("CertPathBuilder",
+ CertPathBuilderSpi.class, algorithm);
+ return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a {@code CertPathBuilder} object that implements the
+ * specified algorithm.
+ *
+ * <p> A new CertPathBuilder object encapsulating the
+ * CertPathBuilderSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the requested {@code CertPathBuilder}
+ * algorithm. See the CertPathBuilder section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a {@code CertPathBuilder} object that implements the
+ * specified algorithm.
+ *
+ * @throws NoSuchAlgorithmException if a CertPathBuilderSpi
+ * implementation for the specified algorithm is not
+ * available from the specified provider.
+ *
+ * @throws NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the {@code provider} is
+ * null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static CertPathBuilder getInstance(String algorithm, String provider)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ Instance instance = GetInstance.getInstance("CertPathBuilder",
+ CertPathBuilderSpi.class, algorithm, provider);
+ return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a {@code CertPathBuilder} object that implements the
+ * specified algorithm.
+ *
+ * <p> A new CertPathBuilder object encapsulating the
+ * CertPathBuilderSpi 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 name of the requested {@code CertPathBuilder}
+ * algorithm. See the CertPathBuilder section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return a {@code CertPathBuilder} object that implements the
+ * specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if a CertPathBuilderSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the {@code provider} is
+ * null.
+ *
+ * @see java.security.Provider
+ */
+ public static CertPathBuilder getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("CertPathBuilder",
+ CertPathBuilderSpi.class, algorithm, provider);
+ return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the provider of this {@code CertPathBuilder}.
+ *
+ * @return the provider of this {@code CertPathBuilder}
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Returns the name of the algorithm of this {@code CertPathBuilder}.
+ *
+ * @return the name of the algorithm of this {@code CertPathBuilder}
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Attempts to build a certification path using the specified algorithm
+ * parameter set.
+ *
+ * @param params the algorithm parameters
+ * @return the result of the build algorithm
+ * @throws CertPathBuilderException if the builder is unable to construct
+ * a certification path that satisfies the specified parameters
+ * @throws InvalidAlgorithmParameterException if the specified parameters
+ * are inappropriate for this {@code CertPathBuilder}
+ */
+ public final CertPathBuilderResult build(CertPathParameters params)
+ throws CertPathBuilderException, InvalidAlgorithmParameterException
+ {
+ return builderSpi.engineBuild(params);
+ }
+
+ /**
+ * Returns the default {@code CertPathBuilder} type as specified by
+ * the {@code certpathbuilder.type} security property, or the string
+ * {@literal "PKIX"} if no such property exists.
+ *
+ * <p>The default {@code CertPathBuilder} type can be used by
+ * applications that do not want to use a hard-coded type when calling one
+ * of the {@code getInstance} methods, and want to provide a default
+ * type in case a user does not specify its own.
+ *
+ * <p>The default {@code CertPathBuilder} type can be changed by
+ * setting the value of the {@code certpathbuilder.type} security property
+ * to the desired type.
+ *
+ * @see java.security.Security security properties
+ * @return the default {@code CertPathBuilder} type as specified
+ * by the {@code certpathbuilder.type} security property, or the string
+ * {@literal "PKIX"} if no such property exists.
+ */
+ public final static String getDefaultType() {
+ String cpbtype =
+ AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(CPB_TYPE);
+ }
+ });
+ return (cpbtype == null) ? "PKIX" : cpbtype;
+ }
+
+ /**
+ * Returns a {@code CertPathChecker} that the encapsulated
+ * {@code CertPathBuilderSpi} implementation uses to check the revocation
+ * status of certificates. A PKIX implementation returns objects of
+ * type {@code PKIXRevocationChecker}. Each invocation of this method
+ * returns a new instance of {@code CertPathChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description for an example.
+ *
+ * @return a {@code CertPathChecker}
+ * @throws UnsupportedOperationException if the service provider does not
+ * support this method
+ * @since 1.8
+ */
+ public final CertPathChecker getRevocationChecker() {
+ return builderSpi.engineGetRevocationChecker();
+ }
+}
diff --git a/java/security/cert/CertPathBuilderException.java b/java/security/cert/CertPathBuilderException.java
new file mode 100644
index 0000000..cf95847
--- /dev/null
+++ b/java/security/cert/CertPathBuilderException.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * An exception indicating one of a variety of problems encountered when
+ * building a certification path with a {@code CertPathBuilder}.
+ * <p>
+ * A {@code CertPathBuilderException} provides support for wrapping
+ * exceptions. The {@link #getCause getCause} method returns the throwable,
+ * if any, that caused this exception to be thrown.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathBuilder
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public class CertPathBuilderException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 5316471420178794402L;
+
+ /**
+ * Creates a {@code CertPathBuilderException} with {@code null}
+ * as its detail message.
+ */
+ public CertPathBuilderException() {
+ super();
+ }
+
+ /**
+ * Creates a {@code CertPathBuilderException} with the given
+ * detail message. The detail message is a {@code String} that
+ * describes this particular exception in more detail.
+ *
+ * @param msg the detail message
+ */
+ public CertPathBuilderException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code CertPathBuilderException} that wraps the specified
+ * throwable. This allows any exception to be converted into a
+ * {@code CertPathBuilderException}, while retaining information
+ * about the wrapped exception, which may be useful for debugging. The
+ * detail message is set to ({@code cause==null ? null : cause.toString()})
+ * (which typically contains the class and detail message of
+ * cause).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or unknown.)
+ */
+ public CertPathBuilderException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Creates a {@code CertPathBuilderException} with the specified
+ * detail message and cause.
+ *
+ * @param msg the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or unknown.)
+ */
+ public CertPathBuilderException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/java/security/cert/CertPathBuilderResult.java b/java/security/cert/CertPathBuilderResult.java
new file mode 100644
index 0000000..ecf53bb
--- /dev/null
+++ b/java/security/cert/CertPathBuilderResult.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * A specification of the result of a certification path builder algorithm.
+ * All results returned by the {@link CertPathBuilder#build
+ * CertPathBuilder.build} method must implement this interface.
+ * <p>
+ * At a minimum, a {@code CertPathBuilderResult} contains the
+ * {@code CertPath} built by the {@code CertPathBuilder} instance.
+ * Implementations of this interface may add methods to return implementation
+ * or algorithm specific information, such as debugging information or
+ * certification path validation results.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this interface are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathBuilder
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public interface CertPathBuilderResult extends Cloneable {
+
+ /**
+ * Returns the built certification path.
+ *
+ * @return the certification path (never {@code null})
+ */
+ CertPath getCertPath();
+
+ /**
+ * Makes a copy of this {@code CertPathBuilderResult}. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this {@code CertPathBuilderResult}
+ */
+ Object clone();
+}
diff --git a/java/security/cert/CertPathBuilderSpi.java b/java/security/cert/CertPathBuilderSpi.java
new file mode 100644
index 0000000..e775541
--- /dev/null
+++ b/java/security/cert/CertPathBuilderSpi.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ * The <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@link CertPathBuilder CertPathBuilder} class. All
+ * {@code CertPathBuilder} implementations must include a class (the
+ * SPI class) that extends this class ({@code CertPathBuilderSpi}) and
+ * implements all of its methods. In general, instances of this class should
+ * only be accessed through the {@code CertPathBuilder} class. For
+ * details, see the Java Cryptography Architecture.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Instances of this class need not be protected against concurrent
+ * access from multiple threads. Threads that need to access a single
+ * {@code CertPathBuilderSpi} instance concurrently should synchronize
+ * amongst themselves and provide the necessary locking before calling the
+ * wrapping {@code CertPathBuilder} object.
+ * <p>
+ * However, implementations of {@code CertPathBuilderSpi} may still
+ * encounter concurrency issues, since multiple threads each
+ * manipulating a different {@code CertPathBuilderSpi} instance need not
+ * synchronize.
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public abstract class CertPathBuilderSpi {
+
+ /**
+ * The default constructor.
+ */
+ public CertPathBuilderSpi() { }
+
+ /**
+ * Attempts to build a certification path using the specified
+ * algorithm parameter set.
+ *
+ * @param params the algorithm parameters
+ * @return the result of the build algorithm
+ * @throws CertPathBuilderException if the builder is unable to construct
+ * a certification path that satisfies the specified parameters
+ * @throws InvalidAlgorithmParameterException if the specified parameters
+ * are inappropriate for this {@code CertPathBuilder}
+ */
+ public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
+ throws CertPathBuilderException, InvalidAlgorithmParameterException;
+
+ /**
+ * Returns a {@code CertPathChecker} that this implementation uses to
+ * check the revocation status of certificates. A PKIX implementation
+ * returns objects of type {@code PKIXRevocationChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description of {@code CertPathBuilder} for an example.
+ *
+ * <p>This method was added to version 1.8 of the Java Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method cannot be abstract and by default throws
+ * an {@code UnsupportedOperationException}.
+ *
+ * @return a {@code CertPathChecker} that this implementation uses to
+ * check the revocation status of certificates
+ * @throws UnsupportedOperationException if this method is not supported
+ * @since 1.8
+ */
+ public CertPathChecker engineGetRevocationChecker() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/java/security/cert/CertPathChecker.java b/java/security/cert/CertPathChecker.java
new file mode 100644
index 0000000..c40a65b
--- /dev/null
+++ b/java/security/cert/CertPathChecker.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * <p>Performs one or more checks on each {@code Certificate} of a
+ * {@code CertPath}.
+ *
+ * <p>A {@code CertPathChecker} implementation is typically created to extend
+ * a certification path validation algorithm. For example, an implementation
+ * may check for and process a critical private extension of each certificate
+ * in a certification path.
+ *
+ * @since 1.8
+ */
+public interface CertPathChecker {
+
+ /**
+ * Initializes the internal state of this {@code CertPathChecker}.
+ *
+ * <p>The {@code forward} flag specifies the order that certificates will
+ * be passed to the {@link #check check} method (forward or reverse).
+ *
+ * @param forward the order that certificates are presented to the
+ * {@code check} method. If {@code true}, certificates are
+ * presented from target to trust anchor (forward); if
+ * {@code false}, from trust anchor to target (reverse).
+ * @throws CertPathValidatorException if this {@code CertPathChecker} is
+ * unable to check certificates in the specified order
+ */
+ void init(boolean forward) throws CertPathValidatorException;
+
+ /**
+ * Indicates if forward checking is supported. Forward checking refers
+ * to the ability of the {@code CertPathChecker} to perform its checks
+ * when certificates are presented to the {@code check} method in the
+ * forward direction (from target to trust anchor).
+ *
+ * @return {@code true} if forward checking is supported, {@code false}
+ * otherwise
+ */
+ boolean isForwardCheckingSupported();
+
+ /**
+ * Performs the check(s) on the specified certificate using its internal
+ * state. The certificates are presented in the order specified by the
+ * {@code init} method.
+ *
+ * @param cert the {@code Certificate} to be checked
+ * @throws CertPathValidatorException if the specified certificate does
+ * not pass the check
+ */
+ void check(Certificate cert) throws CertPathValidatorException;
+}
diff --git a/java/security/cert/CertPathHelperImpl.java b/java/security/cert/CertPathHelperImpl.java
new file mode 100644
index 0000000..fd9e111
--- /dev/null
+++ b/java/security/cert/CertPathHelperImpl.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2002, 2009, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.util.*;
+
+import sun.security.provider.certpath.CertPathHelper;
+
+import sun.security.x509.GeneralNameInterface;
+
+/**
+ * Helper class that allows the Sun CertPath provider to access
+ * implementation dependent APIs in CertPath framework.
+ *
+ * @author Andreas Sterbenz
+ */
+class CertPathHelperImpl extends CertPathHelper {
+
+ private CertPathHelperImpl() {
+ // empty
+ }
+
+ /**
+ * Initialize the helper framework. This method must be called from
+ * the static initializer of each class that is the target of one of
+ * the methods in this class. This ensures that the helper is initialized
+ * prior to a tunneled call from the Sun provider.
+ */
+ synchronized static void initialize() {
+ if (CertPathHelper.instance == null) {
+ CertPathHelper.instance = new CertPathHelperImpl();
+ }
+ }
+
+ protected void implSetPathToNames(X509CertSelector sel,
+ Set<GeneralNameInterface> names) {
+ sel.setPathToNamesInternal(names);
+ }
+
+ protected void implSetDateAndTime(X509CRLSelector sel, Date date, long skew) {
+ sel.setDateAndTime(date, skew);
+ }
+}
diff --git a/java/security/cert/CertPathParameters.java b/java/security/cert/CertPathParameters.java
new file mode 100644
index 0000000..ace1b21
--- /dev/null
+++ b/java/security/cert/CertPathParameters.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * A specification of certification path algorithm parameters.
+ * The purpose of this interface is to group (and provide type safety for)
+ * all {@code CertPath} parameter specifications. All
+ * {@code CertPath} parameter specifications must implement this
+ * interface.
+ *
+ * @author Yassir Elley
+ * @see CertPathValidator#validate(CertPath, CertPathParameters)
+ * @see CertPathBuilder#build(CertPathParameters)
+ * @since 1.4
+ */
+public interface CertPathParameters extends Cloneable {
+
+ /**
+ * Makes a copy of this {@code CertPathParameters}. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this {@code CertPathParameters}
+ */
+ Object clone();
+}
diff --git a/java/security/cert/CertPathValidator.java b/java/security/cert/CertPathValidator.java
new file mode 100644
index 0000000..3a4b053
--- /dev/null
+++ b/java/security/cert/CertPathValidator.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+import sun.security.util.Debug;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * A class for validating certification paths (also known as certificate
+ * chains).
+ * <p>
+ * This class uses a provider-based architecture.
+ * To create a {@code CertPathValidator},
+ * call one of the static {@code getInstance} methods, passing in the
+ * algorithm name of the {@code CertPathValidator} desired and
+ * optionally the name of the provider desired.
+ *
+ * <p>Once a {@code CertPathValidator} object has been created, it can
+ * be used to validate certification paths by calling the {@link #validate
+ * validate} method and passing it the {@code CertPath} to be validated
+ * and an algorithm-specific set of parameters. If successful, the result is
+ * returned in an object that implements the
+ * {@code CertPathValidatorResult} interface.
+ *
+ * <p>The {@link #getRevocationChecker} method allows an application to specify
+ * additional algorithm-specific parameters and options used by the
+ * {@code CertPathValidator} when checking the revocation status of
+ * certificates. Here is an example demonstrating how it is used with the PKIX
+ * algorithm:
+ *
+ * <pre>
+ * CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpv.getRevocationChecker();
+ * rc.setOptions(EnumSet.of(Option.SOFT_FAIL));
+ * params.addCertPathChecker(rc);
+ * CertPathValidatorResult cpvr = cpv.validate(path, params);
+ * </pre>
+ *
+ * <p> Android provides the following {@code CertPathValidator} algorithms:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>PKIX</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * This algorithm is described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathValidator">
+ * CertPathValidator section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * The static methods of this class are guaranteed to be thread-safe.
+ * Multiple threads may concurrently invoke the static methods defined in
+ * this class with no ill effects.
+ * <p>
+ * However, this is not true for the non-static methods defined by this class.
+ * Unless otherwise documented by a specific provider, threads that need to
+ * access a single {@code CertPathValidator} instance concurrently should
+ * synchronize amongst themselves and provide the necessary locking. Multiple
+ * threads each manipulating a different {@code CertPathValidator}
+ * instance need not synchronize.
+ *
+ * @see CertPath
+ *
+ * @since 1.4
+ * @author Yassir Elley
+ */
+public class CertPathValidator {
+
+ /*
+ * Constant to lookup in the Security properties file to determine
+ * the default certpathvalidator type. In the Security properties file,
+ * the default certpathvalidator type is given as:
+ * <pre>
+ * certpathvalidator.type=PKIX
+ * </pre>
+ */
+ private static final String CPV_TYPE = "certpathvalidator.type";
+ private final CertPathValidatorSpi validatorSpi;
+ private final Provider provider;
+ private final String algorithm;
+
+ /**
+ * Creates a {@code CertPathValidator} object of the given algorithm,
+ * and encapsulates the given provider implementation (SPI object) in it.
+ *
+ * @param validatorSpi the provider implementation
+ * @param provider the provider
+ * @param algorithm the algorithm name
+ */
+ protected CertPathValidator(CertPathValidatorSpi validatorSpi,
+ Provider provider, String algorithm)
+ {
+ this.validatorSpi = validatorSpi;
+ this.provider = provider;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * Returns a {@code CertPathValidator} object that implements the
+ * specified algorithm.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new CertPathValidator object encapsulating the
+ * CertPathValidatorSpi implementation from the first
+ * Provider that supports the specified algorithm is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the requested {@code CertPathValidator}
+ * algorithm. See the CertPathValidator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathValidator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @return a {@code CertPathValidator} object that implements the
+ * specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if no Provider supports a
+ * CertPathValidatorSpi implementation for the
+ * specified algorithm.
+ *
+ * @see java.security.Provider
+ */
+ public static CertPathValidator getInstance(String algorithm)
+ throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("CertPathValidator",
+ CertPathValidatorSpi.class, algorithm);
+ return new CertPathValidator((CertPathValidatorSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a {@code CertPathValidator} object that implements the
+ * specified algorithm.
+ *
+ * <p> A new CertPathValidator object encapsulating the
+ * CertPathValidatorSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param algorithm the name of the requested {@code CertPathValidator}
+ * algorithm. See the CertPathValidator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathValidator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a {@code CertPathValidator} object that implements the
+ * specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
+ * 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 {@code provider} is
+ * null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static CertPathValidator getInstance(String algorithm,
+ String provider) throws NoSuchAlgorithmException,
+ NoSuchProviderException {
+ Instance instance = GetInstance.getInstance("CertPathValidator",
+ CertPathValidatorSpi.class, algorithm, provider);
+ return new CertPathValidator((CertPathValidatorSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns a {@code CertPathValidator} object that implements the
+ * specified algorithm.
+ *
+ * <p> A new CertPathValidator object encapsulating the
+ * CertPathValidatorSpi 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 name of the requested {@code CertPathValidator}
+ * algorithm. See the CertPathValidator section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathValidator">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard algorithm names.
+ *
+ * @param provider the provider.
+ *
+ * @return a {@code CertPathValidator} object that implements the
+ * specified algorithm.
+ *
+ * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the {@code provider} is
+ * null.
+ *
+ * @see java.security.Provider
+ */
+ public static CertPathValidator getInstance(String algorithm,
+ Provider provider) throws NoSuchAlgorithmException {
+ Instance instance = GetInstance.getInstance("CertPathValidator",
+ CertPathValidatorSpi.class, algorithm, provider);
+ return new CertPathValidator((CertPathValidatorSpi)instance.impl,
+ instance.provider, algorithm);
+ }
+
+ /**
+ * Returns the {@code Provider} of this
+ * {@code CertPathValidator}.
+ *
+ * @return the {@code Provider} of this {@code CertPathValidator}
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Returns the algorithm name of this {@code CertPathValidator}.
+ *
+ * @return the algorithm name of this {@code CertPathValidator}
+ */
+ public final String getAlgorithm() {
+ return this.algorithm;
+ }
+
+ /**
+ * Validates the specified certification path using the specified
+ * algorithm parameter set.
+ * <p>
+ * The {@code CertPath} specified must be of a type that is
+ * supported by the validation algorithm, otherwise an
+ * {@code InvalidAlgorithmParameterException} will be thrown. For
+ * example, a {@code CertPathValidator} that implements the PKIX
+ * algorithm validates {@code CertPath} objects of type X.509.
+ *
+ * @param certPath the {@code CertPath} to be validated
+ * @param params the algorithm parameters
+ * @return the result of the validation algorithm
+ * @exception CertPathValidatorException if the {@code CertPath}
+ * does not validate
+ * @exception InvalidAlgorithmParameterException if the specified
+ * parameters or the type of the specified {@code CertPath} are
+ * inappropriate for this {@code CertPathValidator}
+ */
+ public final CertPathValidatorResult validate(CertPath certPath,
+ CertPathParameters params)
+ throws CertPathValidatorException, InvalidAlgorithmParameterException
+ {
+ return validatorSpi.engineValidate(certPath, params);
+ }
+
+ /**
+ * Returns the default {@code CertPathValidator} type as specified by
+ * the {@code certpathvalidator.type} security property, or the string
+ * {@literal "PKIX"} if no such property exists.
+ *
+ * <p>The default {@code CertPathValidator} type can be used by
+ * applications that do not want to use a hard-coded type when calling one
+ * of the {@code getInstance} methods, and want to provide a default
+ * type in case a user does not specify its own.
+ *
+ * <p>The default {@code CertPathValidator} type can be changed by
+ * setting the value of the {@code certpathvalidator.type} security
+ * property to the desired type.
+ *
+ * @see java.security.Security security properties
+ * @return the default {@code CertPathValidator} type as specified
+ * by the {@code certpathvalidator.type} security property, or the string
+ * {@literal "PKIX"} if no such property exists.
+ */
+ public final static String getDefaultType() {
+ String cpvtype =
+ AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(CPV_TYPE);
+ }
+ });
+ return (cpvtype == null) ? "PKIX" : cpvtype;
+ }
+
+ /**
+ * Returns a {@code CertPathChecker} that the encapsulated
+ * {@code CertPathValidatorSpi} implementation uses to check the revocation
+ * status of certificates. A PKIX implementation returns objects of
+ * type {@code PKIXRevocationChecker}. Each invocation of this method
+ * returns a new instance of {@code CertPathChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description for an example.
+ *
+ * @return a {@code CertPathChecker}
+ * @throws UnsupportedOperationException if the service provider does not
+ * support this method
+ * @since 1.8
+ */
+ public final CertPathChecker getRevocationChecker() {
+ return validatorSpi.engineGetRevocationChecker();
+ }
+}
diff --git a/java/security/cert/CertPathValidatorException.java b/java/security/cert/CertPathValidatorException.java
new file mode 100644
index 0000000..7e6b916
--- /dev/null
+++ b/java/security/cert/CertPathValidatorException.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.InvalidObjectException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.security.GeneralSecurityException;
+
+/**
+ * An exception indicating one of a variety of problems encountered when
+ * validating a certification path.
+ * <p>
+ * A {@code CertPathValidatorException} provides support for wrapping
+ * exceptions. The {@link #getCause getCause} method returns the throwable,
+ * if any, that caused this exception to be thrown.
+ * <p>
+ * A {@code CertPathValidatorException} may also include the
+ * certification path that was being validated when the exception was thrown,
+ * the index of the certificate in the certification path that caused the
+ * exception to be thrown, and the reason that caused the failure. Use the
+ * {@link #getCertPath getCertPath}, {@link #getIndex getIndex}, and
+ * {@link #getReason getReason} methods to retrieve this information.
+ *
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathValidator
+ *
+ * @since 1.4
+ * @author Yassir Elley
+ */
+public class CertPathValidatorException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -3083180014971893139L;
+
+ /**
+ * @serial the index of the certificate in the certification path
+ * that caused the exception to be thrown
+ */
+ private int index = -1;
+
+ /**
+ * @serial the {@code CertPath} that was being validated when
+ * the exception was thrown
+ */
+ private CertPath certPath;
+
+ /**
+ * @serial the reason the validation failed
+ */
+ private Reason reason = BasicReason.UNSPECIFIED;
+
+ /**
+ * Creates a {@code CertPathValidatorException} with
+ * no detail message.
+ */
+ public CertPathValidatorException() {
+ this(null, null);
+ }
+
+ /**
+ * Creates a {@code CertPathValidatorException} with the given
+ * detail message. A detail message is a {@code String} that
+ * describes this particular exception.
+ *
+ * @param msg the detail message
+ */
+ public CertPathValidatorException(String msg) {
+ this(msg, null);
+ }
+
+ /**
+ * Creates a {@code CertPathValidatorException} that wraps the
+ * specified throwable. This allows any exception to be converted into a
+ * {@code CertPathValidatorException}, while retaining information
+ * about the wrapped exception, which may be useful for debugging. The
+ * detail message is set to ({@code cause==null ? null : cause.toString()})
+ * (which typically contains the class and detail message of
+ * cause).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or unknown.)
+ */
+ public CertPathValidatorException(Throwable cause) {
+ this((cause == null ? null : cause.toString()), cause);
+ }
+
+ /**
+ * Creates a {@code CertPathValidatorException} with the specified
+ * detail message and cause.
+ *
+ * @param msg the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or unknown.)
+ */
+ public CertPathValidatorException(String msg, Throwable cause) {
+ this(msg, cause, null, -1);
+ }
+
+ /**
+ * Creates a {@code CertPathValidatorException} with the specified
+ * detail message, cause, certification path, and index.
+ *
+ * @param msg the detail message (or {@code null} if none)
+ * @param cause the cause (or {@code null} if none)
+ * @param certPath the certification path that was in the process of
+ * being validated when the error was encountered
+ * @param index the index of the certificate in the certification path
+ * that caused the error (or -1 if not applicable). Note that
+ * the list of certificates in a {@code CertPath} is zero based.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * {@code (index < -1 || (certPath != null && index >=
+ * certPath.getCertificates().size()) }
+ * @throws IllegalArgumentException if {@code certPath} is
+ * {@code null} and {@code index} is not -1
+ */
+ public CertPathValidatorException(String msg, Throwable cause,
+ CertPath certPath, int index) {
+ this(msg, cause, certPath, index, BasicReason.UNSPECIFIED);
+ }
+
+ /**
+ * Creates a {@code CertPathValidatorException} with the specified
+ * detail message, cause, certification path, index, and reason.
+ *
+ * @param msg the detail message (or {@code null} if none)
+ * @param cause the cause (or {@code null} if none)
+ * @param certPath the certification path that was in the process of
+ * being validated when the error was encountered
+ * @param index the index of the certificate in the certification path
+ * that caused the error (or -1 if not applicable). Note that
+ * the list of certificates in a {@code CertPath} is zero based.
+ * @param reason the reason the validation failed
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * {@code (index < -1 || (certPath != null && index >=
+ * certPath.getCertificates().size()) }
+ * @throws IllegalArgumentException if {@code certPath} is
+ * {@code null} and {@code index} is not -1
+ * @throws NullPointerException if {@code reason} is {@code null}
+ *
+ * @since 1.7
+ */
+ public CertPathValidatorException(String msg, Throwable cause,
+ CertPath certPath, int index, Reason reason) {
+ super(msg, cause);
+ if (certPath == null && index != -1) {
+ throw new IllegalArgumentException();
+ }
+ if (index < -1 ||
+ (certPath != null && index >= certPath.getCertificates().size())) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (reason == null) {
+ throw new NullPointerException("reason can't be null");
+ }
+ this.certPath = certPath;
+ this.index = index;
+ this.reason = reason;
+ }
+
+ /**
+ * Returns the certification path that was being validated when
+ * the exception was thrown.
+ *
+ * @return the {@code CertPath} that was being validated when
+ * the exception was thrown (or {@code null} if not specified)
+ */
+ public CertPath getCertPath() {
+ return this.certPath;
+ }
+
+ /**
+ * Returns the index of the certificate in the certification path
+ * that caused the exception to be thrown. Note that the list of
+ * certificates in a {@code CertPath} is zero based. If no
+ * index has been set, -1 is returned.
+ *
+ * @return the index that has been set, or -1 if none has been set
+ */
+ public int getIndex() {
+ return this.index;
+ }
+
+ /**
+ * Returns the reason that the validation failed. The reason is
+ * associated with the index of the certificate returned by
+ * {@link #getIndex}.
+ *
+ * @return the reason that the validation failed, or
+ * {@code BasicReason.UNSPECIFIED} if a reason has not been
+ * specified
+ *
+ * @since 1.7
+ */
+ public Reason getReason() {
+ return this.reason;
+ }
+
+ private void readObject(ObjectInputStream stream)
+ throws ClassNotFoundException, IOException {
+ stream.defaultReadObject();
+ if (reason == null) {
+ reason = BasicReason.UNSPECIFIED;
+ }
+ if (certPath == null && index != -1) {
+ throw new InvalidObjectException("certpath is null and index != -1");
+ }
+ if (index < -1 ||
+ (certPath != null && index >= certPath.getCertificates().size())) {
+ throw new InvalidObjectException("index out of range");
+ }
+ }
+
+ /**
+ * The reason the validation algorithm failed.
+ *
+ * @since 1.7
+ */
+ public static interface Reason extends java.io.Serializable { }
+
+
+ /**
+ * The BasicReason enumerates the potential reasons that a certification
+ * path of any type may be invalid.
+ *
+ * @since 1.7
+ */
+ public static enum BasicReason implements Reason {
+ /**
+ * Unspecified reason.
+ */
+ UNSPECIFIED,
+
+ /**
+ * The certificate is expired.
+ */
+ EXPIRED,
+
+ /**
+ * The certificate is not yet valid.
+ */
+ NOT_YET_VALID,
+
+ /**
+ * The certificate is revoked.
+ */
+ REVOKED,
+
+ /**
+ * The revocation status of the certificate could not be determined.
+ */
+ UNDETERMINED_REVOCATION_STATUS,
+
+ /**
+ * The signature is invalid.
+ */
+ INVALID_SIGNATURE,
+
+ /**
+ * The public key or the signature algorithm has been constrained.
+ */
+ ALGORITHM_CONSTRAINED
+ }
+}
diff --git a/java/security/cert/CertPathValidatorResult.java b/java/security/cert/CertPathValidatorResult.java
new file mode 100644
index 0000000..ae07dc4
--- /dev/null
+++ b/java/security/cert/CertPathValidatorResult.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * A specification of the result of a certification path validator algorithm.
+ * <p>
+ * The purpose of this interface is to group (and provide type safety
+ * for) all certification path validator results. All results returned
+ * by the {@link CertPathValidator#validate CertPathValidator.validate}
+ * method must implement this interface.
+ *
+ * @see CertPathValidator
+ *
+ * @since 1.4
+ * @author Yassir Elley
+ */
+public interface CertPathValidatorResult extends Cloneable {
+
+ /**
+ * Makes a copy of this {@code CertPathValidatorResult}. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this {@code CertPathValidatorResult}
+ */
+ Object clone();
+}
diff --git a/java/security/cert/CertPathValidatorSpi.java b/java/security/cert/CertPathValidatorSpi.java
new file mode 100644
index 0000000..02d503c
--- /dev/null
+++ b/java/security/cert/CertPathValidatorSpi.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ *
+ * The <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@link CertPathValidator CertPathValidator} class. All
+ * {@code CertPathValidator} implementations must include a class (the
+ * SPI class) that extends this class ({@code CertPathValidatorSpi})
+ * and implements all of its methods. In general, instances of this class
+ * should only be accessed through the {@code CertPathValidator} class.
+ * For details, see the Java Cryptography Architecture.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Instances of this class need not be protected against concurrent
+ * access from multiple threads. Threads that need to access a single
+ * {@code CertPathValidatorSpi} instance concurrently should synchronize
+ * amongst themselves and provide the necessary locking before calling the
+ * wrapping {@code CertPathValidator} object.
+ * <p>
+ * However, implementations of {@code CertPathValidatorSpi} may still
+ * encounter concurrency issues, since multiple threads each
+ * manipulating a different {@code CertPathValidatorSpi} instance need not
+ * synchronize.
+ *
+ * @since 1.4
+ * @author Yassir Elley
+ */
+public abstract class CertPathValidatorSpi {
+
+ /**
+ * The default constructor.
+ */
+ public CertPathValidatorSpi() {}
+
+ /**
+ * Validates the specified certification path using the specified
+ * algorithm parameter set.
+ * <p>
+ * The {@code CertPath} specified must be of a type that is
+ * supported by the validation algorithm, otherwise an
+ * {@code InvalidAlgorithmParameterException} will be thrown. For
+ * example, a {@code CertPathValidator} that implements the PKIX
+ * algorithm validates {@code CertPath} objects of type X.509.
+ *
+ * @param certPath the {@code CertPath} to be validated
+ * @param params the algorithm parameters
+ * @return the result of the validation algorithm
+ * @exception CertPathValidatorException if the {@code CertPath}
+ * does not validate
+ * @exception InvalidAlgorithmParameterException if the specified
+ * parameters or the type of the specified {@code CertPath} are
+ * inappropriate for this {@code CertPathValidator}
+ */
+ public abstract CertPathValidatorResult
+ engineValidate(CertPath certPath, CertPathParameters params)
+ throws CertPathValidatorException, InvalidAlgorithmParameterException;
+
+ /**
+ * Returns a {@code CertPathChecker} that this implementation uses to
+ * check the revocation status of certificates. A PKIX implementation
+ * returns objects of type {@code PKIXRevocationChecker}.
+ *
+ * <p>The primary purpose of this method is to allow callers to specify
+ * additional input parameters and options specific to revocation checking.
+ * See the class description of {@code CertPathValidator} for an example.
+ *
+ * <p>This method was added to version 1.8 of the Java Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method cannot be abstract and by default throws
+ * an {@code UnsupportedOperationException}.
+ *
+ * @return a {@code CertPathChecker} that this implementation uses to
+ * check the revocation status of certificates
+ * @throws UnsupportedOperationException if this method is not supported
+ * @since 1.8
+ */
+ public CertPathChecker engineGetRevocationChecker() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/java/security/cert/CertSelector.java b/java/security/cert/CertSelector.java
new file mode 100644
index 0000000..a06cc84
--- /dev/null
+++ b/java/security/cert/CertSelector.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * A selector that defines a set of criteria for selecting
+ * {@code Certificate}s. Classes that implement this interface
+ * are often used to specify which {@code Certificate}s should
+ * be retrieved from a {@code CertStore}.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this interface are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see Certificate
+ * @see CertStore
+ * @see CertStore#getCertificates
+ *
+ * @author Steve Hanna
+ * @since 1.4
+ */
+public interface CertSelector extends Cloneable {
+
+ /**
+ * Decides whether a {@code Certificate} should be selected.
+ *
+ * @param cert the {@code Certificate} to be checked
+ * @return {@code true} if the {@code Certificate}
+ * should be selected, {@code false} otherwise
+ */
+ boolean match(Certificate cert);
+
+ /**
+ * Makes a copy of this {@code CertSelector}. Changes to the
+ * copy will not affect the original and vice versa.
+ *
+ * @return a copy of this {@code CertSelector}
+ */
+ Object clone();
+}
diff --git a/java/security/cert/CertStore.java b/java/security/cert/CertStore.java
new file mode 100644
index 0000000..047af77
--- /dev/null
+++ b/java/security/cert/CertStore.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Collection;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * A class for retrieving {@code Certificate}s and {@code CRL}s
+ * from a repository.
+ * <p>
+ * This class uses a provider-based architecture.
+ * To create a {@code CertStore}, call one of the static
+ * {@code getInstance} methods, passing in the type of
+ * {@code CertStore} desired, any applicable initialization parameters
+ * and optionally the name of the provider desired.
+ * <p>
+ * Once the {@code CertStore} has been created, it can be used to
+ * retrieve {@code Certificate}s and {@code CRL}s by calling its
+ * {@link #getCertificates(CertSelector selector) getCertificates} and
+ * {@link #getCRLs(CRLSelector selector) getCRLs} methods.
+ * <p>
+ * Unlike a {@link java.security.KeyStore KeyStore}, which provides access
+ * to a cache of private keys and trusted certificates, a
+ * {@code CertStore} is designed to provide access to a potentially
+ * vast repository of untrusted certificates and CRLs. For example, an LDAP
+ * implementation of {@code CertStore} provides access to certificates
+ * and CRLs stored in one or more directories using the LDAP protocol and the
+ * schema as defined in the RFC service attribute.
+ *
+ * <p> Android provides the following <code>CertStore</code> types:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>Collection</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * This type is described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
+ * CertStore section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * All public methods of {@code CertStore} objects must be thread-safe.
+ * That is, multiple threads may concurrently invoke these methods on a
+ * single {@code CertStore} object (or more than one) with no
+ * ill effects. This allows a {@code CertPathBuilder} to search for a
+ * CRL while simultaneously searching for further certificates, for instance.
+ * <p>
+ * The static methods of this class are also guaranteed to be thread-safe.
+ * Multiple threads may concurrently invoke the static methods defined in
+ * this class with no ill effects.
+ *
+ * @since 1.4
+ * @author Sean Mullan, Steve Hanna
+ */
+public class CertStore {
+ /*
+ * Constant to lookup in the Security properties file to determine
+ * the default certstore type. In the Security properties file, the
+ * default certstore type is given as:
+ * <pre>
+ * certstore.type=LDAP
+ * </pre>
+ */
+ private static final String CERTSTORE_TYPE = "certstore.type";
+ private CertStoreSpi storeSpi;
+ private Provider provider;
+ private String type;
+ private CertStoreParameters params;
+
+ /**
+ * Creates a {@code CertStore} object of the given type, and
+ * encapsulates the given provider implementation (SPI object) in it.
+ *
+ * @param storeSpi the provider implementation
+ * @param provider the provider
+ * @param type the type
+ * @param params the initialization parameters (may be {@code null})
+ */
+ protected CertStore(CertStoreSpi storeSpi, Provider provider,
+ String type, CertStoreParameters params) {
+ this.storeSpi = storeSpi;
+ this.provider = provider;
+ this.type = type;
+ if (params != null)
+ this.params = (CertStoreParameters) params.clone();
+ }
+
+ /**
+ * Returns a {@code Collection} of {@code Certificate}s that
+ * match the specified selector. If no {@code Certificate}s
+ * match the selector, an empty {@code Collection} will be returned.
+ * <p>
+ * For some {@code CertStore} types, the resulting
+ * {@code Collection} may not contain <b>all</b> of the
+ * {@code Certificate}s that match the selector. For instance,
+ * an LDAP {@code CertStore} may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the {@code Certificate}s it is looking for.
+ * <p>
+ * Some {@code CertStore} implementations (especially LDAP
+ * {@code CertStore}s) may throw a {@code CertStoreException}
+ * unless a non-null {@code CertSelector} is provided that
+ * includes specific criteria that can be used to find the certificates.
+ * Issuer and/or subject names are especially useful criteria.
+ *
+ * @param selector A {@code CertSelector} used to select which
+ * {@code Certificate}s should be returned. Specify {@code null}
+ * to return all {@code Certificate}s (if supported).
+ * @return A {@code Collection} of {@code Certificate}s that
+ * match the specified selector (never {@code null})
+ * @throws CertStoreException if an exception occurs
+ */
+ public final Collection<? extends Certificate> getCertificates
+ (CertSelector selector) throws CertStoreException {
+ return storeSpi.engineGetCertificates(selector);
+ }
+
+ /**
+ * Returns a {@code Collection} of {@code CRL}s that
+ * match the specified selector. If no {@code CRL}s
+ * match the selector, an empty {@code Collection} will be returned.
+ * <p>
+ * For some {@code CertStore} types, the resulting
+ * {@code Collection} may not contain <b>all</b> of the
+ * {@code CRL}s that match the selector. For instance,
+ * an LDAP {@code CertStore} may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the {@code CRL}s it is looking for.
+ * <p>
+ * Some {@code CertStore} implementations (especially LDAP
+ * {@code CertStore}s) may throw a {@code CertStoreException}
+ * unless a non-null {@code CRLSelector} is provided that
+ * includes specific criteria that can be used to find the CRLs.
+ * Issuer names and/or the certificate to be checked are especially useful.
+ *
+ * @param selector A {@code CRLSelector} used to select which
+ * {@code CRL}s should be returned. Specify {@code null}
+ * to return all {@code CRL}s (if supported).
+ * @return A {@code Collection} of {@code CRL}s that
+ * match the specified selector (never {@code null})
+ * @throws CertStoreException if an exception occurs
+ */
+ public final Collection<? extends CRL> getCRLs(CRLSelector selector)
+ throws CertStoreException {
+ return storeSpi.engineGetCRLs(selector);
+ }
+
+ /**
+ * Returns a {@code CertStore} object that implements the specified
+ * {@code CertStore} type and is initialized with the specified
+ * parameters.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new CertStore object encapsulating the
+ * CertStoreSpi implementation from the first
+ * Provider that supports the specified type is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p>The {@code CertStore} that is returned is initialized with the
+ * specified {@code CertStoreParameters}. The type of parameters
+ * needed may vary between different types of {@code CertStore}s.
+ * Note that the specified {@code CertStoreParameters} object is
+ * cloned.
+ *
+ * @param type the name of the requested {@code CertStore} type.
+ * See the CertStore section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard types.
+ *
+ * @param params the initialization parameters (may be {@code null}).
+ *
+ * @return a {@code CertStore} object that implements the specified
+ * {@code CertStore} type.
+ *
+ * @throws NoSuchAlgorithmException if no Provider supports a
+ * CertStoreSpi implementation for the specified type.
+ *
+ * @throws InvalidAlgorithmParameterException if the specified
+ * initialization parameters are inappropriate for this
+ * {@code CertStore}.
+ *
+ * @see java.security.Provider
+ */
+ public static CertStore getInstance(String type, CertStoreParameters params)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException {
+ try {
+ Instance instance = GetInstance.getInstance("CertStore",
+ CertStoreSpi.class, type, params);
+ return new CertStore((CertStoreSpi)instance.impl,
+ instance.provider, type, params);
+ } catch (NoSuchAlgorithmException e) {
+ return handleException(e);
+ }
+ }
+
+ private static CertStore handleException(NoSuchAlgorithmException e)
+ throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+ Throwable cause = e.getCause();
+ if (cause instanceof InvalidAlgorithmParameterException) {
+ throw (InvalidAlgorithmParameterException)cause;
+ }
+ throw e;
+ }
+
+ /**
+ * Returns a {@code CertStore} object that implements the specified
+ * {@code CertStore} type.
+ *
+ * <p> A new CertStore object encapsulating the
+ * CertStoreSpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * <p>The {@code CertStore} that is returned is initialized with the
+ * specified {@code CertStoreParameters}. The type of parameters
+ * needed may vary between different types of {@code CertStore}s.
+ * Note that the specified {@code CertStoreParameters} object is
+ * cloned.
+ *
+ * @param type the requested {@code CertStore} type.
+ * See the CertStore section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard types.
+ *
+ * @param params the initialization parameters (may be {@code null}).
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a {@code CertStore} object that implements the
+ * specified type.
+ *
+ * @throws NoSuchAlgorithmException if a CertStoreSpi
+ * implementation for the specified type is not
+ * available from the specified provider.
+ *
+ * @throws InvalidAlgorithmParameterException if the specified
+ * initialization parameters are inappropriate for this
+ * {@code CertStore}.
+ *
+ * @throws NoSuchProviderException if the specified provider is not
+ * registered in the security provider list.
+ *
+ * @exception IllegalArgumentException if the {@code provider} is
+ * null or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static CertStore getInstance(String type,
+ CertStoreParameters params, String provider)
+ throws InvalidAlgorithmParameterException,
+ NoSuchAlgorithmException, NoSuchProviderException {
+ try {
+ Instance instance = GetInstance.getInstance("CertStore",
+ CertStoreSpi.class, type, params, provider);
+ return new CertStore((CertStoreSpi)instance.impl,
+ instance.provider, type, params);
+ } catch (NoSuchAlgorithmException e) {
+ return handleException(e);
+ }
+ }
+
+ /**
+ * Returns a {@code CertStore} object that implements the specified
+ * {@code CertStore} type.
+ *
+ * <p> A new CertStore object encapsulating the
+ * CertStoreSpi implementation from the specified Provider
+ * object is returned. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * <p>The {@code CertStore} that is returned is initialized with the
+ * specified {@code CertStoreParameters}. The type of parameters
+ * needed may vary between different types of {@code CertStore}s.
+ * Note that the specified {@code CertStoreParameters} object is
+ * cloned.
+ *
+ * @param type the requested {@code CertStore} type.
+ * See the CertStore section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertStore">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard types.
+ *
+ * @param params the initialization parameters (may be {@code null}).
+ *
+ * @param provider the provider.
+ *
+ * @return a {@code CertStore} object that implements the
+ * specified type.
+ *
+ * @exception NoSuchAlgorithmException if a CertStoreSpi
+ * implementation for the specified type is not available
+ * from the specified Provider object.
+ *
+ * @throws InvalidAlgorithmParameterException if the specified
+ * initialization parameters are inappropriate for this
+ * {@code CertStore}
+ *
+ * @exception IllegalArgumentException if the {@code provider} is
+ * null.
+ *
+ * @see java.security.Provider
+ */
+ public static CertStore getInstance(String type, CertStoreParameters params,
+ Provider provider) throws NoSuchAlgorithmException,
+ InvalidAlgorithmParameterException {
+ try {
+ Instance instance = GetInstance.getInstance("CertStore",
+ CertStoreSpi.class, type, params, provider);
+ return new CertStore((CertStoreSpi)instance.impl,
+ instance.provider, type, params);
+ } catch (NoSuchAlgorithmException e) {
+ return handleException(e);
+ }
+ }
+
+ /**
+ * Returns the parameters used to initialize this {@code CertStore}.
+ * Note that the {@code CertStoreParameters} object is cloned before
+ * it is returned.
+ *
+ * @return the parameters used to initialize this {@code CertStore}
+ * (may be {@code null})
+ */
+ public final CertStoreParameters getCertStoreParameters() {
+ return (params == null ? null : (CertStoreParameters) params.clone());
+ }
+
+ /**
+ * Returns the type of this {@code CertStore}.
+ *
+ * @return the type of this {@code CertStore}
+ */
+ public final String getType() {
+ return this.type;
+ }
+
+ /**
+ * Returns the provider of this {@code CertStore}.
+ *
+ * @return the provider of this {@code CertStore}
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Returns the default {@code CertStore} type as specified by the
+ * {@code certstore.type} security property, or the string
+ * {@literal "LDAP"} if no such property exists.
+ *
+ * <p>The default {@code CertStore} type can be used by applications
+ * that do not want to use a hard-coded type when calling one of the
+ * {@code getInstance} methods, and want to provide a default
+ * {@code CertStore} type in case a user does not specify its own.
+ *
+ * <p>The default {@code CertStore} type can be changed by setting
+ * the value of the {@code certstore.type} security property to the
+ * desired type.
+ *
+ * @see java.security.Security security properties
+ * @return the default {@code CertStore} type as specified by the
+ * {@code certstore.type} security property, or the string
+ * {@literal "LDAP"} if no such property exists.
+ */
+ public final static String getDefaultType() {
+ String cstype;
+ cstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return Security.getProperty(CERTSTORE_TYPE);
+ }
+ });
+ if (cstype == null) {
+ cstype = "LDAP";
+ }
+ return cstype;
+ }
+}
diff --git a/java/security/cert/CertStoreException.java b/java/security/cert/CertStoreException.java
new file mode 100644
index 0000000..77b1c23
--- /dev/null
+++ b/java/security/cert/CertStoreException.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * An exception indicating one of a variety of problems retrieving
+ * certificates and CRLs from a {@code CertStore}.
+ * <p>
+ * A {@code CertStoreException} provides support for wrapping
+ * exceptions. The {@link #getCause getCause} method returns the throwable,
+ * if any, that caused this exception to be thrown.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertStore
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public class CertStoreException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 2395296107471573245L;
+
+ /**
+ * Creates a {@code CertStoreException} with {@code null} as
+ * its detail message.
+ */
+ public CertStoreException() {
+ super();
+ }
+
+ /**
+ * Creates a {@code CertStoreException} with the given detail
+ * message. A detail message is a {@code String} that describes this
+ * particular exception.
+ *
+ * @param msg the detail message
+ */
+ public CertStoreException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code CertStoreException} that wraps the specified
+ * throwable. This allows any exception to be converted into a
+ * {@code CertStoreException}, while retaining information about the
+ * cause, which may be useful for debugging. The detail message is
+ * set to ({@code cause==null ? null : cause.toString()}) (which
+ * typically contains the class and detail message of cause).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or unknown.)
+ */
+ public CertStoreException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Creates a {@code CertStoreException} with the specified detail
+ * message and cause.
+ *
+ * @param msg the detail message
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or unknown.)
+ */
+ public CertStoreException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/java/security/cert/CertStoreParameters.java b/java/security/cert/CertStoreParameters.java
new file mode 100644
index 0000000..9938ba2
--- /dev/null
+++ b/java/security/cert/CertStoreParameters.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * A specification of {@code CertStore} parameters.
+ * <p>
+ * The purpose of this interface is to group (and provide type safety for)
+ * all {@code CertStore} parameter specifications. All
+ * {@code CertStore} parameter specifications must implement this
+ * interface.
+ * <p>
+ * Typically, a {@code CertStoreParameters} object is passed as a parameter
+ * to one of the {@link CertStore#getInstance CertStore.getInstance} methods.
+ * The {@code getInstance} method returns a {@code CertStore} that
+ * is used for retrieving {@code Certificate}s and {@code CRL}s. The
+ * {@code CertStore} that is returned is initialized with the specified
+ * parameters. The type of parameters needed may vary between different types
+ * of {@code CertStore}s.
+ *
+ * @see CertStore#getInstance
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ */
+public interface CertStoreParameters extends Cloneable {
+
+ /**
+ * Makes a copy of this {@code CertStoreParameters}.
+ * <p>
+ * The precise meaning of "copy" may depend on the class of
+ * the {@code CertStoreParameters} object. A typical implementation
+ * performs a "deep copy" of this object, but this is not an absolute
+ * requirement. Some implementations may perform a "shallow copy" of some
+ * or all of the fields of this object.
+ * <p>
+ * Note that the {@code CertStore.getInstance} methods make a copy
+ * of the specified {@code CertStoreParameters}. A deep copy
+ * implementation of {@code clone} is safer and more robust, as it
+ * prevents the caller from corrupting a shared {@code CertStore} by
+ * subsequently modifying the contents of its initialization parameters.
+ * However, a shallow copy implementation of {@code clone} is more
+ * appropriate for applications that need to hold a reference to a
+ * parameter contained in the {@code CertStoreParameters}. For example,
+ * a shallow copy clone allows an application to release the resources of
+ * a particular {@code CertStore} initialization parameter immediately,
+ * rather than waiting for the garbage collection mechanism. This should
+ * be done with the utmost care, since the {@code CertStore} may still
+ * be in use by other threads.
+ * <p>
+ * Each subclass should state the precise behavior of this method so
+ * that users and developers know what to expect.
+ *
+ * @return a copy of this {@code CertStoreParameters}
+ */
+ Object clone();
+}
diff --git a/java/security/cert/CertStoreSpi.java b/java/security/cert/CertStoreSpi.java
new file mode 100644
index 0000000..fc98e9e
--- /dev/null
+++ b/java/security/cert/CertStoreSpi.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.util.Collection;
+
+/**
+ * The <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@link CertStore CertStore} class. All {@code CertStore}
+ * implementations must include a class (the SPI class) that extends
+ * this class ({@code CertStoreSpi}), provides a constructor with
+ * a single argument of type {@code CertStoreParameters}, and implements
+ * all of its methods. In general, instances of this class should only be
+ * accessed through the {@code CertStore} class.
+ * For details, see the Java Cryptography Architecture.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * The public methods of all {@code CertStoreSpi} objects must be
+ * thread-safe. That is, multiple threads may concurrently invoke these
+ * methods on a single {@code CertStoreSpi} object (or more than one)
+ * with no ill effects. This allows a {@code CertPathBuilder} to search
+ * for a CRL while simultaneously searching for further certificates, for
+ * instance.
+ * <p>
+ * Simple {@code CertStoreSpi} implementations will probably ensure
+ * thread safety by adding a {@code synchronized} keyword to their
+ * {@code engineGetCertificates} and {@code engineGetCRLs} methods.
+ * More sophisticated ones may allow truly concurrent access.
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ */
+public abstract class CertStoreSpi {
+
+ /**
+ * The sole constructor.
+ *
+ * @param params the initialization parameters (may be {@code null})
+ * @throws InvalidAlgorithmParameterException if the initialization
+ * parameters are inappropriate for this {@code CertStoreSpi}
+ */
+ public CertStoreSpi(CertStoreParameters params)
+ throws InvalidAlgorithmParameterException { }
+
+ /**
+ * Returns a {@code Collection} of {@code Certificate}s that
+ * match the specified selector. If no {@code Certificate}s
+ * match the selector, an empty {@code Collection} will be returned.
+ * <p>
+ * For some {@code CertStore} types, the resulting
+ * {@code Collection} may not contain <b>all</b> of the
+ * {@code Certificate}s that match the selector. For instance,
+ * an LDAP {@code CertStore} may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the {@code Certificate}s it is looking for.
+ * <p>
+ * Some {@code CertStore} implementations (especially LDAP
+ * {@code CertStore}s) may throw a {@code CertStoreException}
+ * unless a non-null {@code CertSelector} is provided that includes
+ * specific criteria that can be used to find the certificates. Issuer
+ * and/or subject names are especially useful criteria.
+ *
+ * @param selector A {@code CertSelector} used to select which
+ * {@code Certificate}s should be returned. Specify {@code null}
+ * to return all {@code Certificate}s (if supported).
+ * @return A {@code Collection} of {@code Certificate}s that
+ * match the specified selector (never {@code null})
+ * @throws CertStoreException if an exception occurs
+ */
+ public abstract Collection<? extends Certificate> engineGetCertificates
+ (CertSelector selector) throws CertStoreException;
+
+ /**
+ * Returns a {@code Collection} of {@code CRL}s that
+ * match the specified selector. If no {@code CRL}s
+ * match the selector, an empty {@code Collection} will be returned.
+ * <p>
+ * For some {@code CertStore} types, the resulting
+ * {@code Collection} may not contain <b>all</b> of the
+ * {@code CRL}s that match the selector. For instance,
+ * an LDAP {@code CertStore} may not search all entries in the
+ * directory. Instead, it may just search entries that are likely to
+ * contain the {@code CRL}s it is looking for.
+ * <p>
+ * Some {@code CertStore} implementations (especially LDAP
+ * {@code CertStore}s) may throw a {@code CertStoreException}
+ * unless a non-null {@code CRLSelector} is provided that includes
+ * specific criteria that can be used to find the CRLs. Issuer names
+ * and/or the certificate to be checked are especially useful.
+ *
+ * @param selector A {@code CRLSelector} used to select which
+ * {@code CRL}s should be returned. Specify {@code null}
+ * to return all {@code CRL}s (if supported).
+ * @return A {@code Collection} of {@code CRL}s that
+ * match the specified selector (never {@code null})
+ * @throws CertStoreException if an exception occurs
+ */
+ public abstract Collection<? extends CRL> engineGetCRLs
+ (CRLSelector selector) throws CertStoreException;
+}
diff --git a/java/security/cert/Certificate.java b/java/security/cert/Certificate.java
new file mode 100644
index 0000000..5ded604
--- /dev/null
+++ b/java/security/cert/Certificate.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.util.Arrays;
+
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * <p>Abstract class for managing a variety of identity certificates.
+ * An identity certificate is a binding of a principal to a public key which
+ * is vouched for by another principal. (A principal represents
+ * an entity such as an individual user, a group, or a corporation.)
+ *<p>
+ * This class is an abstraction for certificates that have different
+ * formats but important common uses. For example, different types of
+ * certificates, such as X.509 and PGP, share general certificate
+ * functionality (like encoding and verifying) and
+ * some types of information (like a public key).
+ * <p>
+ * X.509, PGP, and SDSI certificates can all be implemented by
+ * subclassing the Certificate class, even though they contain different
+ * sets of information, and they store and retrieve the information in
+ * different ways.
+ *
+ * @see X509Certificate
+ * @see CertificateFactory
+ *
+ * @author Hemma Prafullchandra
+ */
+
+public abstract class Certificate implements java.io.Serializable {
+
+ private static final long serialVersionUID = -3585440601605666277L;
+
+ // the certificate type
+ private final String type;
+
+ /** Cache the hash code for the certiticate */
+ private int hash = -1; // Default to -1
+
+ /**
+ * Creates a certificate of the specified type.
+ *
+ * @param type the standard name of the certificate type.
+ * See the CertificateFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertificateFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard certificate types.
+ */
+ protected Certificate(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the type of this certificate.
+ *
+ * @return the type of this certificate.
+ */
+ public final String getType() {
+ return this.type;
+ }
+
+ /**
+ * Compares this certificate for equality with the specified
+ * object. If the {@code other} object is an
+ * {@code instanceof} {@code Certificate}, then
+ * its encoded form is retrieved and compared with the
+ * encoded form of this certificate.
+ *
+ * @param other the object to test for equality with this certificate.
+ * @return true iff the encoded forms of the two certificates
+ * match, false otherwise.
+ */
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Certificate)) {
+ return false;
+ }
+ try {
+ byte[] thisCert = X509CertImpl.getEncodedInternal(this);
+ byte[] otherCert = X509CertImpl.getEncodedInternal((Certificate)other);
+
+ return Arrays.equals(thisCert, otherCert);
+ } catch (CertificateException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a hashcode value for this certificate from its
+ * encoded form.
+ *
+ * @return the hashcode value.
+ */
+ public int hashCode() {
+ int h = hash;
+ if (h == -1) {
+ try {
+ h = Arrays.hashCode(X509CertImpl.getEncodedInternal(this));
+ } catch (CertificateException e) {
+ h = 0;
+ }
+ hash = h;
+ }
+ return h;
+ }
+
+ /**
+ * Returns the encoded form of this certificate. It is
+ * assumed that each certificate type would have only a single
+ * form of encoding; for example, X.509 certificates would
+ * be encoded as ASN.1 DER.
+ *
+ * @return the encoded form of this certificate
+ *
+ * @exception CertificateEncodingException if an encoding error occurs.
+ */
+ public abstract byte[] getEncoded()
+ throws CertificateEncodingException;
+
+ /**
+ * Verifies that this certificate was signed using the
+ * private key that corresponds to the specified public key.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception NoSuchProviderException if there's no default provider.
+ * @exception SignatureException on signature errors.
+ * @exception CertificateException on encoding errors.
+ */
+ public abstract void verify(PublicKey key)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException;
+
+ /**
+ * Verifies that this certificate was signed using the
+ * private key that corresponds to the specified public key.
+ * This method uses the signature verification engine
+ * supplied by the specified provider.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ * @param sigProvider the name of the signature provider.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception NoSuchProviderException on incorrect provider.
+ * @exception SignatureException on signature errors.
+ * @exception CertificateException on encoding errors.
+ */
+ public abstract void verify(PublicKey key, String sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException;
+
+ /**
+ * Verifies that this certificate was signed using the
+ * private key that corresponds to the specified public key.
+ * This method uses the signature verification engine
+ * supplied by the specified provider. Note that the specified
+ * Provider object does not have to be registered in the provider list.
+ *
+ * <p> This method was added to version 1.8 of the Java Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be {@code abstract}
+ * and by default throws an {@code UnsupportedOperationException}.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ * @param sigProvider the signature provider.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception SignatureException on signature errors.
+ * @exception CertificateException on encoding errors.
+ * @exception UnsupportedOperationException if the method is not supported
+ * @since 1.8
+ */
+ public void verify(PublicKey key, Provider sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a string representation of this certificate.
+ *
+ * @return a string representation of this certificate.
+ */
+ public abstract String toString();
+
+ /**
+ * Gets the public key from this certificate.
+ *
+ * @return the public key.
+ */
+ public abstract PublicKey getPublicKey();
+
+ /**
+ * Alternate Certificate class for serialization.
+ * @since 1.3
+ */
+ protected static class CertificateRep implements java.io.Serializable {
+
+ private static final long serialVersionUID = -8563758940495660020L;
+
+ private String type;
+ private byte[] data;
+
+ /**
+ * Construct the alternate Certificate class with the Certificate
+ * type and Certificate encoding bytes.
+ *
+ * <p>
+ *
+ * @param type the standard name of the Certificate type. <p>
+ *
+ * @param data the Certificate data.
+ */
+ protected CertificateRep(String type, byte[] data) {
+ this.type = type;
+ this.data = data;
+ }
+
+ /**
+ * Resolve the Certificate Object.
+ *
+ * <p>
+ *
+ * @return the resolved Certificate Object
+ *
+ * @throws java.io.ObjectStreamException if the Certificate
+ * could not be resolved
+ */
+ protected Object readResolve() throws java.io.ObjectStreamException {
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance(type);
+ return cf.generateCertificate
+ (new java.io.ByteArrayInputStream(data));
+ } catch (CertificateException e) {
+ throw new java.io.NotSerializableException
+ ("java.security.cert.Certificate: " +
+ type +
+ ": " +
+ e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Replace the Certificate to be serialized.
+ *
+ * @return the alternate Certificate object to be serialized
+ *
+ * @throws java.io.ObjectStreamException if a new object representing
+ * this Certificate could not be created
+ * @since 1.3
+ */
+ protected Object writeReplace() throws java.io.ObjectStreamException {
+ try {
+ return new CertificateRep(type, getEncoded());
+ } catch (CertificateException e) {
+ throw new java.io.NotSerializableException
+ ("java.security.cert.Certificate: " +
+ type +
+ ": " +
+ e.getMessage());
+ }
+ }
+}
diff --git a/java/security/cert/CertificateEncodingException.java b/java/security/cert/CertificateEncodingException.java
new file mode 100644
index 0000000..618ee0a
--- /dev/null
+++ b/java/security/cert/CertificateEncodingException.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * Certificate Encoding Exception. This is thrown whenever an error
+ * occurs while attempting to encode a certificate.
+ *
+ * @author Hemma Prafullchandra
+ */
+public class CertificateEncodingException extends CertificateException {
+
+ private static final long serialVersionUID = 6219492851589449162L;
+
+ /**
+ * Constructs a CertificateEncodingException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public CertificateEncodingException() {
+ super();
+ }
+
+ /**
+ * Constructs a CertificateEncodingException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param message the detail message.
+ */
+ public CertificateEncodingException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a {@code CertificateEncodingException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CertificateEncodingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code CertificateEncodingException}
+ * with the specified cause and a detail message of
+ * {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CertificateEncodingException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/cert/CertificateException.java b/java/security/cert/CertificateException.java
new file mode 100644
index 0000000..f663054
--- /dev/null
+++ b/java/security/cert/CertificateException.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This exception indicates one of a variety of certificate problems.
+ *
+ * @author Hemma Prafullchandra
+ * @see Certificate
+ */
+public class CertificateException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 3192535253797119798L;
+
+ /**
+ * Constructs a certificate exception with no detail message. A detail
+ * message is a String that describes this particular exception.
+ */
+ public CertificateException() {
+ super();
+ }
+
+ /**
+ * Constructs a certificate exception with the given detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public CertificateException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code CertificateException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CertificateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code CertificateException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CertificateException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/cert/CertificateExpiredException.java b/java/security/cert/CertificateExpiredException.java
new file mode 100644
index 0000000..9de0c23
--- /dev/null
+++ b/java/security/cert/CertificateExpiredException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * Certificate Expired Exception. This is thrown whenever the current
+ * {@code Date} or the specified {@code Date} is after the
+ * {@code notAfter} date/time specified in the validity period
+ * of the certificate.
+ *
+ * @author Hemma Prafullchandra
+ */
+public class CertificateExpiredException extends CertificateException {
+
+ private static final long serialVersionUID = 9071001339691533771L;
+
+ /**
+ * Constructs a CertificateExpiredException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public CertificateExpiredException() {
+ super();
+ }
+
+ /**
+ * Constructs a CertificateExpiredException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param message the detail message.
+ */
+ public CertificateExpiredException(String message) {
+ super(message);
+ }
+}
diff --git a/java/security/cert/CertificateFactory.java b/java/security/cert/CertificateFactory.java
new file mode 100644
index 0000000..e74ff0a
--- /dev/null
+++ b/java/security/cert/CertificateFactory.java
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.security.Provider;
+import java.security.Security;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+import sun.security.jca.*;
+import sun.security.jca.GetInstance.Instance;
+
+/**
+ * This class defines the functionality of a certificate factory, which is
+ * used to generate certificate, certification path ({@code CertPath})
+ * and certificate revocation list (CRL) objects from their encodings.
+ *
+ * <p>For encodings consisting of multiple certificates, use
+ * {@code generateCertificates} when you want to
+ * parse a collection of possibly unrelated certificates. Otherwise,
+ * use {@code generateCertPath} when you want to generate
+ * a {@code CertPath} (a certificate chain) and subsequently
+ * validate it with a {@code CertPathValidator}.
+ *
+ * <p>A certificate factory for X.509 must return certificates that are an
+ * instance of {@code java.security.cert.X509Certificate}, and CRLs
+ * that are an instance of {@code java.security.cert.X509CRL}.
+ *
+ * <p>The following example reads a file with Base64 encoded certificates,
+ * which are each bounded at the beginning by -----BEGIN CERTIFICATE-----, and
+ * bounded at the end by -----END CERTIFICATE-----. We convert the
+ * {@code FileInputStream} (which does not support {@code mark}
+ * and {@code reset}) to a {@code BufferedInputStream} (which
+ * supports those methods), so that each call to
+ * {@code generateCertificate} consumes only one certificate, and the
+ * read position of the input stream is positioned to the next certificate in
+ * the file:
+ *
+ * <pre>{@code
+ * FileInputStream fis = new FileInputStream(filename);
+ * BufferedInputStream bis = new BufferedInputStream(fis);
+ *
+ * CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ *
+ * while (bis.available() > 0) {
+ * Certificate cert = cf.generateCertificate(bis);
+ * System.out.println(cert.toString());
+ * }
+ * }</pre>
+ *
+ * <p>The following example parses a PKCS#7-formatted certificate reply stored
+ * in a file and extracts all the certificates from it:
+ *
+ * <pre>
+ * FileInputStream fis = new FileInputStream(filename);
+ * CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ * Collection c = cf.generateCertificates(fis);
+ * Iterator i = c.iterator();
+ * while (i.hasNext()) {
+ * Certificate cert = (Certificate)i.next();
+ * System.out.println(cert);
+ * }
+ * </pre>
+ *
+ * <p> Android provides the following <code>CertificateFactory</code> types:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Algorithm</th>
+ * <th>Supported API Levels</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>X.509</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ * and the following <code>CertPath</code> encodings:
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Name</th>
+ * <th>Supported (API Levels)</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>PKCS7</td>
+ * <td>1+</td>
+ * </tr>
+ * <tr>
+ * <td>PkiPath</td>
+ * <td>1+</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * The type and encodings are described in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertificateFactory">
+ * CertificateFactory section</a> and the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * CertPath Encodings section</a> of the
+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ *
+ * @author Hemma Prafullchandra
+ * @author Jan Luehe
+ * @author Sean Mullan
+ *
+ * @see Certificate
+ * @see X509Certificate
+ * @see CertPath
+ * @see CRL
+ * @see X509CRL
+ *
+ * @since 1.2
+ */
+
+public class CertificateFactory {
+
+ // The certificate type
+ private String type;
+
+ // The provider
+ private Provider provider;
+
+ // The provider implementation
+ private CertificateFactorySpi certFacSpi;
+
+ /**
+ * Creates a CertificateFactory object of the given type, and encapsulates
+ * the given provider implementation (SPI object) in it.
+ *
+ * @param certFacSpi the provider implementation.
+ * @param provider the provider.
+ * @param type the certificate type.
+ */
+ protected CertificateFactory(CertificateFactorySpi certFacSpi,
+ Provider provider, String type)
+ {
+ this.certFacSpi = certFacSpi;
+ this.provider = provider;
+ this.type = type;
+ }
+
+ /**
+ * Returns a certificate factory object that implements the
+ * specified certificate type.
+ *
+ * <p> This method traverses the list of registered security Providers,
+ * starting with the most preferred Provider.
+ * A new CertificateFactory object encapsulating the
+ * CertificateFactorySpi implementation from the first
+ * Provider that supports the specified type is returned.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param type the name of the requested certificate type.
+ * See the CertificateFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertificateFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard certificate types.
+ *
+ * @return a certificate factory object for the specified type.
+ *
+ * @exception CertificateException if no Provider supports a
+ * CertificateFactorySpi implementation for the
+ * specified type.
+ *
+ * @see java.security.Provider
+ */
+ public static final CertificateFactory getInstance(String type)
+ throws CertificateException {
+ try {
+ Instance instance = GetInstance.getInstance("CertificateFactory",
+ CertificateFactorySpi.class, type);
+ return new CertificateFactory((CertificateFactorySpi)instance.impl,
+ instance.provider, type);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CertificateException(type + " not found", e);
+ }
+ }
+
+ /**
+ * Returns a certificate factory object for the specified
+ * certificate type.
+ *
+ * <p> A new CertificateFactory object encapsulating the
+ * CertificateFactorySpi implementation from the specified provider
+ * is returned. The specified provider must be registered
+ * in the security provider list.
+ *
+ * <p> Note that the list of registered providers may be retrieved via
+ * the {@link Security#getProviders() Security.getProviders()} method.
+ *
+ * @param type the certificate type.
+ * See the CertificateFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertificateFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard certificate types.
+ *
+ * @param provider the name of the provider.
+ *
+ * @return a certificate factory object for the specified type.
+ *
+ * @exception CertificateException if a CertificateFactorySpi
+ * 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 name is null
+ * or empty.
+ *
+ * @see java.security.Provider
+ */
+ public static final CertificateFactory getInstance(String type,
+ String provider) throws CertificateException,
+ NoSuchProviderException {
+ try {
+ Instance instance = GetInstance.getInstance("CertificateFactory",
+ CertificateFactorySpi.class, type, provider);
+ return new CertificateFactory((CertificateFactorySpi)instance.impl,
+ instance.provider, type);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CertificateException(type + " not found", e);
+ }
+ }
+
+ /**
+ * Returns a certificate factory object for the specified
+ * certificate type.
+ *
+ * <p> A new CertificateFactory object encapsulating the
+ * CertificateFactorySpi 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 type the certificate type.
+ * See the CertificateFactory section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertificateFactory">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard certificate types.
+ * @param provider the provider.
+ *
+ * @return a certificate factory object for the specified type.
+ *
+ * @exception CertificateException if a CertificateFactorySpi
+ * implementation for the specified algorithm is not available
+ * from the specified Provider object.
+ *
+ * @exception IllegalArgumentException if the {@code provider} is
+ * null.
+ *
+ * @see java.security.Provider
+ *
+ * @since 1.4
+ */
+ public static final CertificateFactory getInstance(String type,
+ Provider provider) throws CertificateException {
+ try {
+ Instance instance = GetInstance.getInstance("CertificateFactory",
+ CertificateFactorySpi.class, type, provider);
+ return new CertificateFactory((CertificateFactorySpi)instance.impl,
+ instance.provider, type);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CertificateException(type + " not found", e);
+ }
+ }
+
+ /**
+ * Returns the provider of this certificate factory.
+ *
+ * @return the provider of this certificate factory.
+ */
+ public final Provider getProvider() {
+ return this.provider;
+ }
+
+ /**
+ * Returns the name of the certificate type associated with this
+ * certificate factory.
+ *
+ * @return the name of the certificate type associated with this
+ * certificate factory.
+ */
+ public final String getType() {
+ return this.type;
+ }
+
+ /**
+ * Generates a certificate object and initializes it with
+ * the data read from the input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized certificate format
+ * supported by this certificate factory,
+ * the returned certificate object can be typecast to the corresponding
+ * certificate class. For example, if this certificate
+ * factory implements X.509 certificates, the returned certificate object
+ * can be typecast to the {@code X509Certificate} class.
+ *
+ * <p>In the case of a certificate factory for X.509 certificates, the
+ * certificate provided in {@code inStream} must be DER-encoded and
+ * may be supplied in binary or printable (Base64) encoding. If the
+ * certificate is provided in Base64 encoding, it must be bounded at
+ * the beginning by -----BEGIN CERTIFICATE-----, and must be bounded at
+ * the end by -----END CERTIFICATE-----.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream. Otherwise, each call to this
+ * method consumes one certificate and the read position of the
+ * input stream is positioned to the next available byte after
+ * the inherent end-of-certificate marker. If the data in the input stream
+ * does not contain an inherent end-of-certificate marker (other
+ * than EOF) and there is trailing data after the certificate is parsed, a
+ * {@code CertificateException} is thrown.
+ *
+ * @param inStream an input stream with the certificate data.
+ *
+ * @return a certificate object initialized with the data
+ * from the input stream.
+ *
+ * @exception CertificateException on parsing errors.
+ */
+ public final Certificate generateCertificate(InputStream inStream)
+ throws CertificateException
+ {
+ return certFacSpi.engineGenerateCertificate(inStream);
+ }
+
+ /**
+ * Returns an iteration of the {@code CertPath} encodings supported
+ * by this certificate factory, with the default encoding first. See
+ * the CertPath Encodings section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard encoding names and their formats.
+ * <p>
+ * Attempts to modify the returned {@code Iterator} via its
+ * {@code remove} method result in an
+ * {@code UnsupportedOperationException}.
+ *
+ * @return an {@code Iterator} over the names of the supported
+ * {@code CertPath} encodings (as {@code String}s)
+ * @since 1.4
+ */
+ public final Iterator<String> getCertPathEncodings() {
+ return(certFacSpi.engineGetCertPathEncodings());
+ }
+
+ /**
+ * Generates a {@code CertPath} object and initializes it with
+ * the data read from the {@code InputStream} inStream. The data
+ * is assumed to be in the default encoding. The name of the default
+ * encoding is the first element of the {@code Iterator} returned by
+ * the {@link #getCertPathEncodings getCertPathEncodings} method.
+ *
+ * @param inStream an {@code InputStream} containing the data
+ * @return a {@code CertPath} initialized with the data from the
+ * {@code InputStream}
+ * @exception CertificateException if an exception occurs while decoding
+ * @since 1.4
+ */
+ public final CertPath generateCertPath(InputStream inStream)
+ throws CertificateException
+ {
+ return(certFacSpi.engineGenerateCertPath(inStream));
+ }
+
+ /**
+ * Generates a {@code CertPath} object and initializes it with
+ * the data read from the {@code InputStream} inStream. The data
+ * is assumed to be in the specified encoding. See
+ * the CertPath Encodings section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard encoding names and their formats.
+ *
+ * @param inStream an {@code InputStream} containing the data
+ * @param encoding the encoding used for the data
+ * @return a {@code CertPath} initialized with the data from the
+ * {@code InputStream}
+ * @exception CertificateException if an exception occurs while decoding or
+ * the encoding requested is not supported
+ * @since 1.4
+ */
+ public final CertPath generateCertPath(InputStream inStream,
+ String encoding) throws CertificateException
+ {
+ return(certFacSpi.engineGenerateCertPath(inStream, encoding));
+ }
+
+ /**
+ * Generates a {@code CertPath} object and initializes it with
+ * a {@code List} of {@code Certificate}s.
+ * <p>
+ * The certificates supplied must be of a type supported by the
+ * {@code CertificateFactory}. They will be copied out of the supplied
+ * {@code List} object.
+ *
+ * @param certificates a {@code List} of {@code Certificate}s
+ * @return a {@code CertPath} initialized with the supplied list of
+ * certificates
+ * @exception CertificateException if an exception occurs
+ * @since 1.4
+ */
+ public final CertPath
+ generateCertPath(List<? extends Certificate> certificates)
+ throws CertificateException
+ {
+ return(certFacSpi.engineGenerateCertPath(certificates));
+ }
+
+ /**
+ * Returns a (possibly empty) collection view of the certificates read
+ * from the given input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized certificate format
+ * supported by this certificate factory, each element in
+ * the returned collection view can be typecast to the corresponding
+ * certificate class. For example, if this certificate
+ * factory implements X.509 certificates, the elements in the returned
+ * collection can be typecast to the {@code X509Certificate} class.
+ *
+ * <p>In the case of a certificate factory for X.509 certificates,
+ * {@code inStream} may contain a sequence of DER-encoded certificates
+ * in the formats described for
+ * {@link #generateCertificate(java.io.InputStream) generateCertificate}.
+ * In addition, {@code inStream} may contain a PKCS#7 certificate
+ * chain. This is a PKCS#7 <i>SignedData</i> object, with the only
+ * significant field being <i>certificates</i>. In particular, the
+ * signature and the contents are ignored. This format allows multiple
+ * certificates to be downloaded at once. If no certificates are present,
+ * an empty collection is returned.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream.
+ *
+ * @param inStream the input stream with the certificates.
+ *
+ * @return a (possibly empty) collection view of
+ * java.security.cert.Certificate objects
+ * initialized with the data from the input stream.
+ *
+ * @exception CertificateException on parsing errors.
+ */
+ public final Collection<? extends Certificate> generateCertificates
+ (InputStream inStream) throws CertificateException {
+ return certFacSpi.engineGenerateCertificates(inStream);
+ }
+
+ /**
+ * Generates a certificate revocation list (CRL) object and initializes it
+ * with the data read from the input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized CRL format
+ * supported by this certificate factory,
+ * the returned CRL object can be typecast to the corresponding
+ * CRL class. For example, if this certificate
+ * factory implements X.509 CRLs, the returned CRL object
+ * can be typecast to the {@code X509CRL} class.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream. Otherwise, each call to this
+ * method consumes one CRL and the read position of the input stream
+ * is positioned to the next available byte after the inherent
+ * end-of-CRL marker. If the data in the
+ * input stream does not contain an inherent end-of-CRL marker (other
+ * than EOF) and there is trailing data after the CRL is parsed, a
+ * {@code CRLException} is thrown.
+ *
+ * @param inStream an input stream with the CRL data.
+ *
+ * @return a CRL object initialized with the data
+ * from the input stream.
+ *
+ * @exception CRLException on parsing errors.
+ */
+ public final CRL generateCRL(InputStream inStream)
+ throws CRLException
+ {
+ return certFacSpi.engineGenerateCRL(inStream);
+ }
+
+ /**
+ * Returns a (possibly empty) collection view of the CRLs read
+ * from the given input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized CRL format
+ * supported by this certificate factory, each element in
+ * the returned collection view can be typecast to the corresponding
+ * CRL class. For example, if this certificate
+ * factory implements X.509 CRLs, the elements in the returned
+ * collection can be typecast to the {@code X509CRL} class.
+ *
+ * <p>In the case of a certificate factory for X.509 CRLs,
+ * {@code inStream} may contain a sequence of DER-encoded CRLs.
+ * In addition, {@code inStream} may contain a PKCS#7 CRL
+ * set. This is a PKCS#7 <i>SignedData</i> object, with the only
+ * significant field being <i>crls</i>. In particular, the
+ * signature and the contents are ignored. This format allows multiple
+ * CRLs to be downloaded at once. If no CRLs are present,
+ * an empty collection is returned.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream.
+ *
+ * @param inStream the input stream with the CRLs.
+ *
+ * @return a (possibly empty) collection view of
+ * java.security.cert.CRL objects initialized with the data from the input
+ * stream.
+ *
+ * @exception CRLException on parsing errors.
+ */
+ public final Collection<? extends CRL> generateCRLs(InputStream inStream)
+ throws CRLException {
+ return certFacSpi.engineGenerateCRLs(inStream);
+ }
+}
diff --git a/java/security/cert/CertificateFactorySpi.java b/java/security/cert/CertificateFactorySpi.java
new file mode 100644
index 0000000..5e13831
--- /dev/null
+++ b/java/security/cert/CertificateFactorySpi.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.security.Provider;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+/**
+ * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
+ * for the {@code CertificateFactory} class.
+ * All the abstract methods in this class must be implemented by each
+ * cryptographic service provider who wishes to supply the implementation
+ * of a certificate factory for a particular certificate type, e.g., X.509.
+ *
+ * <p>Certificate factories are used to generate certificate, certification path
+ * ({@code CertPath}) and certificate revocation list (CRL) objects from
+ * their encodings.
+ *
+ * <p>A certificate factory for X.509 must return certificates that are an
+ * instance of {@code java.security.cert.X509Certificate}, and CRLs
+ * that are an instance of {@code java.security.cert.X509CRL}.
+ *
+ * @author Hemma Prafullchandra
+ * @author Jan Luehe
+ * @author Sean Mullan
+ *
+ *
+ * @see CertificateFactory
+ * @see Certificate
+ * @see X509Certificate
+ * @see CertPath
+ * @see CRL
+ * @see X509CRL
+ *
+ * @since 1.2
+ */
+
+public abstract class CertificateFactorySpi {
+
+ /**
+ * Generates a certificate object and initializes it with
+ * the data read from the input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized certificate format
+ * supported by this certificate factory,
+ * the returned certificate object can be typecast to the corresponding
+ * certificate class. For example, if this certificate
+ * factory implements X.509 certificates, the returned certificate object
+ * can be typecast to the {@code X509Certificate} class.
+ *
+ * <p>In the case of a certificate factory for X.509 certificates, the
+ * certificate provided in {@code inStream} must be DER-encoded and
+ * may be supplied in binary or printable (Base64) encoding. If the
+ * certificate is provided in Base64 encoding, it must be bounded at
+ * the beginning by -----BEGIN CERTIFICATE-----, and must be bounded at
+ * the end by -----END CERTIFICATE-----.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream. Otherwise, each call to this
+ * method consumes one certificate and the read position of the input stream
+ * is positioned to the next available byte after the inherent
+ * end-of-certificate marker. If the data in the
+ * input stream does not contain an inherent end-of-certificate marker (other
+ * than EOF) and there is trailing data after the certificate is parsed, a
+ * {@code CertificateException} is thrown.
+ *
+ * @param inStream an input stream with the certificate data.
+ *
+ * @return a certificate object initialized with the data
+ * from the input stream.
+ *
+ * @exception CertificateException on parsing errors.
+ */
+ public abstract Certificate engineGenerateCertificate(InputStream inStream)
+ throws CertificateException;
+
+ /**
+ * Generates a {@code CertPath} object and initializes it with
+ * the data read from the {@code InputStream} inStream. The data
+ * is assumed to be in the default encoding.
+ *
+ * <p> This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be {@code abstract}
+ * and by default throws an {@code UnsupportedOperationException}.
+ *
+ * @param inStream an {@code InputStream} containing the data
+ * @return a {@code CertPath} initialized with the data from the
+ * {@code InputStream}
+ * @exception CertificateException if an exception occurs while decoding
+ * @exception UnsupportedOperationException if the method is not supported
+ * @since 1.4
+ */
+ public CertPath engineGenerateCertPath(InputStream inStream)
+ throws CertificateException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Generates a {@code CertPath} object and initializes it with
+ * the data read from the {@code InputStream} inStream. The data
+ * is assumed to be in the specified encoding.
+ *
+ * <p> This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be {@code abstract}
+ * and by default throws an {@code UnsupportedOperationException}.
+ *
+ * @param inStream an {@code InputStream} containing the data
+ * @param encoding the encoding used for the data
+ * @return a {@code CertPath} initialized with the data from the
+ * {@code InputStream}
+ * @exception CertificateException if an exception occurs while decoding or
+ * the encoding requested is not supported
+ * @exception UnsupportedOperationException if the method is not supported
+ * @since 1.4
+ */
+ public CertPath engineGenerateCertPath(InputStream inStream,
+ String encoding) throws CertificateException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Generates a {@code CertPath} object and initializes it with
+ * a {@code List} of {@code Certificate}s.
+ * <p>
+ * The certificates supplied must be of a type supported by the
+ * {@code CertificateFactory}. They will be copied out of the supplied
+ * {@code List} object.
+ *
+ * <p> This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be {@code abstract}
+ * and by default throws an {@code UnsupportedOperationException}.
+ *
+ * @param certificates a {@code List} of {@code Certificate}s
+ * @return a {@code CertPath} initialized with the supplied list of
+ * certificates
+ * @exception CertificateException if an exception occurs
+ * @exception UnsupportedOperationException if the method is not supported
+ * @since 1.4
+ */
+ public CertPath
+ engineGenerateCertPath(List<? extends Certificate> certificates)
+ throws CertificateException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns an iteration of the {@code CertPath} encodings supported
+ * by this certificate factory, with the default encoding first. See
+ * the CertPath Encodings section in the <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+ * for information about standard encoding names.
+ * <p>
+ * Attempts to modify the returned {@code Iterator} via its
+ * {@code remove} method result in an
+ * {@code UnsupportedOperationException}.
+ *
+ * <p> This method was added to version 1.4 of the Java 2 Platform
+ * Standard Edition. In order to maintain backwards compatibility with
+ * existing service providers, this method cannot be {@code abstract}
+ * and by default throws an {@code UnsupportedOperationException}.
+ *
+ * @return an {@code Iterator} over the names of the supported
+ * {@code CertPath} encodings (as {@code String}s)
+ * @exception UnsupportedOperationException if the method is not supported
+ * @since 1.4
+ */
+ public Iterator<String> engineGetCertPathEncodings() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns a (possibly empty) collection view of the certificates read
+ * from the given input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized certificate format
+ * supported by this certificate factory, each element in
+ * the returned collection view can be typecast to the corresponding
+ * certificate class. For example, if this certificate
+ * factory implements X.509 certificates, the elements in the returned
+ * collection can be typecast to the {@code X509Certificate} class.
+ *
+ * <p>In the case of a certificate factory for X.509 certificates,
+ * {@code inStream} may contain a single DER-encoded certificate
+ * in the formats described for
+ * {@link CertificateFactory#generateCertificate(java.io.InputStream)
+ * generateCertificate}.
+ * In addition, {@code inStream} may contain a PKCS#7 certificate
+ * chain. This is a PKCS#7 <i>SignedData</i> object, with the only
+ * significant field being <i>certificates</i>. In particular, the
+ * signature and the contents are ignored. This format allows multiple
+ * certificates to be downloaded at once. If no certificates are present,
+ * an empty collection is returned.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream.
+ *
+ * @param inStream the input stream with the certificates.
+ *
+ * @return a (possibly empty) collection view of
+ * java.security.cert.Certificate objects
+ * initialized with the data from the input stream.
+ *
+ * @exception CertificateException on parsing errors.
+ */
+ public abstract Collection<? extends Certificate>
+ engineGenerateCertificates(InputStream inStream)
+ throws CertificateException;
+
+ /**
+ * Generates a certificate revocation list (CRL) object and initializes it
+ * with the data read from the input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized CRL format
+ * supported by this certificate factory,
+ * the returned CRL object can be typecast to the corresponding
+ * CRL class. For example, if this certificate
+ * factory implements X.509 CRLs, the returned CRL object
+ * can be typecast to the {@code X509CRL} class.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream. Otherwise, each call to this
+ * method consumes one CRL and the read position of the input stream
+ * is positioned to the next available byte after the inherent
+ * end-of-CRL marker. If the data in the
+ * input stream does not contain an inherent end-of-CRL marker (other
+ * than EOF) and there is trailing data after the CRL is parsed, a
+ * {@code CRLException} is thrown.
+ *
+ * @param inStream an input stream with the CRL data.
+ *
+ * @return a CRL object initialized with the data
+ * from the input stream.
+ *
+ * @exception CRLException on parsing errors.
+ */
+ public abstract CRL engineGenerateCRL(InputStream inStream)
+ throws CRLException;
+
+ /**
+ * Returns a (possibly empty) collection view of the CRLs read
+ * from the given input stream {@code inStream}.
+ *
+ * <p>In order to take advantage of the specialized CRL format
+ * supported by this certificate factory, each element in
+ * the returned collection view can be typecast to the corresponding
+ * CRL class. For example, if this certificate
+ * factory implements X.509 CRLs, the elements in the returned
+ * collection can be typecast to the {@code X509CRL} class.
+ *
+ * <p>In the case of a certificate factory for X.509 CRLs,
+ * {@code inStream} may contain a single DER-encoded CRL.
+ * In addition, {@code inStream} may contain a PKCS#7 CRL
+ * set. This is a PKCS#7 <i>SignedData</i> object, with the only
+ * significant field being <i>crls</i>. In particular, the
+ * signature and the contents are ignored. This format allows multiple
+ * CRLs to be downloaded at once. If no CRLs are present,
+ * an empty collection is returned.
+ *
+ * <p>Note that if the given input stream does not support
+ * {@link java.io.InputStream#mark(int) mark} and
+ * {@link java.io.InputStream#reset() reset}, this method will
+ * consume the entire input stream.
+ *
+ * @param inStream the input stream with the CRLs.
+ *
+ * @return a (possibly empty) collection view of
+ * java.security.cert.CRL objects initialized with the data from the input
+ * stream.
+ *
+ * @exception CRLException on parsing errors.
+ */
+ public abstract Collection<? extends CRL> engineGenerateCRLs
+ (InputStream inStream) throws CRLException;
+}
diff --git a/java/security/cert/CertificateNotYetValidException.java b/java/security/cert/CertificateNotYetValidException.java
new file mode 100644
index 0000000..e8722bd
--- /dev/null
+++ b/java/security/cert/CertificateNotYetValidException.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * Certificate is not yet valid exception. This is thrown whenever
+ * the current {@code Date} or the specified {@code Date}
+ * is before the {@code notBefore} date/time in the Certificate
+ * validity period.
+ *
+ * @author Hemma Prafullchandra
+ */
+public class CertificateNotYetValidException extends CertificateException {
+
+ static final long serialVersionUID = 4355919900041064702L;
+
+ /**
+ * Constructs a CertificateNotYetValidException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public CertificateNotYetValidException() {
+ super();
+ }
+
+ /**
+ * Constructs a CertificateNotYetValidException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param message the detail message.
+ */
+ public CertificateNotYetValidException(String message) {
+ super(message);
+ }
+}
diff --git a/java/security/cert/CertificateParsingException.java b/java/security/cert/CertificateParsingException.java
new file mode 100644
index 0000000..06a7d60
--- /dev/null
+++ b/java/security/cert/CertificateParsingException.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * Certificate Parsing Exception. This is thrown whenever an
+ * invalid DER-encoded certificate is parsed or unsupported DER features
+ * are found in the Certificate.
+ *
+ * @author Hemma Prafullchandra
+ */
+public class CertificateParsingException extends CertificateException {
+
+ private static final long serialVersionUID = -7989222416793322029L;
+
+ /**
+ * Constructs a CertificateParsingException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public CertificateParsingException() {
+ super();
+ }
+
+ /**
+ * Constructs a CertificateParsingException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param message the detail message.
+ */
+ public CertificateParsingException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a {@code CertificateParsingException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CertificateParsingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code CertificateParsingException} with the
+ * specified cause and a detail message of
+ * {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public CertificateParsingException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/cert/CertificateRevokedException.java b/java/security/cert/CertificateRevokedException.java
new file mode 100644
index 0000000..505a007
--- /dev/null
+++ b/java/security/cert/CertificateRevokedException.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.InvalidityDateExtension;
+
+/**
+ * An exception that indicates an X.509 certificate is revoked. A
+ * {@code CertificateRevokedException} contains additional information
+ * about the revoked certificate, such as the date on which the
+ * certificate was revoked and the reason it was revoked.
+ *
+ * @author Sean Mullan
+ * @since 1.7
+ * @see CertPathValidatorException
+ */
+public class CertificateRevokedException extends CertificateException {
+
+ private static final long serialVersionUID = 7839996631571608627L;
+
+ /**
+ * @serial the date on which the certificate was revoked
+ */
+ private Date revocationDate;
+ /**
+ * @serial the revocation reason
+ */
+ private final CRLReason reason;
+ /**
+ * @serial the {@code X500Principal} that represents the name of the
+ * authority that signed the certificate's revocation status information
+ */
+ private final X500Principal authority;
+
+ private transient Map<String, Extension> extensions;
+
+ /**
+ * Constructs a {@code CertificateRevokedException} with
+ * the specified revocation date, reason code, authority name, and map
+ * of extensions.
+ *
+ * @param revocationDate the date on which the certificate was revoked. The
+ * date is copied to protect against subsequent modification.
+ * @param reason the revocation reason
+ * @param extensions a map of X.509 Extensions. Each key is an OID String
+ * that maps to the corresponding Extension. The map is copied to
+ * prevent subsequent modification.
+ * @param authority the {@code X500Principal} that represents the name
+ * of the authority that signed the certificate's revocation status
+ * information
+ * @throws NullPointerException if {@code revocationDate},
+ * {@code reason}, {@code authority}, or
+ * {@code extensions} is {@code null}
+ */
+ public CertificateRevokedException(Date revocationDate, CRLReason reason,
+ X500Principal authority, Map<String, Extension> extensions) {
+ if (revocationDate == null || reason == null || authority == null ||
+ extensions == null) {
+ throw new NullPointerException();
+ }
+ this.revocationDate = new Date(revocationDate.getTime());
+ this.reason = reason;
+ this.authority = authority;
+ // make sure Map only contains correct types
+ this.extensions = Collections.checkedMap(new HashMap<>(),
+ String.class, Extension.class);
+ this.extensions.putAll(extensions);
+ }
+
+ /**
+ * Returns the date on which the certificate was revoked. A new copy is
+ * returned each time the method is invoked to protect against subsequent
+ * modification.
+ *
+ * @return the revocation date
+ */
+ public Date getRevocationDate() {
+ return (Date) revocationDate.clone();
+ }
+
+ /**
+ * Returns the reason the certificate was revoked.
+ *
+ * @return the revocation reason
+ */
+ public CRLReason getRevocationReason() {
+ return reason;
+ }
+
+ /**
+ * Returns the name of the authority that signed the certificate's
+ * revocation status information.
+ *
+ * @return the {@code X500Principal} that represents the name of the
+ * authority that signed the certificate's revocation status information
+ */
+ public X500Principal getAuthorityName() {
+ return authority;
+ }
+
+ /**
+ * Returns the invalidity date, as specified in the Invalidity Date
+ * extension of this {@code CertificateRevokedException}. The
+ * invalidity date is the date on which it is known or suspected that the
+ * private key was compromised or that the certificate otherwise became
+ * invalid. This implementation calls {@code getExtensions()} and
+ * checks the returned map for an entry for the Invalidity Date extension
+ * OID ("2.5.29.24"). If found, it returns the invalidity date in the
+ * extension; otherwise null. A new Date object is returned each time the
+ * method is invoked to protect against subsequent modification.
+ *
+ * @return the invalidity date, or {@code null} if not specified
+ */
+ public Date getInvalidityDate() {
+ Extension ext = getExtensions().get("2.5.29.24");
+ if (ext == null) {
+ return null;
+ } else {
+ try {
+ Date invalidity = InvalidityDateExtension.toImpl(ext).get("DATE");
+ return new Date(invalidity.getTime());
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns a map of X.509 extensions containing additional information
+ * about the revoked certificate, such as the Invalidity Date
+ * Extension. Each key is an OID String that maps to the corresponding
+ * Extension.
+ *
+ * @return an unmodifiable map of X.509 extensions, or an empty map
+ * if there are no extensions
+ */
+ public Map<String, Extension> getExtensions() {
+ return Collections.unmodifiableMap(extensions);
+ }
+
+ @Override
+ public String getMessage() {
+ return "Certificate has been revoked, reason: "
+ + reason + ", revocation date: " + revocationDate
+ + ", authority: " + authority + ", extension OIDs: "
+ + extensions.keySet();
+ }
+
+ /**
+ * Serialize this {@code CertificateRevokedException} instance.
+ *
+ * @serialData the size of the extensions map (int), followed by all of
+ * the extensions in the map, in no particular order. For each extension,
+ * the following data is emitted: the OID String (Object), the criticality
+ * flag (boolean), the length of the encoded extension value byte array
+ * (int), and the encoded extension value bytes.
+ */
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ // Write out the non-transient fields
+ // (revocationDate, reason, authority)
+ oos.defaultWriteObject();
+
+ // Write out the size (number of mappings) of the extensions map
+ oos.writeInt(extensions.size());
+
+ // For each extension in the map, the following are emitted (in order):
+ // the OID String (Object), the criticality flag (boolean), the length
+ // of the encoded extension value byte array (int), and the encoded
+ // extension value byte array. The extensions themselves are emitted
+ // in no particular order.
+ for (Map.Entry<String, Extension> entry : extensions.entrySet()) {
+ Extension ext = entry.getValue();
+ oos.writeObject(ext.getId());
+ oos.writeBoolean(ext.isCritical());
+ byte[] extVal = ext.getValue();
+ oos.writeInt(extVal.length);
+ oos.write(extVal);
+ }
+ }
+
+ /**
+ * Deserialize the {@code CertificateRevokedException} instance.
+ */
+ private void readObject(ObjectInputStream ois)
+ throws IOException, ClassNotFoundException {
+ // Read in the non-transient fields
+ // (revocationDate, reason, authority)
+ ois.defaultReadObject();
+
+ // Defensively copy the revocation date
+ revocationDate = new Date(revocationDate.getTime());
+
+ // Read in the size (number of mappings) of the extensions map
+ // and create the extensions map
+ int size = ois.readInt();
+ if (size == 0) {
+ extensions = Collections.emptyMap();
+ } else {
+ extensions = new HashMap<String, Extension>(size);
+ }
+
+ // Read in the extensions and put the mappings in the extensions map
+ for (int i = 0; i < size; i++) {
+ String oid = (String) ois.readObject();
+ boolean critical = ois.readBoolean();
+ int length = ois.readInt();
+ byte[] extVal = new byte[length];
+ ois.readFully(extVal);
+ Extension ext = sun.security.x509.Extension.newExtension
+ (new ObjectIdentifier(oid), critical, extVal);
+ extensions.put(oid, ext);
+ }
+ }
+}
diff --git a/java/security/cert/CollectionCertStoreParameters.java b/java/security/cert/CollectionCertStoreParameters.java
new file mode 100644
index 0000000..12bd358
--- /dev/null
+++ b/java/security/cert/CollectionCertStoreParameters.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Parameters used as input for the Collection {@code CertStore}
+ * algorithm.
+ * <p>
+ * This class is used to provide necessary configuration parameters
+ * to implementations of the Collection {@code CertStore}
+ * algorithm. The only parameter included in this class is the
+ * {@code Collection} from which the {@code CertStore} will
+ * retrieve certificates and CRLs.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ * @see java.util.Collection
+ * @see CertStore
+ */
+public class CollectionCertStoreParameters
+ implements CertStoreParameters {
+
+ private Collection<?> coll;
+
+ /**
+ * Creates an instance of {@code CollectionCertStoreParameters}
+ * which will allow certificates and CRLs to be retrieved from the
+ * specified {@code Collection}. If the specified
+ * {@code Collection} contains an object that is not a
+ * {@code Certificate} or {@code CRL}, that object will be
+ * ignored by the Collection {@code CertStore}.
+ * <p>
+ * The {@code Collection} is <b>not</b> copied. Instead, a
+ * reference is used. This allows the caller to subsequently add or
+ * remove {@code Certificates} or {@code CRL}s from the
+ * {@code Collection}, thus changing the set of
+ * {@code Certificates} or {@code CRL}s available to the
+ * Collection {@code CertStore}. The Collection {@code CertStore}
+ * will not modify the contents of the {@code Collection}.
+ * <p>
+ * If the {@code Collection} will be modified by one thread while
+ * another thread is calling a method of a Collection {@code CertStore}
+ * that has been initialized with this {@code Collection}, the
+ * {@code Collection} must have fail-fast iterators.
+ *
+ * @param collection a {@code Collection} of
+ * {@code Certificate}s and {@code CRL}s
+ * @exception NullPointerException if {@code collection} is
+ * {@code null}
+ */
+ public CollectionCertStoreParameters(Collection<?> collection) {
+ if (collection == null)
+ throw new NullPointerException();
+ coll = collection;
+ }
+
+ /**
+ * Creates an instance of {@code CollectionCertStoreParameters} with
+ * the default parameter values (an empty and immutable
+ * {@code Collection}).
+ */
+ public CollectionCertStoreParameters() {
+ coll = Collections.EMPTY_SET;
+ }
+
+ /**
+ * Returns the {@code Collection} from which {@code Certificate}s
+ * and {@code CRL}s are retrieved. This is <b>not</b> a copy of the
+ * {@code Collection}, it is a reference. This allows the caller to
+ * subsequently add or remove {@code Certificates} or
+ * {@code CRL}s from the {@code Collection}.
+ *
+ * @return the {@code Collection} (never null)
+ */
+ public Collection<?> getCollection() {
+ return coll;
+ }
+
+ /**
+ * Returns a copy of this object. Note that only a reference to the
+ * {@code Collection} is copied, and not the contents.
+ *
+ * @return the copy
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("CollectionCertStoreParameters: [\n");
+ sb.append(" collection: " + coll + "\n");
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/Extension.java b/java/security/cert/Extension.java
new file mode 100644
index 0000000..98e827c
--- /dev/null
+++ b/java/security/cert/Extension.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2007, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+/**
+ * This interface represents an X.509 extension.
+ *
+ * <p>
+ * Extensions provide a means of associating additional attributes with users
+ * or public keys and for managing a certification hierarchy. The extension
+ * format also allows communities to define private extensions to carry
+ * information unique to those communities.
+ *
+ * <p>
+ * Each extension contains an object identifier, a criticality setting
+ * indicating whether it is a critical or a non-critical extension, and
+ * and an ASN.1 DER-encoded value. Its ASN.1 definition is:
+ *
+ * <pre>
+ *
+ * Extension ::= SEQUENCE {
+ * extnId OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING
+ * -- contains a DER encoding of a value
+ * -- of the type registered for use with
+ * -- the extnId object identifier value
+ * }
+ *
+ * </pre>
+ *
+ * <p>
+ * This interface is designed to provide access to a single extension,
+ * unlike {@link java.security.cert.X509Extension} which is more suitable
+ * for accessing a set of extensions.
+ *
+ * @since 1.7
+ */
+public interface Extension {
+
+ /**
+ * Gets the extensions's object identifier.
+ *
+ * @return the object identifier as a String
+ */
+ String getId();
+
+ /**
+ * Gets the extension's criticality setting.
+ *
+ * @return true if this is a critical extension.
+ */
+ boolean isCritical();
+
+ /**
+ * Gets the extensions's DER-encoded value. Note, this is the bytes
+ * that are encoded as an OCTET STRING. It does not include the OCTET
+ * STRING tag and length.
+ *
+ * @return a copy of the extension's value, or {@code null} if no
+ * extension value is present.
+ */
+ byte[] getValue();
+
+ /**
+ * Generates the extension's DER encoding and writes it to the output
+ * stream.
+ *
+ * @param out the output stream
+ * @exception IOException on encoding or output error.
+ * @exception NullPointerException if {@code out} is {@code null}.
+ */
+ void encode(OutputStream out) throws IOException;
+}
diff --git a/java/security/cert/LDAPCertStoreParameters.java b/java/security/cert/LDAPCertStoreParameters.java
new file mode 100644
index 0000000..96fe9cd
--- /dev/null
+++ b/java/security/cert/LDAPCertStoreParameters.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * Parameters used as input for the LDAP {@code CertStore} algorithm.
+ * <p>
+ * This class is used to provide necessary configuration parameters (server
+ * name and port number) to implementations of the LDAP {@code CertStore}
+ * algorithm.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ * @see CertStore
+ */
+public class LDAPCertStoreParameters implements CertStoreParameters {
+
+ private static final int LDAP_DEFAULT_PORT = 389;
+
+ /**
+ * the port number of the LDAP server
+ */
+ private int port;
+
+ /**
+ * the DNS name of the LDAP server
+ */
+ private String serverName;
+
+ /**
+ * Creates an instance of {@code LDAPCertStoreParameters} with the
+ * specified parameter values.
+ *
+ * @param serverName the DNS name of the LDAP server
+ * @param port the port number of the LDAP server
+ * @exception NullPointerException if {@code serverName} is
+ * {@code null}
+ */
+ public LDAPCertStoreParameters(String serverName, int port) {
+ if (serverName == null)
+ throw new NullPointerException();
+ this.serverName = serverName;
+ this.port = port;
+ }
+
+ /**
+ * Creates an instance of {@code LDAPCertStoreParameters} with the
+ * specified server name and a default port of 389.
+ *
+ * @param serverName the DNS name of the LDAP server
+ * @exception NullPointerException if {@code serverName} is
+ * {@code null}
+ */
+ public LDAPCertStoreParameters(String serverName) {
+ this(serverName, LDAP_DEFAULT_PORT);
+ }
+
+ /**
+ * Creates an instance of {@code LDAPCertStoreParameters} with the
+ * default parameter values (server name "localhost", port 389).
+ */
+ public LDAPCertStoreParameters() {
+ this("localhost", LDAP_DEFAULT_PORT);
+ }
+
+ /**
+ * Returns the DNS name of the LDAP server.
+ *
+ * @return the name (not {@code null})
+ */
+ public String getServerName() {
+ return serverName;
+ }
+
+ /**
+ * Returns the port number of the LDAP server.
+ *
+ * @return the port number
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * Returns a copy of this object. Changes to the copy will not affect
+ * the original and vice versa.
+ * <p>
+ * Note: this method currently performs a shallow copy of the object
+ * (simply calls {@code Object.clone()}). This may be changed in a
+ * future revision to perform a deep copy if new parameters are added
+ * that should not be shared.
+ *
+ * @return the copy
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("LDAPCertStoreParameters: [\n");
+
+ sb.append(" serverName: " + serverName + "\n");
+ sb.append(" port: " + port + "\n");
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/PKIXBuilderParameters.java b/java/security/cert/PKIXBuilderParameters.java
new file mode 100644
index 0000000..b33e1f8
--- /dev/null
+++ b/java/security/cert/PKIXBuilderParameters.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.util.Set;
+
+/**
+ * Parameters used as input for the PKIX {@code CertPathBuilder}
+ * algorithm.
+ * <p>
+ * A PKIX {@code CertPathBuilder} uses these parameters to {@link
+ * CertPathBuilder#build build} a {@code CertPath} which has been
+ * validated according to the PKIX certification path validation algorithm.
+ *
+ * <p>To instantiate a {@code PKIXBuilderParameters} object, an
+ * application must specify one or more <i>most-trusted CAs</i> as defined by
+ * the PKIX certification path validation algorithm. The most-trusted CA
+ * can be specified using one of two constructors. An application
+ * can call {@link #PKIXBuilderParameters(Set, CertSelector)
+ * PKIXBuilderParameters(Set, CertSelector)}, specifying a
+ * {@code Set} of {@code TrustAnchor} objects, each of which
+ * identifies a most-trusted CA. Alternatively, an application can call
+ * {@link #PKIXBuilderParameters(KeyStore, CertSelector)
+ * PKIXBuilderParameters(KeyStore, CertSelector)}, specifying a
+ * {@code KeyStore} instance containing trusted certificate entries, each
+ * of which will be considered as a most-trusted CA.
+ *
+ * <p>In addition, an application must specify constraints on the target
+ * certificate that the {@code CertPathBuilder} will attempt
+ * to build a path to. The constraints are specified as a
+ * {@code CertSelector} object. These constraints should provide the
+ * {@code CertPathBuilder} with enough search criteria to find the target
+ * certificate. Minimal criteria for an {@code X509Certificate} usually
+ * include the subject name and/or one or more subject alternative names.
+ * If enough criteria is not specified, the {@code CertPathBuilder}
+ * may throw a {@code CertPathBuilderException}.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathBuilder
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public class PKIXBuilderParameters extends PKIXParameters {
+
+ private int maxPathLength = 5;
+
+ /**
+ * Creates an instance of {@code PKIXBuilderParameters} with
+ * the specified {@code Set} of most-trusted CAs.
+ * Each element of the set is a {@link TrustAnchor TrustAnchor}.
+ *
+ * <p>Note that the {@code Set} is copied to protect against
+ * subsequent modifications.
+ *
+ * @param trustAnchors a {@code Set} of {@code TrustAnchor}s
+ * @param targetConstraints a {@code CertSelector} specifying the
+ * constraints on the target certificate
+ * @throws InvalidAlgorithmParameterException if {@code trustAnchors}
+ * is empty {@code (trustAnchors.isEmpty() == true)}
+ * @throws NullPointerException if {@code trustAnchors} is
+ * {@code null}
+ * @throws ClassCastException if any of the elements of
+ * {@code trustAnchors} are not of type
+ * {@code java.security.cert.TrustAnchor}
+ */
+ public PKIXBuilderParameters(Set<TrustAnchor> trustAnchors, CertSelector
+ targetConstraints) throws InvalidAlgorithmParameterException
+ {
+ super(trustAnchors);
+ setTargetCertConstraints(targetConstraints);
+ }
+
+ /**
+ * Creates an instance of {@code PKIXBuilderParameters} that
+ * populates the set of most-trusted CAs from the trusted
+ * certificate entries contained in the specified {@code KeyStore}.
+ * Only keystore entries that contain trusted {@code X509Certificate}s
+ * are considered; all other certificate types are ignored.
+ *
+ * @param keystore a {@code KeyStore} from which the set of
+ * most-trusted CAs will be populated
+ * @param targetConstraints a {@code CertSelector} specifying the
+ * constraints on the target certificate
+ * @throws KeyStoreException if {@code keystore} has not been
+ * initialized
+ * @throws InvalidAlgorithmParameterException if {@code keystore} does
+ * not contain at least one trusted certificate entry
+ * @throws NullPointerException if {@code keystore} is
+ * {@code null}
+ */
+ public PKIXBuilderParameters(KeyStore keystore,
+ CertSelector targetConstraints)
+ throws KeyStoreException, InvalidAlgorithmParameterException
+ {
+ super(keystore);
+ setTargetCertConstraints(targetConstraints);
+ }
+
+ /**
+ * Sets the value of the maximum number of non-self-issued intermediate
+ * certificates that may exist in a certification path. A certificate
+ * is self-issued if the DNs that appear in the subject and issuer
+ * fields are identical and are not empty. Note that the last certificate
+ * in a certification path is not an intermediate certificate, and is not
+ * included in this limit. Usually the last certificate is an end entity
+ * certificate, but it can be a CA certificate. A PKIX
+ * {@code CertPathBuilder} instance must not build
+ * paths longer than the length specified.
+ *
+ * <p> A value of 0 implies that the path can only contain
+ * a single certificate. A value of -1 implies that the
+ * path length is unconstrained (i.e. there is no maximum).
+ * The default maximum path length, if not specified, is 5.
+ * Setting a value less than -1 will cause an exception to be thrown.
+ *
+ * <p> If any of the CA certificates contain the
+ * {@code BasicConstraintsExtension}, the value of the
+ * {@code pathLenConstraint} field of the extension overrides
+ * the maximum path length parameter whenever the result is a
+ * certification path of smaller length.
+ *
+ * @param maxPathLength the maximum number of non-self-issued intermediate
+ * certificates that may exist in a certification path
+ * @throws InvalidParameterException if {@code maxPathLength} is set
+ * to a value less than -1
+ *
+ * @see #getMaxPathLength
+ */
+ public void setMaxPathLength(int maxPathLength) {
+ if (maxPathLength < -1) {
+ throw new InvalidParameterException("the maximum path "
+ + "length parameter can not be less than -1");
+ }
+ this.maxPathLength = maxPathLength;
+ }
+
+ /**
+ * Returns the value of the maximum number of intermediate non-self-issued
+ * certificates that may exist in a certification path. See
+ * the {@link #setMaxPathLength} method for more details.
+ *
+ * @return the maximum number of non-self-issued intermediate certificates
+ * that may exist in a certification path, or -1 if there is no limit
+ *
+ * @see #setMaxPathLength
+ */
+ public int getMaxPathLength() {
+ return maxPathLength;
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[\n");
+ sb.append(super.toString());
+ sb.append(" Maximum Path Length: " + maxPathLength + "\n");
+ sb.append("]\n");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/PKIXCertPathBuilderResult.java b/java/security/cert/PKIXCertPathBuilderResult.java
new file mode 100644
index 0000000..3255a3b
--- /dev/null
+++ b/java/security/cert/PKIXCertPathBuilderResult.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.PublicKey;
+
+/**
+ * This class represents the successful result of the PKIX certification
+ * path builder algorithm. All certification paths that are built and
+ * returned using this algorithm are also validated according to the PKIX
+ * certification path validation algorithm.
+ *
+ * <p>Instances of {@code PKIXCertPathBuilderResult} are returned by
+ * the {@code build} method of {@code CertPathBuilder}
+ * objects implementing the PKIX algorithm.
+ *
+ * <p>All {@code PKIXCertPathBuilderResult} objects contain the
+ * certification path constructed by the build algorithm, the
+ * valid policy tree and subject public key resulting from the build
+ * algorithm, and a {@code TrustAnchor} describing the certification
+ * authority (CA) that served as a trust anchor for the certification path.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathBuilderResult
+ *
+ * @since 1.4
+ * @author Anne Anderson
+ */
+public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult
+ implements CertPathBuilderResult {
+
+ private CertPath certPath;
+
+ /**
+ * Creates an instance of {@code PKIXCertPathBuilderResult}
+ * containing the specified parameters.
+ *
+ * @param certPath the validated {@code CertPath}
+ * @param trustAnchor a {@code TrustAnchor} describing the CA that
+ * served as a trust anchor for the certification path
+ * @param policyTree the immutable valid policy tree, or {@code null}
+ * if there are no valid policies
+ * @param subjectPublicKey the public key of the subject
+ * @throws NullPointerException if the {@code certPath},
+ * {@code trustAnchor} or {@code subjectPublicKey} parameters
+ * are {@code null}
+ */
+ public PKIXCertPathBuilderResult(CertPath certPath,
+ TrustAnchor trustAnchor, PolicyNode policyTree,
+ PublicKey subjectPublicKey)
+ {
+ super(trustAnchor, policyTree, subjectPublicKey);
+ if (certPath == null)
+ throw new NullPointerException("certPath must be non-null");
+ this.certPath = certPath;
+ }
+
+ /**
+ * Returns the built and validated certification path. The
+ * {@code CertPath} object does not include the trust anchor.
+ * Instead, use the {@link #getTrustAnchor() getTrustAnchor()} method to
+ * obtain the {@code TrustAnchor} that served as the trust anchor
+ * for the certification path.
+ *
+ * @return the built and validated {@code CertPath} (never
+ * {@code null})
+ */
+ public CertPath getCertPath() {
+ return certPath;
+ }
+
+ /**
+ * Return a printable representation of this
+ * {@code PKIXCertPathBuilderResult}.
+ *
+ * @return a {@code String} describing the contents of this
+ * {@code PKIXCertPathBuilderResult}
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("PKIXCertPathBuilderResult: [\n");
+ sb.append(" Certification Path: " + certPath + "\n");
+ sb.append(" Trust Anchor: " + getTrustAnchor().toString() + "\n");
+ sb.append(" Policy Tree: " + String.valueOf(getPolicyTree()) + "\n");
+ sb.append(" Subject Public Key: " + getPublicKey() + "\n");
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/PKIXCertPathChecker.java b/java/security/cert/PKIXCertPathChecker.java
new file mode 100644
index 0000000..21e01bf
--- /dev/null
+++ b/java/security/cert/PKIXCertPathChecker.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * An abstract class that performs one or more checks on an
+ * {@code X509Certificate}.
+ *
+ * <p>A concrete implementation of the {@code PKIXCertPathChecker} class
+ * can be created to extend the PKIX certification path validation algorithm.
+ * For example, an implementation may check for and process a critical private
+ * extension of each certificate in a certification path.
+ *
+ * <p>Instances of {@code PKIXCertPathChecker} are passed as parameters
+ * using the {@link PKIXParameters#setCertPathCheckers setCertPathCheckers}
+ * or {@link PKIXParameters#addCertPathChecker addCertPathChecker} methods
+ * of the {@code PKIXParameters} and {@code PKIXBuilderParameters}
+ * class. Each of the {@code PKIXCertPathChecker}s {@link #check check}
+ * methods will be called, in turn, for each certificate processed by a PKIX
+ * {@code CertPathValidator} or {@code CertPathBuilder}
+ * implementation.
+ *
+ * <p>A {@code PKIXCertPathChecker} may be called multiple times on
+ * successive certificates in a certification path. Concrete subclasses
+ * are expected to maintain any internal state that may be necessary to
+ * check successive certificates. The {@link #init init} method is used
+ * to initialize the internal state of the checker so that the certificates
+ * of a new certification path may be checked. A stateful implementation
+ * <b>must</b> override the {@link #clone clone} method if necessary in
+ * order to allow a PKIX {@code CertPathBuilder} to efficiently
+ * backtrack and try other paths. In these situations, the
+ * {@code CertPathBuilder} is able to restore prior path validation
+ * states by restoring the cloned {@code PKIXCertPathChecker}s.
+ *
+ * <p>The order in which the certificates are presented to the
+ * {@code PKIXCertPathChecker} may be either in the forward direction
+ * (from target to most-trusted CA) or in the reverse direction (from
+ * most-trusted CA to target). A {@code PKIXCertPathChecker} implementation
+ * <b>must</b> support reverse checking (the ability to perform its checks when
+ * it is presented with certificates in the reverse direction) and <b>may</b>
+ * support forward checking (the ability to perform its checks when it is
+ * presented with certificates in the forward direction). The
+ * {@link #isForwardCheckingSupported isForwardCheckingSupported} method
+ * indicates whether forward checking is supported.
+ * <p>
+ * Additional input parameters required for executing the check may be
+ * specified through constructors of concrete implementations of this class.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see PKIXParameters
+ * @see PKIXBuilderParameters
+ *
+ * @since 1.4
+ * @author Yassir Elley
+ * @author Sean Mullan
+ */
+public abstract class PKIXCertPathChecker
+ implements CertPathChecker, Cloneable {
+
+ /**
+ * Default constructor.
+ */
+ protected PKIXCertPathChecker() {}
+
+ /**
+ * Initializes the internal state of this {@code PKIXCertPathChecker}.
+ * <p>
+ * The {@code forward} flag specifies the order that
+ * certificates will be passed to the {@link #check check} method
+ * (forward or reverse). A {@code PKIXCertPathChecker} <b>must</b>
+ * support reverse checking and <b>may</b> support forward checking.
+ *
+ * @param forward the order that certificates are presented to
+ * the {@code check} method. If {@code true}, certificates
+ * are presented from target to most-trusted CA (forward); if
+ * {@code false}, from most-trusted CA to target (reverse).
+ * @throws CertPathValidatorException if this
+ * {@code PKIXCertPathChecker} is unable to check certificates in
+ * the specified order; it should never be thrown if the forward flag
+ * is false since reverse checking must be supported
+ */
+ @Override
+ public abstract void init(boolean forward)
+ throws CertPathValidatorException;
+
+ /**
+ * Indicates if forward checking is supported. Forward checking refers
+ * to the ability of the {@code PKIXCertPathChecker} to perform
+ * its checks when certificates are presented to the {@code check}
+ * method in the forward direction (from target to most-trusted CA).
+ *
+ * @return {@code true} if forward checking is supported,
+ * {@code false} otherwise
+ */
+ @Override
+ public abstract boolean isForwardCheckingSupported();
+
+ /**
+ * Returns an immutable {@code Set} of X.509 certificate extensions
+ * that this {@code PKIXCertPathChecker} supports (i.e. recognizes, is
+ * able to process), or {@code null} if no extensions are supported.
+ * <p>
+ * Each element of the set is a {@code String} representing the
+ * Object Identifier (OID) of the X.509 extension that is supported.
+ * The OID is represented by a set of nonnegative integers separated by
+ * periods.
+ * <p>
+ * All X.509 certificate extensions that a {@code PKIXCertPathChecker}
+ * might possibly be able to process should be included in the set.
+ *
+ * @return an immutable {@code Set} of X.509 extension OIDs (in
+ * {@code String} format) supported by this
+ * {@code PKIXCertPathChecker}, or {@code null} if no
+ * extensions are supported
+ */
+ public abstract Set<String> getSupportedExtensions();
+
+ /**
+ * Performs the check(s) on the specified certificate using its internal
+ * state and removes any critical extensions that it processes from the
+ * specified collection of OID strings that represent the unresolved
+ * critical extensions. The certificates are presented in the order
+ * specified by the {@code init} method.
+ *
+ * @param cert the {@code Certificate} to be checked
+ * @param unresolvedCritExts a {@code Collection} of OID strings
+ * representing the current set of unresolved critical extensions
+ * @exception CertPathValidatorException if the specified certificate does
+ * not pass the check
+ */
+ public abstract void check(Certificate cert,
+ Collection<String> unresolvedCritExts)
+ throws CertPathValidatorException;
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation calls
+ * {@code check(cert, java.util.Collections.<String>emptySet())}.
+ */
+ @Override
+ public void check(Certificate cert) throws CertPathValidatorException {
+ check(cert, java.util.Collections.<String>emptySet());
+ }
+
+ /**
+ * Returns a clone of this object. Calls the {@code Object.clone()}
+ * method.
+ * All subclasses which maintain state must support and
+ * override this method, if necessary.
+ *
+ * @return a copy of this {@code PKIXCertPathChecker}
+ */
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+}
diff --git a/java/security/cert/PKIXCertPathValidatorResult.java b/java/security/cert/PKIXCertPathValidatorResult.java
new file mode 100644
index 0000000..b40cd39
--- /dev/null
+++ b/java/security/cert/PKIXCertPathValidatorResult.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.PublicKey;
+
+/**
+ * This class represents the successful result of the PKIX certification
+ * path validation algorithm.
+ *
+ * <p>Instances of {@code PKIXCertPathValidatorResult} are returned by the
+ * {@link CertPathValidator#validate validate} method of
+ * {@code CertPathValidator} objects implementing the PKIX algorithm.
+ *
+ * <p> All {@code PKIXCertPathValidatorResult} objects contain the
+ * valid policy tree and subject public key resulting from the
+ * validation algorithm, as well as a {@code TrustAnchor} describing
+ * the certification authority (CA) that served as a trust anchor for the
+ * certification path.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathValidatorResult
+ *
+ * @since 1.4
+ * @author Yassir Elley
+ * @author Sean Mullan
+ */
+public class PKIXCertPathValidatorResult implements CertPathValidatorResult {
+
+ private TrustAnchor trustAnchor;
+ private PolicyNode policyTree;
+ private PublicKey subjectPublicKey;
+
+ /**
+ * Creates an instance of {@code PKIXCertPathValidatorResult}
+ * containing the specified parameters.
+ *
+ * @param trustAnchor a {@code TrustAnchor} describing the CA that
+ * served as a trust anchor for the certification path
+ * @param policyTree the immutable valid policy tree, or {@code null}
+ * if there are no valid policies
+ * @param subjectPublicKey the public key of the subject
+ * @throws NullPointerException if the {@code subjectPublicKey} or
+ * {@code trustAnchor} parameters are {@code null}
+ */
+ public PKIXCertPathValidatorResult(TrustAnchor trustAnchor,
+ PolicyNode policyTree, PublicKey subjectPublicKey)
+ {
+ if (subjectPublicKey == null)
+ throw new NullPointerException("subjectPublicKey must be non-null");
+ if (trustAnchor == null)
+ throw new NullPointerException("trustAnchor must be non-null");
+ this.trustAnchor = trustAnchor;
+ this.policyTree = policyTree;
+ this.subjectPublicKey = subjectPublicKey;
+ }
+
+ /**
+ * Returns the {@code TrustAnchor} describing the CA that served
+ * as a trust anchor for the certification path.
+ *
+ * @return the {@code TrustAnchor} (never {@code null})
+ */
+ public TrustAnchor getTrustAnchor() {
+ return trustAnchor;
+ }
+
+ /**
+ * Returns the root node of the valid policy tree resulting from the
+ * PKIX certification path validation algorithm. The
+ * {@code PolicyNode} object that is returned and any objects that
+ * it returns through public methods are immutable.
+ *
+ * <p>Most applications will not need to examine the valid policy tree.
+ * They can achieve their policy processing goals by setting the
+ * policy-related parameters in {@code PKIXParameters}. However, more
+ * sophisticated applications, especially those that process policy
+ * qualifiers, may need to traverse the valid policy tree using the
+ * {@link PolicyNode#getParent PolicyNode.getParent} and
+ * {@link PolicyNode#getChildren PolicyNode.getChildren} methods.
+ *
+ * @return the root node of the valid policy tree, or {@code null}
+ * if there are no valid policies
+ */
+ public PolicyNode getPolicyTree() {
+ return policyTree;
+ }
+
+ /**
+ * Returns the public key of the subject (target) of the certification
+ * path, including any inherited public key parameters if applicable.
+ *
+ * @return the public key of the subject (never {@code null})
+ */
+ public PublicKey getPublicKey() {
+ return subjectPublicKey;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return the copy
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+
+ /**
+ * Return a printable representation of this
+ * {@code PKIXCertPathValidatorResult}.
+ *
+ * @return a {@code String} describing the contents of this
+ * {@code PKIXCertPathValidatorResult}
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("PKIXCertPathValidatorResult: [\n");
+ sb.append(" Trust Anchor: " + trustAnchor.toString() + "\n");
+ sb.append(" Policy Tree: " + String.valueOf(policyTree) + "\n");
+ sb.append(" Subject Public Key: " + subjectPublicKey + "\n");
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/PKIXParameters.java b/java/security/cert/PKIXParameters.java
new file mode 100644
index 0000000..4d8a344
--- /dev/null
+++ b/java/security/cert/PKIXParameters.java
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Parameters used as input for the PKIX {@code CertPathValidator}
+ * algorithm.
+ * <p>
+ * A PKIX {@code CertPathValidator} uses these parameters to
+ * validate a {@code CertPath} according to the PKIX certification path
+ * validation algorithm.
+ *
+ * <p>To instantiate a {@code PKIXParameters} object, an
+ * application must specify one or more <i>most-trusted CAs</i> as defined by
+ * the PKIX certification path validation algorithm. The most-trusted CAs
+ * can be specified using one of two constructors. An application
+ * can call {@link #PKIXParameters(Set) PKIXParameters(Set)},
+ * specifying a {@code Set} of {@code TrustAnchor} objects, each
+ * of which identify a most-trusted CA. Alternatively, an application can call
+ * {@link #PKIXParameters(KeyStore) PKIXParameters(KeyStore)}, specifying a
+ * {@code KeyStore} instance containing trusted certificate entries, each
+ * of which will be considered as a most-trusted CA.
+ * <p>
+ * Once a {@code PKIXParameters} object has been created, other parameters
+ * can be specified (by calling {@link #setInitialPolicies setInitialPolicies}
+ * or {@link #setDate setDate}, for instance) and then the
+ * {@code PKIXParameters} is passed along with the {@code CertPath}
+ * to be validated to {@link CertPathValidator#validate
+ * CertPathValidator.validate}.
+ * <p>
+ * Any parameter that is not set (or is set to {@code null}) will
+ * be set to the default value for that parameter. The default value for the
+ * {@code date} parameter is {@code null}, which indicates
+ * the current time when the path is validated. The default for the
+ * remaining parameters is the least constrained.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertPathValidator
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ * @author Yassir Elley
+ */
+public class PKIXParameters implements CertPathParameters {
+
+ private Set<TrustAnchor> unmodTrustAnchors;
+ private Date date;
+ private List<PKIXCertPathChecker> certPathCheckers;
+ private String sigProvider;
+ private boolean revocationEnabled = true;
+ private Set<String> unmodInitialPolicies;
+ private boolean explicitPolicyRequired = false;
+ private boolean policyMappingInhibited = false;
+ private boolean anyPolicyInhibited = false;
+ private boolean policyQualifiersRejected = true;
+ private List<CertStore> certStores;
+ private CertSelector certSelector;
+
+ /**
+ * Creates an instance of {@code PKIXParameters} with the specified
+ * {@code Set} of most-trusted CAs. Each element of the
+ * set is a {@link TrustAnchor TrustAnchor}.
+ * <p>
+ * Note that the {@code Set} is copied to protect against
+ * subsequent modifications.
+ *
+ * @param trustAnchors a {@code Set} of {@code TrustAnchor}s
+ * @throws InvalidAlgorithmParameterException if the specified
+ * {@code Set} is empty {@code (trustAnchors.isEmpty() == true)}
+ * @throws NullPointerException if the specified {@code Set} is
+ * {@code null}
+ * @throws ClassCastException if any of the elements in the {@code Set}
+ * are not of type {@code java.security.cert.TrustAnchor}
+ */
+ public PKIXParameters(Set<TrustAnchor> trustAnchors)
+ throws InvalidAlgorithmParameterException
+ {
+ setTrustAnchors(trustAnchors);
+
+ this.unmodInitialPolicies = Collections.<String>emptySet();
+ this.certPathCheckers = new ArrayList<PKIXCertPathChecker>();
+ this.certStores = new ArrayList<CertStore>();
+ }
+
+ /**
+ * Creates an instance of {@code PKIXParameters} that
+ * populates the set of most-trusted CAs from the trusted
+ * certificate entries contained in the specified {@code KeyStore}.
+ * Only keystore entries that contain trusted {@code X509Certificates}
+ * are considered; all other certificate types are ignored.
+ *
+ * @param keystore a {@code KeyStore} from which the set of
+ * most-trusted CAs will be populated
+ * @throws KeyStoreException if the keystore has not been initialized
+ * @throws InvalidAlgorithmParameterException if the keystore does
+ * not contain at least one trusted certificate entry
+ * @throws NullPointerException if the keystore is {@code null}
+ */
+ public PKIXParameters(KeyStore keystore)
+ throws KeyStoreException, InvalidAlgorithmParameterException
+ {
+ if (keystore == null)
+ throw new NullPointerException("the keystore parameter must be " +
+ "non-null");
+ Set<TrustAnchor> hashSet = new HashSet<TrustAnchor>();
+ Enumeration<String> aliases = keystore.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ if (keystore.isCertificateEntry(alias)) {
+ Certificate cert = keystore.getCertificate(alias);
+ if (cert instanceof X509Certificate)
+ hashSet.add(new TrustAnchor((X509Certificate)cert, null));
+ }
+ }
+ setTrustAnchors(hashSet);
+ this.unmodInitialPolicies = Collections.<String>emptySet();
+ this.certPathCheckers = new ArrayList<PKIXCertPathChecker>();
+ this.certStores = new ArrayList<CertStore>();
+ }
+
+ /**
+ * Returns an immutable {@code Set} of the most-trusted
+ * CAs.
+ *
+ * @return an immutable {@code Set} of {@code TrustAnchor}s
+ * (never {@code null})
+ *
+ * @see #setTrustAnchors
+ */
+ public Set<TrustAnchor> getTrustAnchors() {
+ return this.unmodTrustAnchors;
+ }
+
+ /**
+ * Sets the {@code Set} of most-trusted CAs.
+ * <p>
+ * Note that the {@code Set} is copied to protect against
+ * subsequent modifications.
+ *
+ * @param trustAnchors a {@code Set} of {@code TrustAnchor}s
+ * @throws InvalidAlgorithmParameterException if the specified
+ * {@code Set} is empty {@code (trustAnchors.isEmpty() == true)}
+ * @throws NullPointerException if the specified {@code Set} is
+ * {@code null}
+ * @throws ClassCastException if any of the elements in the set
+ * are not of type {@code java.security.cert.TrustAnchor}
+ *
+ * @see #getTrustAnchors
+ */
+ public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
+ throws InvalidAlgorithmParameterException
+ {
+ if (trustAnchors == null) {
+ throw new NullPointerException("the trustAnchors parameters must" +
+ " be non-null");
+ }
+ if (trustAnchors.isEmpty()) {
+ throw new InvalidAlgorithmParameterException("the trustAnchors " +
+ "parameter must be non-empty");
+ }
+ for (Iterator<TrustAnchor> i = trustAnchors.iterator(); i.hasNext(); ) {
+ if (!(i.next() instanceof TrustAnchor)) {
+ throw new ClassCastException("all elements of set must be "
+ + "of type java.security.cert.TrustAnchor");
+ }
+ }
+ this.unmodTrustAnchors = Collections.unmodifiableSet
+ (new HashSet<TrustAnchor>(trustAnchors));
+ }
+
+ /**
+ * Returns an immutable {@code Set} of initial
+ * policy identifiers (OID strings), indicating that any one of these
+ * policies would be acceptable to the certificate user for the purposes of
+ * certification path processing. The default return value is an empty
+ * {@code Set}, which is interpreted as meaning that any policy would
+ * be acceptable.
+ *
+ * @return an immutable {@code Set} of initial policy OIDs in
+ * {@code String} format, or an empty {@code Set} (implying any
+ * policy is acceptable). Never returns {@code null}.
+ *
+ * @see #setInitialPolicies
+ */
+ public Set<String> getInitialPolicies() {
+ return this.unmodInitialPolicies;
+ }
+
+ /**
+ * Sets the {@code Set} of initial policy identifiers
+ * (OID strings), indicating that any one of these
+ * policies would be acceptable to the certificate user for the purposes of
+ * certification path processing. By default, any policy is acceptable
+ * (i.e. all policies), so a user that wants to allow any policy as
+ * acceptable does not need to call this method, or can call it
+ * with an empty {@code Set} (or {@code null}).
+ * <p>
+ * Note that the {@code Set} is copied to protect against
+ * subsequent modifications.
+ *
+ * @param initialPolicies a {@code Set} of initial policy
+ * OIDs in {@code String} format (or {@code null})
+ * @throws ClassCastException if any of the elements in the set are
+ * not of type {@code String}
+ *
+ * @see #getInitialPolicies
+ */
+ public void setInitialPolicies(Set<String> initialPolicies) {
+ if (initialPolicies != null) {
+ for (Iterator<String> i = initialPolicies.iterator();
+ i.hasNext();) {
+ if (!(i.next() instanceof String))
+ throw new ClassCastException("all elements of set must be "
+ + "of type java.lang.String");
+ }
+ this.unmodInitialPolicies =
+ Collections.unmodifiableSet(new HashSet<String>(initialPolicies));
+ } else
+ this.unmodInitialPolicies = Collections.<String>emptySet();
+ }
+
+ /**
+ * Sets the list of {@code CertStore}s to be used in finding
+ * certificates and CRLs. May be {@code null}, in which case
+ * no {@code CertStore}s will be used. The first
+ * {@code CertStore}s in the list may be preferred to those that
+ * appear later.
+ * <p>
+ * Note that the {@code List} is copied to protect against
+ * subsequent modifications.
+ *
+ * @param stores a {@code List} of {@code CertStore}s (or
+ * {@code null})
+ * @throws ClassCastException if any of the elements in the list are
+ * not of type {@code java.security.cert.CertStore}
+ *
+ * @see #getCertStores
+ */
+ public void setCertStores(List<CertStore> stores) {
+ if (stores == null) {
+ this.certStores = new ArrayList<CertStore>();
+ } else {
+ for (Iterator<CertStore> i = stores.iterator(); i.hasNext();) {
+ if (!(i.next() instanceof CertStore)) {
+ throw new ClassCastException("all elements of list must be "
+ + "of type java.security.cert.CertStore");
+ }
+ }
+ this.certStores = new ArrayList<CertStore>(stores);
+ }
+ }
+
+ /**
+ * Adds a {@code CertStore} to the end of the list of
+ * {@code CertStore}s used in finding certificates and CRLs.
+ *
+ * @param store the {@code CertStore} to add. If {@code null},
+ * the store is ignored (not added to list).
+ */
+ public void addCertStore(CertStore store) {
+ if (store != null) {
+ this.certStores.add(store);
+ }
+ }
+
+ /**
+ * Returns an immutable {@code List} of {@code CertStore}s that
+ * are used to find certificates and CRLs.
+ *
+ * @return an immutable {@code List} of {@code CertStore}s
+ * (may be empty, but never {@code null})
+ *
+ * @see #setCertStores
+ */
+ public List<CertStore> getCertStores() {
+ return Collections.unmodifiableList
+ (new ArrayList<CertStore>(this.certStores));
+ }
+
+ /**
+ * Sets the RevocationEnabled flag. If this flag is true, the default
+ * revocation checking mechanism of the underlying PKIX service provider
+ * will be used. If this flag is false, the default revocation checking
+ * mechanism will be disabled (not used).
+ * <p>
+ * When a {@code PKIXParameters} object is created, this flag is set
+ * to true. This setting reflects the most common strategy for checking
+ * revocation, since each service provider must support revocation
+ * checking to be PKIX compliant. Sophisticated applications should set
+ * this flag to false when it is not practical to use a PKIX service
+ * provider's default revocation checking mechanism or when an alternative
+ * revocation checking mechanism is to be substituted (by also calling the
+ * {@link #addCertPathChecker addCertPathChecker} or {@link
+ * #setCertPathCheckers setCertPathCheckers} methods).
+ *
+ * @param val the new value of the RevocationEnabled flag
+ */
+ public void setRevocationEnabled(boolean val) {
+ revocationEnabled = val;
+ }
+
+ /**
+ * Checks the RevocationEnabled flag. If this flag is true, the default
+ * revocation checking mechanism of the underlying PKIX service provider
+ * will be used. If this flag is false, the default revocation checking
+ * mechanism will be disabled (not used). See the {@link
+ * #setRevocationEnabled setRevocationEnabled} method for more details on
+ * setting the value of this flag.
+ *
+ * @return the current value of the RevocationEnabled flag
+ */
+ public boolean isRevocationEnabled() {
+ return revocationEnabled;
+ }
+
+ /**
+ * Sets the ExplicitPolicyRequired flag. If this flag is true, an
+ * acceptable policy needs to be explicitly identified in every certificate.
+ * By default, the ExplicitPolicyRequired flag is false.
+ *
+ * @param val {@code true} if explicit policy is to be required,
+ * {@code false} otherwise
+ */
+ public void setExplicitPolicyRequired(boolean val) {
+ explicitPolicyRequired = val;
+ }
+
+ /**
+ * Checks if explicit policy is required. If this flag is true, an
+ * acceptable policy needs to be explicitly identified in every certificate.
+ * By default, the ExplicitPolicyRequired flag is false.
+ *
+ * @return {@code true} if explicit policy is required,
+ * {@code false} otherwise
+ */
+ public boolean isExplicitPolicyRequired() {
+ return explicitPolicyRequired;
+ }
+
+ /**
+ * Sets the PolicyMappingInhibited flag. If this flag is true, policy
+ * mapping is inhibited. By default, policy mapping is not inhibited (the
+ * flag is false).
+ *
+ * @param val {@code true} if policy mapping is to be inhibited,
+ * {@code false} otherwise
+ */
+ public void setPolicyMappingInhibited(boolean val) {
+ policyMappingInhibited = val;
+ }
+
+ /**
+ * Checks if policy mapping is inhibited. If this flag is true, policy
+ * mapping is inhibited. By default, policy mapping is not inhibited (the
+ * flag is false).
+ *
+ * @return true if policy mapping is inhibited, false otherwise
+ */
+ public boolean isPolicyMappingInhibited() {
+ return policyMappingInhibited;
+ }
+
+ /**
+ * Sets state to determine if the any policy OID should be processed
+ * if it is included in a certificate. By default, the any policy OID
+ * is not inhibited ({@link #isAnyPolicyInhibited isAnyPolicyInhibited()}
+ * returns {@code false}).
+ *
+ * @param val {@code true} if the any policy OID is to be
+ * inhibited, {@code false} otherwise
+ */
+ public void setAnyPolicyInhibited(boolean val) {
+ anyPolicyInhibited = val;
+ }
+
+ /**
+ * Checks whether the any policy OID should be processed if it
+ * is included in a certificate.
+ *
+ * @return {@code true} if the any policy OID is inhibited,
+ * {@code false} otherwise
+ */
+ public boolean isAnyPolicyInhibited() {
+ return anyPolicyInhibited;
+ }
+
+ /**
+ * Sets the PolicyQualifiersRejected flag. If this flag is true,
+ * certificates that include policy qualifiers in a certificate
+ * policies extension that is marked critical are rejected.
+ * If the flag is false, certificates are not rejected on this basis.
+ *
+ * <p> When a {@code PKIXParameters} object is created, this flag is
+ * set to true. This setting reflects the most common (and simplest)
+ * strategy for processing policy qualifiers. Applications that want to use
+ * a more sophisticated policy must set this flag to false.
+ * <p>
+ * Note that the PKIX certification path validation algorithm specifies
+ * that any policy qualifier in a certificate policies extension that is
+ * marked critical must be processed and validated. Otherwise the
+ * certification path must be rejected. If the policyQualifiersRejected flag
+ * is set to false, it is up to the application to validate all policy
+ * qualifiers in this manner in order to be PKIX compliant.
+ *
+ * @param qualifiersRejected the new value of the PolicyQualifiersRejected
+ * flag
+ * @see #getPolicyQualifiersRejected
+ * @see PolicyQualifierInfo
+ */
+ public void setPolicyQualifiersRejected(boolean qualifiersRejected) {
+ policyQualifiersRejected = qualifiersRejected;
+ }
+
+ /**
+ * Gets the PolicyQualifiersRejected flag. If this flag is true,
+ * certificates that include policy qualifiers in a certificate policies
+ * extension that is marked critical are rejected.
+ * If the flag is false, certificates are not rejected on this basis.
+ *
+ * <p> When a {@code PKIXParameters} object is created, this flag is
+ * set to true. This setting reflects the most common (and simplest)
+ * strategy for processing policy qualifiers. Applications that want to use
+ * a more sophisticated policy must set this flag to false.
+ *
+ * @return the current value of the PolicyQualifiersRejected flag
+ * @see #setPolicyQualifiersRejected
+ */
+ public boolean getPolicyQualifiersRejected() {
+ return policyQualifiersRejected;
+ }
+
+ /**
+ * Returns the time for which the validity of the certification path
+ * should be determined. If {@code null}, the current time is used.
+ * <p>
+ * Note that the {@code Date} returned is copied to protect against
+ * subsequent modifications.
+ *
+ * @return the {@code Date}, or {@code null} if not set
+ * @see #setDate
+ */
+ public Date getDate() {
+ if (date == null)
+ return null;
+ else
+ return (Date) this.date.clone();
+ }
+
+ /**
+ * Sets the time for which the validity of the certification path
+ * should be determined. If {@code null}, the current time is used.
+ * <p>
+ * Note that the {@code Date} supplied here is copied to protect
+ * against subsequent modifications.
+ *
+ * @param date the {@code Date}, or {@code null} for the
+ * current time
+ * @see #getDate
+ */
+ public void setDate(Date date) {
+ if (date != null)
+ this.date = (Date) date.clone();
+ else
+ date = null;
+ }
+
+ /**
+ * Sets a {@code List} of additional certification path checkers. If
+ * the specified {@code List} contains an object that is not a
+ * {@code PKIXCertPathChecker}, it is ignored.
+ * <p>
+ * Each {@code PKIXCertPathChecker} specified implements
+ * additional checks on a certificate. Typically, these are checks to
+ * process and verify private extensions contained in certificates.
+ * Each {@code PKIXCertPathChecker} should be instantiated with any
+ * initialization parameters needed to execute the check.
+ * <p>
+ * This method allows sophisticated applications to extend a PKIX
+ * {@code CertPathValidator} or {@code CertPathBuilder}.
+ * Each of the specified {@code PKIXCertPathChecker}s will be called,
+ * in turn, by a PKIX {@code CertPathValidator} or
+ * {@code CertPathBuilder} for each certificate processed or
+ * validated.
+ * <p>
+ * Regardless of whether these additional {@code PKIXCertPathChecker}s
+ * are set, a PKIX {@code CertPathValidator} or
+ * {@code CertPathBuilder} must perform all of the required PKIX
+ * checks on each certificate. The one exception to this rule is if the
+ * RevocationEnabled flag is set to false (see the {@link
+ * #setRevocationEnabled setRevocationEnabled} method).
+ * <p>
+ * Note that the {@code List} supplied here is copied and each
+ * {@code PKIXCertPathChecker} in the list is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param checkers a {@code List} of {@code PKIXCertPathChecker}s.
+ * May be {@code null}, in which case no additional checkers will be
+ * used.
+ * @throws ClassCastException if any of the elements in the list
+ * are not of type {@code java.security.cert.PKIXCertPathChecker}
+ * @see #getCertPathCheckers
+ */
+ public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) {
+ if (checkers != null) {
+ List<PKIXCertPathChecker> tmpList =
+ new ArrayList<PKIXCertPathChecker>();
+ for (PKIXCertPathChecker checker : checkers) {
+ tmpList.add((PKIXCertPathChecker)checker.clone());
+ }
+ this.certPathCheckers = tmpList;
+ } else {
+ this.certPathCheckers = new ArrayList<PKIXCertPathChecker>();
+ }
+ }
+
+ /**
+ * Returns the {@code List} of certification path checkers.
+ * The returned {@code List} is immutable, and each
+ * {@code PKIXCertPathChecker} in the {@code List} is cloned
+ * to protect against subsequent modifications.
+ *
+ * @return an immutable {@code List} of
+ * {@code PKIXCertPathChecker}s (may be empty, but not
+ * {@code null})
+ * @see #setCertPathCheckers
+ */
+ public List<PKIXCertPathChecker> getCertPathCheckers() {
+ List<PKIXCertPathChecker> tmpList = new ArrayList<PKIXCertPathChecker>();
+ for (PKIXCertPathChecker ck : certPathCheckers) {
+ tmpList.add((PKIXCertPathChecker)ck.clone());
+ }
+ return Collections.unmodifiableList(tmpList);
+ }
+
+ /**
+ * Adds a {@code PKIXCertPathChecker} to the list of certification
+ * path checkers. See the {@link #setCertPathCheckers setCertPathCheckers}
+ * method for more details.
+ * <p>
+ * Note that the {@code PKIXCertPathChecker} is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param checker a {@code PKIXCertPathChecker} to add to the list of
+ * checks. If {@code null}, the checker is ignored (not added to list).
+ */
+ public void addCertPathChecker(PKIXCertPathChecker checker) {
+ if (checker != null) {
+ certPathCheckers.add((PKIXCertPathChecker)checker.clone());
+ }
+ }
+
+ /**
+ * Returns the signature provider's name, or {@code null}
+ * if not set.
+ *
+ * @return the signature provider's name (or {@code null})
+ * @see #setSigProvider
+ */
+ public String getSigProvider() {
+ return this.sigProvider;
+ }
+
+ /**
+ * Sets the signature provider's name. The specified provider will be
+ * preferred when creating {@link java.security.Signature Signature}
+ * objects. If {@code null} or not set, the first provider found
+ * supporting the algorithm will be used.
+ *
+ * @param sigProvider the signature provider's name (or {@code null})
+ * @see #getSigProvider
+ */
+ public void setSigProvider(String sigProvider) {
+ this.sigProvider = sigProvider;
+ }
+
+ /**
+ * Returns the required constraints on the target certificate.
+ * The constraints are returned as an instance of {@code CertSelector}.
+ * If {@code null}, no constraints are defined.
+ *
+ * <p>Note that the {@code CertSelector} returned is cloned
+ * to protect against subsequent modifications.
+ *
+ * @return a {@code CertSelector} specifying the constraints
+ * on the target certificate (or {@code null})
+ * @see #setTargetCertConstraints
+ */
+ public CertSelector getTargetCertConstraints() {
+ if (certSelector != null) {
+ return (CertSelector) certSelector.clone();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the required constraints on the target certificate.
+ * The constraints are specified as an instance of
+ * {@code CertSelector}. If {@code null}, no constraints are
+ * defined.
+ *
+ * <p>Note that the {@code CertSelector} specified is cloned
+ * to protect against subsequent modifications.
+ *
+ * @param selector a {@code CertSelector} specifying the constraints
+ * on the target certificate (or {@code null})
+ * @see #getTargetCertConstraints
+ */
+ public void setTargetCertConstraints(CertSelector selector) {
+ if (selector != null)
+ certSelector = (CertSelector) selector.clone();
+ else
+ certSelector = null;
+ }
+
+ /**
+ * Makes a copy of this {@code PKIXParameters} object. Changes
+ * to the copy will not affect the original and vice versa.
+ *
+ * @return a copy of this {@code PKIXParameters} object
+ */
+ public Object clone() {
+ try {
+ PKIXParameters copy = (PKIXParameters)super.clone();
+
+ // must clone these because addCertStore, et al. modify them
+ if (certStores != null) {
+ copy.certStores = new ArrayList<CertStore>(certStores);
+ }
+ if (certPathCheckers != null) {
+ copy.certPathCheckers =
+ new ArrayList<PKIXCertPathChecker>(certPathCheckers.size());
+ for (PKIXCertPathChecker checker : certPathCheckers) {
+ copy.certPathCheckers.add(
+ (PKIXCertPathChecker)checker.clone());
+ }
+ }
+
+ // other class fields are immutable to public, don't bother
+ // to clone the read-only fields.
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+
+ /**
+ * Returns a formatted string describing the parameters.
+ *
+ * @return a formatted string describing the parameters.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[\n");
+
+ /* start with trusted anchor info */
+ if (unmodTrustAnchors != null) {
+ sb.append(" Trust Anchors: " + unmodTrustAnchors.toString()
+ + "\n");
+ }
+
+ /* now, append initial state information */
+ if (unmodInitialPolicies != null) {
+ if (unmodInitialPolicies.isEmpty()) {
+ sb.append(" Initial Policy OIDs: any\n");
+ } else {
+ sb.append(" Initial Policy OIDs: ["
+ + unmodInitialPolicies.toString() + "]\n");
+ }
+ }
+
+ /* now, append constraints on all certificates in the path */
+ sb.append(" Validity Date: " + String.valueOf(date) + "\n");
+ sb.append(" Signature Provider: " + String.valueOf(sigProvider) + "\n");
+ sb.append(" Default Revocation Enabled: " + revocationEnabled + "\n");
+ sb.append(" Explicit Policy Required: " + explicitPolicyRequired + "\n");
+ sb.append(" Policy Mapping Inhibited: " + policyMappingInhibited + "\n");
+ sb.append(" Any Policy Inhibited: " + anyPolicyInhibited + "\n");
+ sb.append(" Policy Qualifiers Rejected: " + policyQualifiersRejected + "\n");
+
+ /* now, append target cert requirements */
+ sb.append(" Target Cert Constraints: " + String.valueOf(certSelector) + "\n");
+
+ /* finally, append miscellaneous parameters */
+ if (certPathCheckers != null)
+ sb.append(" Certification Path Checkers: ["
+ + certPathCheckers.toString() + "]\n");
+ if (certStores != null)
+ sb.append(" CertStores: [" + certStores.toString() + "]\n");
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/PKIXReason.java b/java/security/cert/PKIXReason.java
new file mode 100644
index 0000000..d58ded9
--- /dev/null
+++ b/java/security/cert/PKIXReason.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+/**
+ * The {@code PKIXReason} enumerates the potential PKIX-specific reasons
+ * that an X.509 certification path may be invalid according to the PKIX
+ * (RFC 3280) standard. These reasons are in addition to those of the
+ * {@code CertPathValidatorException.BasicReason} enumeration.
+ *
+ * @since 1.7
+ */
+public enum PKIXReason implements CertPathValidatorException.Reason {
+ /**
+ * The certificate does not chain correctly.
+ */
+ NAME_CHAINING,
+
+ /**
+ * The certificate's key usage is invalid.
+ */
+ INVALID_KEY_USAGE,
+
+ /**
+ * The policy constraints have been violated.
+ */
+ INVALID_POLICY,
+
+ /**
+ * No acceptable trust anchor found.
+ */
+ NO_TRUST_ANCHOR,
+
+ /**
+ * The certificate contains one or more unrecognized critical
+ * extensions.
+ */
+ UNRECOGNIZED_CRIT_EXT,
+
+ /**
+ * The certificate is not a CA certificate.
+ */
+ NOT_CA_CERT,
+
+ /**
+ * The path length constraint has been violated.
+ */
+ PATH_TOO_LONG,
+
+ /**
+ * The name constraints have been violated.
+ */
+ INVALID_NAME
+}
diff --git a/java/security/cert/PKIXRevocationChecker.java b/java/security/cert/PKIXRevocationChecker.java
new file mode 100644
index 0000000..620291e
--- /dev/null
+++ b/java/security/cert/PKIXRevocationChecker.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.cert;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * A {@code PKIXCertPathChecker} for checking the revocation status of
+ * certificates with the PKIX algorithm.
+ *
+ * <p>A {@code PKIXRevocationChecker} checks the revocation status of
+ * certificates with the Online Certificate Status Protocol (OCSP) or
+ * Certificate Revocation Lists (CRLs). OCSP is described in RFC 2560 and
+ * is a network protocol for determining the status of a certificate. A CRL
+ * is a time-stamped list identifying revoked certificates, and RFC 5280
+ * describes an algorithm for determining the revocation status of certificates
+ * using CRLs.
+ *
+ * <p>Each {@code PKIXRevocationChecker} must be able to check the revocation
+ * status of certificates with OCSP and CRLs. By default, OCSP is the
+ * preferred mechanism for checking revocation status, with CRLs as the
+ * fallback mechanism. However, this preference can be switched to CRLs with
+ * the {@link Option#PREFER_CRLS PREFER_CRLS} option. In addition, the fallback
+ * mechanism can be disabled with the {@link Option#NO_FALLBACK NO_FALLBACK}
+ * option.
+ *
+ * <p>A {@code PKIXRevocationChecker} is obtained by calling the
+ * {@link CertPathValidator#getRevocationChecker getRevocationChecker} method
+ * of a PKIX {@code CertPathValidator}. Additional parameters and options
+ * specific to revocation can be set (by calling the
+ * {@link #setOcspResponder setOcspResponder} method for instance). The
+ * {@code PKIXRevocationChecker} is added to a {@code PKIXParameters} object
+ * using the {@link PKIXParameters#addCertPathChecker addCertPathChecker}
+ * or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method,
+ * and then the {@code PKIXParameters} is passed along with the {@code CertPath}
+ * to be validated to the {@link CertPathValidator#validate validate} method
+ * of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
+ * this manner, it will be used to check revocation irrespective of the setting
+ * of the {@link PKIXParameters#isRevocationEnabled RevocationEnabled} flag.
+ * Similarly, a {@code PKIXRevocationChecker} may be added to a
+ * {@code PKIXBuilderParameters} object for use with a PKIX
+ * {@code CertPathBuilder}.
+ *
+ * <p>Note that when a {@code PKIXRevocationChecker} is added to
+ * {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
+ * thus any subsequent modifications to the {@code PKIXRevocationChecker}
+ * have no effect.
+ *
+ * <p>Any parameter that is not set (or is set to {@code null}) will be set to
+ * the default value for that parameter.
+ *
+ * <p><b>Concurrent Access</b>
+ *
+ * <p>Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single object
+ * concurrently should synchronize amongst themselves and provide the
+ * necessary locking. Multiple threads each manipulating separate objects
+ * need not synchronize.
+ *
+ * <p>See RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate Status Protocol -
+ * OCSP, RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation
+ * List (CRL) Profile (Android note: this paragraph was originally in a malformed "see" tag below,
+ * moved here for correct construction of the docs).
+ *
+ * @since 1.8
+
+ */
+public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
+ private URI ocspResponder;
+ private X509Certificate ocspResponderCert;
+ private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
+ private Map<X509Certificate, byte[]> ocspResponses = Collections.emptyMap();
+ private Set<Option> options = Collections.emptySet();
+
+ /**
+ * Default constructor.
+ */
+ protected PKIXRevocationChecker() {}
+
+ /**
+ * Sets the URI that identifies the location of the OCSP responder. This
+ * overrides the {@code ocsp.responderURL} security property and any
+ * responder specified in a certificate's Authority Information Access
+ * Extension, as defined in RFC 5280.
+ *
+ * @param uri the responder URI
+ */
+ public void setOcspResponder(URI uri) {
+ this.ocspResponder = uri;
+ }
+
+ /**
+ * Gets the URI that identifies the location of the OCSP responder. This
+ * overrides the {@code ocsp.responderURL} security property. If this
+ * parameter or the {@code ocsp.responderURL} property is not set, the
+ * location is determined from the certificate's Authority Information
+ * Access Extension, as defined in RFC 5280.
+ *
+ * @return the responder URI, or {@code null} if not set
+ */
+ public URI getOcspResponder() {
+ return ocspResponder;
+ }
+
+ /**
+ * Sets the OCSP responder's certificate. This overrides the
+ * {@code ocsp.responderCertSubjectName},
+ * {@code ocsp.responderCertIssuerName},
+ * and {@code ocsp.responderCertSerialNumber} security properties.
+ *
+ * @param cert the responder's certificate
+ */
+ public void setOcspResponderCert(X509Certificate cert) {
+ this.ocspResponderCert = cert;
+ }
+
+ /**
+ * Gets the OCSP responder's certificate. This overrides the
+ * {@code ocsp.responderCertSubjectName},
+ * {@code ocsp.responderCertIssuerName},
+ * and {@code ocsp.responderCertSerialNumber} security properties. If this
+ * parameter or the aforementioned properties are not set, then the
+ * responder's certificate is determined as specified in RFC 2560.
+ *
+ * @return the responder's certificate, or {@code null} if not set
+ */
+ public X509Certificate getOcspResponderCert() {
+ return ocspResponderCert;
+ }
+
+ // request extensions; single extensions not supported
+ /**
+ * Sets the optional OCSP request extensions.
+ *
+ * @param extensions a list of extensions. The list is copied to protect
+ * against subsequent modification.
+ */
+ public void setOcspExtensions(List<Extension> extensions)
+ {
+ this.ocspExtensions = (extensions == null)
+ ? Collections.<Extension>emptyList()
+ : new ArrayList<Extension>(extensions);
+ }
+
+ /**
+ * Gets the optional OCSP request extensions.
+ *
+ * @return an unmodifiable list of extensions. The list is empty if no
+ * extensions have been specified.
+ */
+ public List<Extension> getOcspExtensions() {
+ return Collections.unmodifiableList(ocspExtensions);
+ }
+
+ /**
+ * Sets the OCSP responses. These responses are used to determine
+ * the revocation status of the specified certificates when OCSP is used.
+ *
+ * @param responses a map of OCSP responses. Each key is an
+ * {@code X509Certificate} that maps to the corresponding
+ * DER-encoded OCSP response for that certificate. A deep copy of
+ * the map is performed to protect against subsequent modification.
+ */
+ public void setOcspResponses(Map<X509Certificate, byte[]> responses)
+ {
+ if (responses == null) {
+ this.ocspResponses = Collections.<X509Certificate, byte[]>emptyMap();
+ } else {
+ Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
+ for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
+ copy.put(e.getKey(), e.getValue().clone());
+ }
+ this.ocspResponses = copy;
+ }
+ }
+
+ /**
+ * Gets the OCSP responses. These responses are used to determine
+ * the revocation status of the specified certificates when OCSP is used.
+ *
+ * @return a map of OCSP responses. Each key is an
+ * {@code X509Certificate} that maps to the corresponding
+ * DER-encoded OCSP response for that certificate. A deep copy of
+ * the map is returned to protect against subsequent modification.
+ * Returns an empty map if no responses have been specified.
+ */
+ public Map<X509Certificate, byte[]> getOcspResponses() {
+ Map<X509Certificate, byte[]> copy = new HashMap<>(ocspResponses.size());
+ for (Map.Entry<X509Certificate, byte[]> e : ocspResponses.entrySet()) {
+ copy.put(e.getKey(), e.getValue().clone());
+ }
+ return copy;
+ }
+
+ /**
+ * Sets the revocation options.
+ *
+ * @param options a set of revocation options. The set is copied to protect
+ * against subsequent modification.
+ */
+ public void setOptions(Set<Option> options) {
+ this.options = (options == null)
+ ? Collections.<Option>emptySet()
+ : new HashSet<Option>(options);
+ }
+
+ /**
+ * Gets the revocation options.
+ *
+ * @return an unmodifiable set of revocation options. The set is empty if
+ * no options have been specified.
+ */
+ public Set<Option> getOptions() {
+ return Collections.unmodifiableSet(options);
+ }
+
+ /**
+ * Returns a list containing the exceptions that are ignored by the
+ * revocation checker when the {@link Option#SOFT_FAIL SOFT_FAIL} option
+ * is set. The list is cleared each time {@link #init init} is called.
+ * The list is ordered in ascending order according to the certificate
+ * index returned by {@link CertPathValidatorException#getIndex getIndex}
+ * method of each entry.
+ * <p>
+ * An implementation of {@code PKIXRevocationChecker} is responsible for
+ * adding the ignored exceptions to the list.
+ *
+ * @return an unmodifiable list containing the ignored exceptions. The list
+ * is empty if no exceptions have been ignored.
+ */
+ public abstract List<CertPathValidatorException> getSoftFailExceptions();
+
+ @Override
+ public PKIXRevocationChecker clone() {
+ PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
+ copy.ocspExtensions = new ArrayList<>(ocspExtensions);
+ copy.ocspResponses = new HashMap<>(ocspResponses);
+ // deep-copy the encoded responses, since they are mutable
+ for (Map.Entry<X509Certificate, byte[]> entry :
+ copy.ocspResponses.entrySet())
+ {
+ byte[] encoded = entry.getValue();
+ entry.setValue(encoded.clone());
+ }
+ copy.options = new HashSet<>(options);
+ return copy;
+ }
+
+ /**
+ * Various revocation options that can be specified for the revocation
+ * checking mechanism.
+ */
+ public enum Option {
+ /**
+ * Only check the revocation status of end-entity certificates.
+ */
+ ONLY_END_ENTITY,
+ /**
+ * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each
+ * PKIX implementation should document further details of their
+ * specific preference rules and fallback policies.
+ */
+ PREFER_CRLS,
+ /**
+ * Disable the fallback mechanism.
+ */
+ NO_FALLBACK,
+ /**
+ * Allow revocation check to succeed if the revocation status cannot be
+ * determined for one of the following reasons:
+ * <ul>
+ * <li>The CRL or OCSP response cannot be obtained because of a
+ * network error.
+ * <li>The OCSP responder returns one of the following errors
+ * specified in section 2.3 of RFC 2560: internalError or tryLater.
+ * </ul><br>
+ * Note that these conditions apply to both OCSP and CRLs, and unless
+ * the {@code NO_FALLBACK} option is set, the revocation check is
+ * allowed to succeed only if both mechanisms fail under one of the
+ * conditions as stated above.
+ * Exceptions that cause the network errors are ignored but can be
+ * later retrieved by calling the
+ * {@link #getSoftFailExceptions getSoftFailExceptions} method.
+ */
+ SOFT_FAIL
+ }
+}
diff --git a/java/security/cert/PolicyNode.java b/java/security/cert/PolicyNode.java
new file mode 100644
index 0000000..1633dcb
--- /dev/null
+++ b/java/security/cert/PolicyNode.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * An immutable valid policy tree node as defined by the PKIX certification
+ * path validation algorithm.
+ *
+ * <p>One of the outputs of the PKIX certification path validation
+ * algorithm is a valid policy tree, which includes the policies that
+ * were determined to be valid, how this determination was reached,
+ * and any policy qualifiers encountered. This tree is of depth
+ * <i>n</i>, where <i>n</i> is the length of the certification
+ * path that has been validated.
+ *
+ * <p>Most applications will not need to examine the valid policy tree.
+ * They can achieve their policy processing goals by setting the
+ * policy-related parameters in {@code PKIXParameters}. However,
+ * the valid policy tree is available for more sophisticated applications,
+ * especially those that process policy qualifiers.
+ *
+ * <p>{@link PKIXCertPathValidatorResult#getPolicyTree()
+ * PKIXCertPathValidatorResult.getPolicyTree} returns the root node of the
+ * valid policy tree. The tree can be traversed using the
+ * {@link #getChildren getChildren} and {@link #getParent getParent} methods.
+ * Data about a particular node can be retrieved using other methods of
+ * {@code PolicyNode}.
+ *
+ * <p><b>Concurrent Access</b>
+ * <p>All {@code PolicyNode} objects must be immutable and
+ * thread-safe. Multiple threads may concurrently invoke the methods defined
+ * in this class on a single {@code PolicyNode} object (or more than one)
+ * with no ill effects. This stipulation applies to all public fields and
+ * methods of this class and any added or overridden by subclasses.
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public interface PolicyNode {
+
+ /**
+ * Returns the parent of this node, or {@code null} if this is the
+ * root node.
+ *
+ * @return the parent of this node, or {@code null} if this is the
+ * root node
+ */
+ PolicyNode getParent();
+
+ /**
+ * Returns an iterator over the children of this node. Any attempts to
+ * modify the children of this node through the
+ * {@code Iterator}'s remove method must throw an
+ * {@code UnsupportedOperationException}.
+ *
+ * @return an iterator over the children of this node
+ */
+ Iterator<? extends PolicyNode> getChildren();
+
+ /**
+ * Returns the depth of this node in the valid policy tree.
+ *
+ * @return the depth of this node (0 for the root node, 1 for its
+ * children, and so on)
+ */
+ int getDepth();
+
+ /**
+ * Returns the valid policy represented by this node.
+ *
+ * @return the {@code String} OID of the valid policy
+ * represented by this node. For the root node, this method always returns
+ * the special anyPolicy OID: "2.5.29.32.0".
+ */
+ String getValidPolicy();
+
+ /**
+ * Returns the set of policy qualifiers associated with the
+ * valid policy represented by this node.
+ *
+ * @return an immutable {@code Set} of
+ * {@code PolicyQualifierInfo}s. For the root node, this
+ * is always an empty {@code Set}.
+ */
+ Set<? extends PolicyQualifierInfo> getPolicyQualifiers();
+
+ /**
+ * Returns the set of expected policies that would satisfy this
+ * node's valid policy in the next certificate to be processed.
+ *
+ * @return an immutable {@code Set} of expected policy
+ * {@code String} OIDs. For the root node, this method
+ * always returns a {@code Set} with one element, the
+ * special anyPolicy OID: "2.5.29.32.0".
+ */
+ Set<String> getExpectedPolicies();
+
+ /**
+ * Returns the criticality indicator of the certificate policy extension
+ * in the most recently processed certificate.
+ *
+ * @return {@code true} if extension marked critical,
+ * {@code false} otherwise. For the root node, {@code false}
+ * is always returned.
+ */
+ boolean isCritical();
+}
diff --git a/java/security/cert/PolicyQualifierInfo.java b/java/security/cert/PolicyQualifierInfo.java
new file mode 100644
index 0000000..ec06a88
--- /dev/null
+++ b/java/security/cert/PolicyQualifierInfo.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.IOException;
+
+import sun.misc.HexDumpEncoder;
+import sun.security.util.DerValue;
+
+/**
+ * An immutable policy qualifier represented by the ASN.1 PolicyQualifierInfo
+ * structure.
+ *
+ * <p>The ASN.1 definition is as follows:
+ * <pre>
+ * PolicyQualifierInfo ::= SEQUENCE {
+ * policyQualifierId PolicyQualifierId,
+ * qualifier ANY DEFINED BY policyQualifierId }
+ * </pre>
+ * <p>
+ * A certificate policies extension, if present in an X.509 version 3
+ * certificate, contains a sequence of one or more policy information terms,
+ * each of which consists of an object identifier (OID) and optional
+ * qualifiers. In an end-entity certificate, these policy information terms
+ * indicate the policy under which the certificate has been issued and the
+ * purposes for which the certificate may be used. In a CA certificate, these
+ * policy information terms limit the set of policies for certification paths
+ * which include this certificate.
+ * <p>
+ * A {@code Set} of {@code PolicyQualifierInfo} objects are returned
+ * by the {@link PolicyNode#getPolicyQualifiers PolicyNode.getPolicyQualifiers}
+ * method. This allows applications with specific policy requirements to
+ * process and validate each policy qualifier. Applications that need to
+ * process policy qualifiers should explicitly set the
+ * {@code policyQualifiersRejected} flag to false (by calling the
+ * {@link PKIXParameters#setPolicyQualifiersRejected
+ * PKIXParameters.setPolicyQualifiersRejected} method) before validating
+ * a certification path.
+ *
+ * <p>Note that the PKIX certification path validation algorithm specifies
+ * that any policy qualifier in a certificate policies extension that is
+ * marked critical must be processed and validated. Otherwise the
+ * certification path must be rejected. If the
+ * {@code policyQualifiersRejected} flag is set to false, it is up to
+ * the application to validate all policy qualifiers in this manner in order
+ * to be PKIX compliant.
+ *
+ * <p><b>Concurrent Access</b>
+ *
+ * <p>All {@code PolicyQualifierInfo} objects must be immutable and
+ * thread-safe. That is, multiple threads may concurrently invoke the
+ * methods defined in this class on a single {@code PolicyQualifierInfo}
+ * object (or more than one) with no ill effects. Requiring
+ * {@code PolicyQualifierInfo} objects to be immutable and thread-safe
+ * allows them to be passed around to various pieces of code without
+ * worrying about coordinating access.
+ *
+ * @author seth proctor
+ * @author Sean Mullan
+ * @since 1.4
+ */
+public class PolicyQualifierInfo {
+
+ private byte [] mEncoded;
+ private String mId;
+ private byte [] mData;
+ private String pqiString;
+
+ /**
+ * Creates an instance of {@code PolicyQualifierInfo} from the
+ * encoded bytes. The encoded byte array is copied on construction.
+ *
+ * @param encoded a byte array containing the qualifier in DER encoding
+ * @exception IOException thrown if the byte array does not represent a
+ * valid and parsable policy qualifier
+ */
+ public PolicyQualifierInfo(byte[] encoded) throws IOException {
+ mEncoded = encoded.clone();
+
+ DerValue val = new DerValue(mEncoded);
+ if (val.tag != DerValue.tag_Sequence)
+ throw new IOException("Invalid encoding for PolicyQualifierInfo");
+
+ mId = (val.data.getDerValue()).getOID().toString();
+ byte [] tmp = val.data.toByteArray();
+ if (tmp == null) {
+ mData = null;
+ } else {
+ mData = new byte[tmp.length];
+ System.arraycopy(tmp, 0, mData, 0, tmp.length);
+ }
+ }
+
+ /**
+ * Returns the {@code policyQualifierId} field of this
+ * {@code PolicyQualifierInfo}. The {@code policyQualifierId}
+ * is an Object Identifier (OID) represented by a set of nonnegative
+ * integers separated by periods.
+ *
+ * @return the OID (never {@code null})
+ */
+ public final String getPolicyQualifierId() {
+ return mId;
+ }
+
+ /**
+ * Returns the ASN.1 DER encoded form of this
+ * {@code PolicyQualifierInfo}.
+ *
+ * @return the ASN.1 DER encoded bytes (never {@code null}).
+ * Note that a copy is returned, so the data is cloned each time
+ * this method is called.
+ */
+ public final byte[] getEncoded() {
+ return mEncoded.clone();
+ }
+
+ /**
+ * Returns the ASN.1 DER encoded form of the {@code qualifier}
+ * field of this {@code PolicyQualifierInfo}.
+ *
+ * @return the ASN.1 DER encoded bytes of the {@code qualifier}
+ * field. Note that a copy is returned, so the data is cloned each
+ * time this method is called.
+ */
+ public final byte[] getPolicyQualifier() {
+ return (mData == null ? null : mData.clone());
+ }
+
+ /**
+ * Return a printable representation of this
+ * {@code PolicyQualifierInfo}.
+ *
+ * @return a {@code String} describing the contents of this
+ * {@code PolicyQualifierInfo}
+ */
+ public String toString() {
+ if (pqiString != null)
+ return pqiString;
+ HexDumpEncoder enc = new HexDumpEncoder();
+ StringBuffer sb = new StringBuffer();
+ sb.append("PolicyQualifierInfo: [\n");
+ sb.append(" qualifierID: " + mId + "\n");
+ sb.append(" qualifier: " +
+ (mData == null ? "null" : enc.encodeBuffer(mData)) + "\n");
+ sb.append("]");
+ pqiString = sb.toString();
+ return pqiString;
+ }
+}
diff --git a/java/security/cert/TrustAnchor.java b/java/security/cert/TrustAnchor.java
new file mode 100644
index 0000000..c98bf81
--- /dev/null
+++ b/java/security/cert/TrustAnchor.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.IOException;
+import java.security.PublicKey;
+
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.x509.NameConstraintsExtension;
+import sun.security.x509.X500Name;
+
+/**
+ * A trust anchor or most-trusted Certification Authority (CA).
+ * <p>
+ * This class represents a "most-trusted CA", which is used as a trust anchor
+ * for validating X.509 certification paths. A most-trusted CA includes the
+ * public key of the CA, the CA's name, and any constraints upon the set of
+ * paths which may be validated using this key. These parameters can be
+ * specified in the form of a trusted {@code X509Certificate} or as
+ * individual parameters.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>All {@code TrustAnchor} objects must be immutable and
+ * thread-safe. That is, multiple threads may concurrently invoke the
+ * methods defined in this class on a single {@code TrustAnchor}
+ * object (or more than one) with no ill effects. Requiring
+ * {@code TrustAnchor} objects to be immutable and thread-safe
+ * allows them to be passed around to various pieces of code without
+ * worrying about coordinating access. This stipulation applies to all
+ * public fields and methods of this class and any added or overridden
+ * by subclasses.
+ *
+ * @see PKIXParameters#PKIXParameters(Set)
+ * @see PKIXBuilderParameters#PKIXBuilderParameters(Set, CertSelector)
+ *
+ * @since 1.4
+ * @author Sean Mullan
+ */
+public class TrustAnchor {
+
+ private final PublicKey pubKey;
+ private final String caName;
+ private final X500Principal caPrincipal;
+ private final X509Certificate trustedCert;
+ private byte[] ncBytes;
+ private NameConstraintsExtension nc;
+
+ /**
+ * Creates an instance of {@code TrustAnchor} with the specified
+ * {@code X509Certificate} and optional name constraints, which
+ * are intended to be used as additional constraints when validating
+ * an X.509 certification path.
+ * <p>
+ * The name constraints are specified as a byte array. This byte array
+ * should contain the DER encoded form of the name constraints, as they
+ * would appear in the NameConstraints structure defined in
+ * <a href="http://www.ietf.org/rfc/rfc3280">RFC 3280</a>
+ * and X.509. The ASN.1 definition of this structure appears below.
+ *
+ * <pre>{@code
+ * NameConstraints ::= SEQUENCE {
+ * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ *
+ * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+ *
+ * GeneralSubtree ::= SEQUENCE {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL }
+ *
+ * BaseDistance ::= INTEGER (0..MAX)
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ * }</pre>
+ * <p>
+ * Note that the name constraints byte array supplied is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param trustedCert a trusted {@code X509Certificate}
+ * @param nameConstraints a byte array containing the ASN.1 DER encoding of
+ * a NameConstraints extension to be used for checking name constraints.
+ * Only the value of the extension is included, not the OID or criticality
+ * flag. Specify {@code null} to omit the parameter.
+ * @throws IllegalArgumentException if the name constraints cannot be
+ * decoded
+ * @throws NullPointerException if the specified
+ * {@code X509Certificate} is {@code null}
+ */
+ public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints)
+ {
+ if (trustedCert == null)
+ throw new NullPointerException("the trustedCert parameter must " +
+ "be non-null");
+ this.trustedCert = trustedCert;
+ this.pubKey = null;
+ this.caName = null;
+ this.caPrincipal = null;
+ setNameConstraints(nameConstraints);
+ }
+
+ /**
+ * Creates an instance of {@code TrustAnchor} where the
+ * most-trusted CA is specified as an X500Principal and public key.
+ * Name constraints are an optional parameter, and are intended to be used
+ * as additional constraints when validating an X.509 certification path.
+ * <p>
+ * The name constraints are specified as a byte array. This byte array
+ * contains the DER encoded form of the name constraints, as they
+ * would appear in the NameConstraints structure defined in RFC 3280
+ * and X.509. The ASN.1 notation for this structure is supplied in the
+ * documentation for
+ * {@link #TrustAnchor(X509Certificate, byte[])
+ * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
+ * <p>
+ * Note that the name constraints byte array supplied here is cloned to
+ * protect against subsequent modifications.
+ *
+ * @param caPrincipal the name of the most-trusted CA as X500Principal
+ * @param pubKey the public key of the most-trusted CA
+ * @param nameConstraints a byte array containing the ASN.1 DER encoding of
+ * a NameConstraints extension to be used for checking name constraints.
+ * Only the value of the extension is included, not the OID or criticality
+ * flag. Specify {@code null} to omit the parameter.
+ * @throws NullPointerException if the specified {@code caPrincipal} or
+ * {@code pubKey} parameter is {@code null}
+ * @since 1.5
+ */
+ public TrustAnchor(X500Principal caPrincipal, PublicKey pubKey,
+ byte[] nameConstraints) {
+ if ((caPrincipal == null) || (pubKey == null)) {
+ throw new NullPointerException();
+ }
+ this.trustedCert = null;
+ this.caPrincipal = caPrincipal;
+ this.caName = caPrincipal.getName();
+ this.pubKey = pubKey;
+ setNameConstraints(nameConstraints);
+ }
+
+ /**
+ * Creates an instance of {@code TrustAnchor} where the
+ * most-trusted CA is specified as a distinguished name and public key.
+ * Name constraints are an optional parameter, and are intended to be used
+ * as additional constraints when validating an X.509 certification path.
+ * <p>
+ * The name constraints are specified as a byte array. This byte array
+ * contains the DER encoded form of the name constraints, as they
+ * would appear in the NameConstraints structure defined in RFC 3280
+ * and X.509. The ASN.1 notation for this structure is supplied in the
+ * documentation for
+ * {@link #TrustAnchor(X509Certificate, byte[])
+ * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
+ * <p>
+ * Note that the name constraints byte array supplied here is cloned to
+ * protect against subsequent modifications.
+ *
+ * @param caName the X.500 distinguished name of the most-trusted CA in
+ * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>
+ * {@code String} format
+ * @param pubKey the public key of the most-trusted CA
+ * @param nameConstraints a byte array containing the ASN.1 DER encoding of
+ * a NameConstraints extension to be used for checking name constraints.
+ * Only the value of the extension is included, not the OID or criticality
+ * flag. Specify {@code null} to omit the parameter.
+ * @throws IllegalArgumentException if the specified
+ * {@code caName} parameter is empty {@code (caName.length() == 0)}
+ * or incorrectly formatted or the name constraints cannot be decoded
+ * @throws NullPointerException if the specified {@code caName} or
+ * {@code pubKey} parameter is {@code null}
+ */
+ public TrustAnchor(String caName, PublicKey pubKey, byte[] nameConstraints)
+ {
+ if (pubKey == null)
+ throw new NullPointerException("the pubKey parameter must be " +
+ "non-null");
+ if (caName == null)
+ throw new NullPointerException("the caName parameter must be " +
+ "non-null");
+ if (caName.length() == 0)
+ throw new IllegalArgumentException("the caName " +
+ "parameter must be a non-empty String");
+ // check if caName is formatted correctly
+ this.caPrincipal = new X500Principal(caName);
+ this.pubKey = pubKey;
+ this.caName = caName;
+ this.trustedCert = null;
+ setNameConstraints(nameConstraints);
+ }
+
+ /**
+ * Returns the most-trusted CA certificate.
+ *
+ * @return a trusted {@code X509Certificate} or {@code null}
+ * if the trust anchor was not specified as a trusted certificate
+ */
+ public final X509Certificate getTrustedCert() {
+ return this.trustedCert;
+ }
+
+ /**
+ * Returns the name of the most-trusted CA as an X500Principal.
+ *
+ * @return the X.500 distinguished name of the most-trusted CA, or
+ * {@code null} if the trust anchor was not specified as a trusted
+ * public key and name or X500Principal pair
+ * @since 1.5
+ */
+ public final X500Principal getCA() {
+ return this.caPrincipal;
+ }
+
+ /**
+ * Returns the name of the most-trusted CA in RFC 2253 {@code String}
+ * format.
+ *
+ * @return the X.500 distinguished name of the most-trusted CA, or
+ * {@code null} if the trust anchor was not specified as a trusted
+ * public key and name or X500Principal pair
+ */
+ public final String getCAName() {
+ return this.caName;
+ }
+
+ /**
+ * Returns the public key of the most-trusted CA.
+ *
+ * @return the public key of the most-trusted CA, or {@code null}
+ * if the trust anchor was not specified as a trusted public key and name
+ * or X500Principal pair
+ */
+ public final PublicKey getCAPublicKey() {
+ return this.pubKey;
+ }
+
+ /**
+ * Decode the name constraints and clone them if not null.
+ */
+ private void setNameConstraints(byte[] bytes) {
+ if (bytes == null) {
+ ncBytes = null;
+ nc = null;
+ } else {
+ ncBytes = bytes.clone();
+ // validate DER encoding
+ try {
+ nc = new NameConstraintsExtension(Boolean.FALSE, bytes);
+ } catch (IOException ioe) {
+ IllegalArgumentException iae =
+ new IllegalArgumentException(ioe.getMessage());
+ iae.initCause(ioe);
+ throw iae;
+ }
+ }
+ }
+
+ /**
+ * Returns the name constraints parameter. The specified name constraints
+ * are associated with this trust anchor and are intended to be used
+ * as additional constraints when validating an X.509 certification path.
+ * <p>
+ * The name constraints are returned as a byte array. This byte array
+ * contains the DER encoded form of the name constraints, as they
+ * would appear in the NameConstraints structure defined in RFC 3280
+ * and X.509. The ASN.1 notation for this structure is supplied in the
+ * documentation for
+ * {@link #TrustAnchor(X509Certificate, byte[])
+ * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
+ * <p>
+ * Note that the byte array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return a byte array containing the ASN.1 DER encoding of
+ * a NameConstraints extension used for checking name constraints,
+ * or {@code null} if not set.
+ */
+ public final byte [] getNameConstraints() {
+ return ncBytes == null ? null : ncBytes.clone();
+ }
+
+ /**
+ * Returns a formatted string describing the {@code TrustAnchor}.
+ *
+ * @return a formatted string describing the {@code TrustAnchor}
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[\n");
+ if (pubKey != null) {
+ sb.append(" Trusted CA Public Key: " + pubKey.toString() + "\n");
+ sb.append(" Trusted CA Issuer Name: "
+ + String.valueOf(caName) + "\n");
+ } else {
+ sb.append(" Trusted CA cert: " + trustedCert.toString() + "\n");
+ }
+ if (nc != null)
+ sb.append(" Name Constraints: " + nc.toString() + "\n");
+ return sb.toString();
+ }
+}
diff --git a/java/security/cert/X509CRL.java b/java/security/cert/X509CRL.java
new file mode 100644
index 0000000..a233b44
--- /dev/null
+++ b/java/security/cert/X509CRL.java
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.Principal;
+import java.security.Provider;
+import java.security.PublicKey;
+import javax.security.auth.x500.X500Principal;
+
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.Set;
+import java.util.Arrays;
+
+import sun.security.x509.X509CRLImpl;
+
+/**
+ * <p>
+ * Abstract class for an X.509 Certificate Revocation List (CRL).
+ * A CRL is a time-stamped list identifying revoked certificates.
+ * It is signed by a Certificate Authority (CA) and made freely
+ * available in a public repository.
+ *
+ * <p>Each revoked certificate is
+ * identified in a CRL by its certificate serial number. When a
+ * certificate-using system uses a certificate (e.g., for verifying a
+ * remote user's digital signature), that system not only checks the
+ * certificate signature and validity but also acquires a suitably-
+ * recent CRL and checks that the certificate serial number is not on
+ * that CRL. The meaning of "suitably-recent" may vary with local
+ * policy, but it usually means the most recently-issued CRL. A CA
+ * issues a new CRL on a regular periodic basis (e.g., hourly, daily, or
+ * weekly). Entries are added to CRLs as revocations occur, and an
+ * entry may be removed when the certificate expiration date is reached.
+ * <p>
+ * The X.509 v2 CRL format is described below in ASN.1:
+ * <pre>
+ * CertificateList ::= SEQUENCE {
+ * tbsCertList TBSCertList,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING }
+ * </pre>
+ * <p>
+ * More information can be found in
+ * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * Public Key Infrastructure Certificate and CRL Profile</a>.
+ * <p>
+ * The ASN.1 definition of {@code tbsCertList} is:
+ * <pre>
+ * TBSCertList ::= SEQUENCE {
+ * version Version OPTIONAL,
+ * -- if present, must be v2
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * thisUpdate ChoiceOfTime,
+ * nextUpdate ChoiceOfTime OPTIONAL,
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate ChoiceOfTime,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, must be v2
+ * } OPTIONAL,
+ * crlExtensions [0] EXPLICIT Extensions OPTIONAL
+ * -- if present, must be v2
+ * }
+ * </pre>
+ * <p>
+ * CRLs are instantiated using a certificate factory. The following is an
+ * example of how to instantiate an X.509 CRL:
+ * <pre>{@code
+ * try (InputStream inStream = new FileInputStream("fileName-of-crl")) {
+ * CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ * X509CRL crl = (X509CRL)cf.generateCRL(inStream);
+ * }
+ * }</pre>
+ *
+ * @author Hemma Prafullchandra
+ *
+ *
+ * @see CRL
+ * @see CertificateFactory
+ * @see X509Extension
+ */
+
+public abstract class X509CRL extends CRL implements X509Extension {
+
+ private transient X500Principal issuerPrincipal;
+
+ /**
+ * Constructor for X.509 CRLs.
+ */
+ protected X509CRL() {
+ super("X.509");
+ }
+
+ /**
+ * Compares this CRL for equality with the given
+ * object. If the {@code other} object is an
+ * {@code instanceof} {@code X509CRL}, then
+ * its encoded form is retrieved and compared with the
+ * encoded form of this CRL.
+ *
+ * @param other the object to test for equality with this CRL.
+ *
+ * @return true iff the encoded forms of the two CRLs
+ * match, false otherwise.
+ */
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof X509CRL)) {
+ return false;
+ }
+ try {
+ byte[] thisCRL = X509CRLImpl.getEncodedInternal(this);
+ byte[] otherCRL = X509CRLImpl.getEncodedInternal((X509CRL)other);
+
+ return Arrays.equals(thisCRL, otherCRL);
+ } catch (CRLException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a hashcode value for this CRL from its
+ * encoded form.
+ *
+ * @return the hashcode value.
+ */
+ public int hashCode() {
+ int retval = 0;
+ try {
+ byte[] crlData = X509CRLImpl.getEncodedInternal(this);
+ for (int i = 1; i < crlData.length; i++) {
+ retval += crlData[i] * i;
+ }
+ return retval;
+ } catch (CRLException e) {
+ return retval;
+ }
+ }
+
+ /**
+ * Returns the ASN.1 DER-encoded form of this CRL.
+ *
+ * @return the encoded form of this certificate
+ * @exception CRLException if an encoding error occurs.
+ */
+ public abstract byte[] getEncoded()
+ throws CRLException;
+
+ /**
+ * Verifies that this CRL was signed using the
+ * private key that corresponds to the given public key.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception NoSuchProviderException if there's no default provider.
+ * @exception SignatureException on signature errors.
+ * @exception CRLException on encoding errors.
+ */
+ public abstract void verify(PublicKey key)
+ throws CRLException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException;
+
+ /**
+ * Verifies that this CRL was signed using the
+ * private key that corresponds to the given public key.
+ * This method uses the signature verification engine
+ * supplied by the given provider.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ * @param sigProvider the name of the signature provider.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception NoSuchProviderException on incorrect provider.
+ * @exception SignatureException on signature errors.
+ * @exception CRLException on encoding errors.
+ */
+ public abstract void verify(PublicKey key, String sigProvider)
+ throws CRLException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException,
+ SignatureException;
+
+ /**
+ * Verifies that this CRL was signed using the
+ * private key that corresponds to the given public key.
+ * This method uses the signature verification engine
+ * supplied by the given provider. Note that the specified Provider object
+ * does not have to be registered in the provider list.
+ *
+ * This method was added to version 1.8 of the Java Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method is not {@code abstract}
+ * and it provides a default implementation.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ * @param sigProvider the signature provider.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception SignatureException on signature errors.
+ * @exception CRLException on encoding errors.
+ * @since 1.8
+ */
+ public void verify(PublicKey key, Provider sigProvider)
+ throws CRLException, NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ // BEGIN Android-changed
+ // TODO(31294527): was X509CRLImpl.verify(this, key, sigProvider);
+ // As the javadoc says, this "default implementation" was introduced as to avoid breaking
+ // providers that generate concrete subclasses of this class.
+ // The method X509Impl in the original definition calls this method, thus entering an
+ // infinite loop. This strange behaviour was checked to be not specific to libcore by
+ // running a test with vogar --mode=jvm .
+ throw new UnsupportedOperationException(
+ "X509CRL instance doesn't not support X509CRL#verify(PublicKey, Provider)");
+ // END Android-changed
+ }
+
+ /**
+ * Gets the {@code version} (version number) value from the CRL.
+ * The ASN.1 definition for this is:
+ * <pre>
+ * version Version OPTIONAL,
+ * -- if present, must be v2
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ * -- v3 does not apply to CRLs but appears for consistency
+ * -- with definition of Version for certs
+ * </pre>
+ *
+ * @return the version number, i.e. 1 or 2.
+ */
+ public abstract int getVersion();
+
+ /**
+ * <strong>Denigrated</strong>, replaced by {@linkplain
+ * #getIssuerX500Principal()}. This method returns the {@code issuer}
+ * as an implementation specific Principal object, which should not be
+ * relied upon by portable code.
+ *
+ * <p>
+ * Gets the {@code issuer} (issuer distinguished name) value from
+ * the CRL. The issuer name identifies the entity that signed (and
+ * issued) the CRL.
+ *
+ * <p>The issuer name field contains an
+ * X.500 distinguished name (DN).
+ * The ASN.1 definition for this is:
+ * <pre>
+ * issuer Name
+ *
+ * Name ::= CHOICE { RDNSequence }
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeValueAssertion
+ *
+ * AttributeValueAssertion ::= SEQUENCE {
+ * AttributeType,
+ * AttributeValue }
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY
+ * </pre>
+ * The {@code Name} describes a hierarchical name composed of
+ * attributes,
+ * such as country name, and corresponding values, such as US.
+ * The type of the {@code AttributeValue} component is determined by
+ * the {@code AttributeType}; in general it will be a
+ * {@code directoryString}. A {@code directoryString} is usually
+ * one of {@code PrintableString},
+ * {@code TeletexString} or {@code UniversalString}.
+ *
+ * @return a Principal whose name is the issuer distinguished name.
+ */
+ public abstract Principal getIssuerDN();
+
+ /**
+ * Returns the issuer (issuer distinguished name) value from the
+ * CRL as an {@code X500Principal}.
+ * <p>
+ * It is recommended that subclasses override this method.
+ *
+ * @return an {@code X500Principal} representing the issuer
+ * distinguished name
+ * @since 1.4
+ */
+ public X500Principal getIssuerX500Principal() {
+ if (issuerPrincipal == null) {
+ issuerPrincipal = X509CRLImpl.getIssuerX500Principal(this);
+ }
+ return issuerPrincipal;
+ }
+
+ /**
+ * Gets the {@code thisUpdate} date from the CRL.
+ * The ASN.1 definition for this is:
+ * <pre>
+ * thisUpdate ChoiceOfTime
+ * ChoiceOfTime ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ *
+ * @return the {@code thisUpdate} date from the CRL.
+ */
+ public abstract Date getThisUpdate();
+
+ /**
+ * Gets the {@code nextUpdate} date from the CRL.
+ *
+ * @return the {@code nextUpdate} date from the CRL, or null if
+ * not present.
+ */
+ public abstract Date getNextUpdate();
+
+ /**
+ * Gets the CRL entry, if any, with the given certificate serialNumber.
+ *
+ * @param serialNumber the serial number of the certificate for which a CRL entry
+ * is to be looked up
+ * @return the entry with the given serial number, or null if no such entry
+ * exists in this CRL.
+ * @see X509CRLEntry
+ */
+ public abstract X509CRLEntry
+ getRevokedCertificate(BigInteger serialNumber);
+
+ /**
+ * Get the CRL entry, if any, for the given certificate.
+ *
+ * <p>This method can be used to lookup CRL entries in indirect CRLs,
+ * that means CRLs that contain entries from issuers other than the CRL
+ * issuer. The default implementation will only return entries for
+ * certificates issued by the CRL issuer. Subclasses that wish to
+ * support indirect CRLs should override this method.
+ *
+ * @param certificate the certificate for which a CRL entry is to be looked
+ * up
+ * @return the entry for the given certificate, or null if no such entry
+ * exists in this CRL.
+ * @exception NullPointerException if certificate is null
+ *
+ * @since 1.5
+ */
+ public X509CRLEntry getRevokedCertificate(X509Certificate certificate) {
+ X500Principal certIssuer = certificate.getIssuerX500Principal();
+ X500Principal crlIssuer = getIssuerX500Principal();
+ if (certIssuer.equals(crlIssuer) == false) {
+ return null;
+ }
+ return getRevokedCertificate(certificate.getSerialNumber());
+ }
+
+ /**
+ * Gets all the entries from this CRL.
+ * This returns a Set of X509CRLEntry objects.
+ *
+ * @return all the entries or null if there are none present.
+ * @see X509CRLEntry
+ */
+ public abstract Set<? extends X509CRLEntry> getRevokedCertificates();
+
+ /**
+ * Gets the DER-encoded CRL information, the
+ * {@code tbsCertList} from this CRL.
+ * This can be used to verify the signature independently.
+ *
+ * @return the DER-encoded CRL information.
+ * @exception CRLException if an encoding error occurs.
+ */
+ public abstract byte[] getTBSCertList() throws CRLException;
+
+ /**
+ * Gets the {@code signature} value (the raw signature bits) from
+ * the CRL.
+ * The ASN.1 definition for this is:
+ * <pre>
+ * signature BIT STRING
+ * </pre>
+ *
+ * @return the signature.
+ */
+ public abstract byte[] getSignature();
+
+ /**
+ * Gets the signature algorithm name for the CRL
+ * signature algorithm. An example is the string "SHA256withRSA".
+ * The ASN.1 definition for this is:
+ * <pre>
+ * signatureAlgorithm AlgorithmIdentifier
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * -- contains a value of the type
+ * -- registered for use with the
+ * -- algorithm object identifier value
+ * </pre>
+ *
+ * <p>The algorithm name is determined from the {@code algorithm}
+ * OID string.
+ *
+ * @return the signature algorithm name.
+ */
+ public abstract String getSigAlgName();
+
+ /**
+ * Gets the signature algorithm OID string from the CRL.
+ * An OID is represented by a set of nonnegative whole numbers separated
+ * by periods.
+ * For example, the string "1.2.840.10040.4.3" identifies the SHA-1
+ * with DSA signature algorithm defined in
+ * <a href="http://www.ietf.org/rfc/rfc3279.txt">RFC 3279: Algorithms and
+ * Identifiers for the Internet X.509 Public Key Infrastructure Certificate
+ * and CRL Profile</a>.
+ *
+ * <p>See {@link #getSigAlgName() getSigAlgName} for
+ * relevant ASN.1 definitions.
+ *
+ * @return the signature algorithm OID string.
+ */
+ public abstract String getSigAlgOID();
+
+ /**
+ * Gets the DER-encoded signature algorithm parameters from this
+ * CRL's signature algorithm. In most cases, the signature
+ * algorithm parameters are null; the parameters are usually
+ * supplied with the public key.
+ * If access to individual parameter values is needed then use
+ * {@link java.security.AlgorithmParameters AlgorithmParameters}
+ * and instantiate with the name returned by
+ * {@link #getSigAlgName() getSigAlgName}.
+ *
+ * <p>See {@link #getSigAlgName() getSigAlgName} for
+ * relevant ASN.1 definitions.
+ *
+ * @return the DER-encoded signature algorithm parameters, or
+ * null if no parameters are present.
+ */
+ public abstract byte[] getSigAlgParams();
+}
diff --git a/java/security/cert/X509CRLEntry.java b/java/security/cert/X509CRLEntry.java
new file mode 100644
index 0000000..268fa81
--- /dev/null
+++ b/java/security/cert/X509CRLEntry.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.math.BigInteger;
+import java.util.Date;
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.x509.X509CRLEntryImpl;
+
+/**
+ * <p>Abstract class for a revoked certificate in a CRL (Certificate
+ * Revocation List).
+ *
+ * The ASN.1 definition for <em>revokedCertificates</em> is:
+ * <pre>
+ * revokedCertificates SEQUENCE OF SEQUENCE {
+ * userCertificate CertificateSerialNumber,
+ * revocationDate ChoiceOfTime,
+ * crlEntryExtensions Extensions OPTIONAL
+ * -- if present, must be v2
+ * } OPTIONAL
+ *
+ * CertificateSerialNumber ::= INTEGER
+ *
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING
+ * -- contains a DER encoding of a value
+ * -- of the type registered for use with
+ * -- the extnId object identifier value
+ * }
+ * </pre>
+ *
+ * @see X509CRL
+ * @see X509Extension
+ *
+ * @author Hemma Prafullchandra
+ */
+
+public abstract class X509CRLEntry implements X509Extension {
+
+ /**
+ * Compares this CRL entry for equality with the given
+ * object. If the {@code other} object is an
+ * {@code instanceof} {@code X509CRLEntry}, then
+ * its encoded form (the inner SEQUENCE) is retrieved and compared
+ * with the encoded form of this CRL entry.
+ *
+ * @param other the object to test for equality with this CRL entry.
+ * @return true iff the encoded forms of the two CRL entries
+ * match, false otherwise.
+ */
+ public boolean equals(Object other) {
+ if (this == other)
+ return true;
+ if (!(other instanceof X509CRLEntry))
+ return false;
+ try {
+ byte[] thisCRLEntry = this.getEncoded();
+ byte[] otherCRLEntry = ((X509CRLEntry)other).getEncoded();
+
+ if (thisCRLEntry.length != otherCRLEntry.length)
+ return false;
+ for (int i = 0; i < thisCRLEntry.length; i++)
+ if (thisCRLEntry[i] != otherCRLEntry[i])
+ return false;
+ } catch (CRLException ce) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hashcode value for this CRL entry from its
+ * encoded form.
+ *
+ * @return the hashcode value.
+ */
+ public int hashCode() {
+ int retval = 0;
+ try {
+ byte[] entryData = this.getEncoded();
+ for (int i = 1; i < entryData.length; i++)
+ retval += entryData[i] * i;
+
+ } catch (CRLException ce) {
+ return(retval);
+ }
+ return(retval);
+ }
+
+ /**
+ * Returns the ASN.1 DER-encoded form of this CRL Entry,
+ * that is the inner SEQUENCE.
+ *
+ * @return the encoded form of this certificate
+ * @exception CRLException if an encoding error occurs.
+ */
+ public abstract byte[] getEncoded() throws CRLException;
+
+ /**
+ * Gets the serial number from this X509CRLEntry,
+ * the <em>userCertificate</em>.
+ *
+ * @return the serial number.
+ */
+ public abstract BigInteger getSerialNumber();
+
+ /**
+ * Get the issuer of the X509Certificate described by this entry. If
+ * the certificate issuer is also the CRL issuer, this method returns
+ * null.
+ *
+ * <p>This method is used with indirect CRLs. The default implementation
+ * always returns null. Subclasses that wish to support indirect CRLs
+ * should override it.
+ *
+ * @return the issuer of the X509Certificate described by this entry
+ * or null if it is issued by the CRL issuer.
+ *
+ * @since 1.5
+ */
+ public X500Principal getCertificateIssuer() {
+ return null;
+ }
+
+ /**
+ * Gets the revocation date from this X509CRLEntry,
+ * the <em>revocationDate</em>.
+ *
+ * @return the revocation date.
+ */
+ public abstract Date getRevocationDate();
+
+ /**
+ * Returns true if this CRL entry has extensions.
+ *
+ * @return true if this entry has extensions, false otherwise.
+ */
+ public abstract boolean hasExtensions();
+
+ /**
+ * Returns a string representation of this CRL entry.
+ *
+ * @return a string representation of this CRL entry.
+ */
+ public abstract String toString();
+
+ /**
+ * Returns the reason the certificate has been revoked, as specified
+ * in the Reason Code extension of this CRL entry.
+ *
+ * @return the reason the certificate has been revoked, or
+ * {@code null} if this CRL entry does not have
+ * a Reason Code extension
+ * @since 1.7
+ */
+ public CRLReason getRevocationReason() {
+ if (!hasExtensions()) {
+ return null;
+ }
+ return X509CRLEntryImpl.getRevocationReason(this);
+ }
+}
diff --git a/java/security/cert/X509CRLSelector.java b/java/security/cert/X509CRLSelector.java
new file mode 100644
index 0000000..face5ff
--- /dev/null
+++ b/java/security/cert/X509CRLSelector.java
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.*;
+
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.util.Debug;
+import sun.security.util.DerInputStream;
+import sun.security.x509.CRLNumberExtension;
+import sun.security.x509.X500Name;
+
+/**
+ * A {@code CRLSelector} that selects {@code X509CRLs} that
+ * match all specified criteria. This class is particularly useful when
+ * selecting CRLs from a {@code CertStore} to check revocation status
+ * of a particular certificate.
+ * <p>
+ * When first constructed, an {@code X509CRLSelector} has no criteria
+ * enabled and each of the {@code get} methods return a default
+ * value ({@code null}). Therefore, the {@link #match match} method
+ * would return {@code true} for any {@code X509CRL}. Typically,
+ * several criteria are enabled (by calling {@link #setIssuers setIssuers}
+ * or {@link #setDateAndTime setDateAndTime}, for instance) and then the
+ * {@code X509CRLSelector} is passed to
+ * {@link CertStore#getCRLs CertStore.getCRLs} or some similar
+ * method.
+ * <p>
+ * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>
+ * for definitions of the X.509 CRL fields and extensions mentioned below.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CRLSelector
+ * @see X509CRL
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ */
+public class X509CRLSelector implements CRLSelector {
+
+ static {
+ CertPathHelperImpl.initialize();
+ }
+
+ private static final Debug debug = Debug.getInstance("certpath");
+ private HashSet<Object> issuerNames;
+ private HashSet<X500Principal> issuerX500Principals;
+ private BigInteger minCRL;
+ private BigInteger maxCRL;
+ private Date dateAndTime;
+ private X509Certificate certChecking;
+ private long skew = 0;
+
+ /**
+ * Creates an {@code X509CRLSelector}. Initially, no criteria are set
+ * so any {@code X509CRL} will match.
+ */
+ public X509CRLSelector() {}
+
+ /**
+ * Sets the issuerNames criterion. The issuer distinguished name in the
+ * {@code X509CRL} must match at least one of the specified
+ * distinguished names. If {@code null}, any issuer distinguished name
+ * will do.
+ * <p>
+ * This method allows the caller to specify, with a single method call,
+ * the complete set of issuer names which {@code X509CRLs} may contain.
+ * The specified value replaces the previous value for the issuerNames
+ * criterion.
+ * <p>
+ * The {@code names} parameter (if not {@code null}) is a
+ * {@code Collection} of {@code X500Principal}s.
+ * <p>
+ * Note that the {@code names} parameter can contain duplicate
+ * distinguished names, but they may be removed from the
+ * {@code Collection} of names returned by the
+ * {@link #getIssuers getIssuers} method.
+ * <p>
+ * Note that a copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @param issuers a {@code Collection} of X500Principals
+ * (or {@code null})
+ * @see #getIssuers
+ * @since 1.5
+ */
+ public void setIssuers(Collection<X500Principal> issuers) {
+ if ((issuers == null) || issuers.isEmpty()) {
+ issuerNames = null;
+ issuerX500Principals = null;
+ } else {
+ // clone
+ issuerX500Principals = new HashSet<X500Principal>(issuers);
+ issuerNames = new HashSet<Object>();
+ for (X500Principal p : issuerX500Principals) {
+ issuerNames.add(p.getEncoded());
+ }
+ }
+ }
+
+ /**
+ * <strong>Note:</strong> use {@linkplain #setIssuers(Collection)} instead
+ * or only specify the byte array form of distinguished names when using
+ * this method. See {@link #addIssuerName(String)} for more information.
+ * <p>
+ * Sets the issuerNames criterion. The issuer distinguished name in the
+ * {@code X509CRL} must match at least one of the specified
+ * distinguished names. If {@code null}, any issuer distinguished name
+ * will do.
+ * <p>
+ * This method allows the caller to specify, with a single method call,
+ * the complete set of issuer names which {@code X509CRLs} may contain.
+ * The specified value replaces the previous value for the issuerNames
+ * criterion.
+ * <p>
+ * The {@code names} parameter (if not {@code null}) is a
+ * {@code Collection} of names. Each name is a {@code String}
+ * or a byte array representing a distinguished name (in
+ * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a> or
+ * ASN.1 DER encoded form, respectively). If {@code null} is supplied
+ * as the value for this argument, no issuerNames check will be performed.
+ * <p>
+ * Note that the {@code names} parameter can contain duplicate
+ * distinguished names, but they may be removed from the
+ * {@code Collection} of names returned by the
+ * {@link #getIssuerNames getIssuerNames} method.
+ * <p>
+ * If a name is specified as a byte array, it should contain a single DER
+ * encoded distinguished name, as defined in X.501. The ASN.1 notation for
+ * this structure is as follows.
+ * <pre>{@code
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::=
+ * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * ....
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * }</pre>
+ * <p>
+ * Note that a deep copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @param names a {@code Collection} of names (or {@code null})
+ * @throws IOException if a parsing error occurs
+ * @see #getIssuerNames
+ */
+ public void setIssuerNames(Collection<?> names) throws IOException {
+ if (names == null || names.size() == 0) {
+ issuerNames = null;
+ issuerX500Principals = null;
+ } else {
+ HashSet<Object> tempNames = cloneAndCheckIssuerNames(names);
+ // Ensure that we either set both of these or neither
+ issuerX500Principals = parseIssuerNames(tempNames);
+ issuerNames = tempNames;
+ }
+ }
+
+ /**
+ * Adds a name to the issuerNames criterion. The issuer distinguished
+ * name in the {@code X509CRL} must match at least one of the specified
+ * distinguished names.
+ * <p>
+ * This method allows the caller to add a name to the set of issuer names
+ * which {@code X509CRLs} may contain. The specified name is added to
+ * any previous value for the issuerNames criterion.
+ * If the specified name is a duplicate, it may be ignored.
+ *
+ * @param issuer the issuer as X500Principal
+ * @since 1.5
+ */
+ public void addIssuer(X500Principal issuer) {
+ addIssuerNameInternal(issuer.getEncoded(), issuer);
+ }
+
+ /**
+ * <strong>Denigrated</strong>, use
+ * {@linkplain #addIssuer(X500Principal)} or
+ * {@linkplain #addIssuerName(byte[])} instead. This method should not be
+ * relied on as it can fail to match some CRLs because of a loss of
+ * encoding information in the RFC 2253 String form of some distinguished
+ * names.
+ * <p>
+ * Adds a name to the issuerNames criterion. The issuer distinguished
+ * name in the {@code X509CRL} must match at least one of the specified
+ * distinguished names.
+ * <p>
+ * This method allows the caller to add a name to the set of issuer names
+ * which {@code X509CRLs} may contain. The specified name is added to
+ * any previous value for the issuerNames criterion.
+ * If the specified name is a duplicate, it may be ignored.
+ *
+ * @param name the name in RFC 2253 form
+ * @throws IOException if a parsing error occurs
+ */
+ public void addIssuerName(String name) throws IOException {
+ addIssuerNameInternal(name, new X500Name(name).asX500Principal());
+ }
+
+ /**
+ * Adds a name to the issuerNames criterion. The issuer distinguished
+ * name in the {@code X509CRL} must match at least one of the specified
+ * distinguished names.
+ * <p>
+ * This method allows the caller to add a name to the set of issuer names
+ * which {@code X509CRLs} may contain. The specified name is added to
+ * any previous value for the issuerNames criterion. If the specified name
+ * is a duplicate, it may be ignored.
+ * If a name is specified as a byte array, it should contain a single DER
+ * encoded distinguished name, as defined in X.501. The ASN.1 notation for
+ * this structure is as follows.
+ * <p>
+ * The name is provided as a byte array. This byte array should contain
+ * a single DER encoded distinguished name, as defined in X.501. The ASN.1
+ * notation for this structure appears in the documentation for
+ * {@link #setIssuerNames setIssuerNames(Collection names)}.
+ * <p>
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param name a byte array containing the name in ASN.1 DER encoded form
+ * @throws IOException if a parsing error occurs
+ */
+ public void addIssuerName(byte[] name) throws IOException {
+ // clone because byte arrays are modifiable
+ addIssuerNameInternal(name.clone(), new X500Name(name).asX500Principal());
+ }
+
+ /**
+ * A private method that adds a name (String or byte array) to the
+ * issuerNames criterion. The issuer distinguished
+ * name in the {@code X509CRL} must match at least one of the specified
+ * distinguished names.
+ *
+ * @param name the name in string or byte array form
+ * @param principal the name in X500Principal form
+ * @throws IOException if a parsing error occurs
+ */
+ private void addIssuerNameInternal(Object name, X500Principal principal) {
+ if (issuerNames == null) {
+ issuerNames = new HashSet<Object>();
+ }
+ if (issuerX500Principals == null) {
+ issuerX500Principals = new HashSet<X500Principal>();
+ }
+ issuerNames.add(name);
+ issuerX500Principals.add(principal);
+ }
+
+ /**
+ * Clone and check an argument of the form passed to
+ * setIssuerNames. Throw an IOException if the argument is malformed.
+ *
+ * @param names a {@code Collection} of names. Each entry is a
+ * String or a byte array (the name, in string or ASN.1
+ * DER encoded form, respectively). {@code null} is
+ * not an acceptable value.
+ * @return a deep copy of the specified {@code Collection}
+ * @throws IOException if a parsing error occurs
+ */
+ private static HashSet<Object> cloneAndCheckIssuerNames(Collection<?> names)
+ throws IOException
+ {
+ HashSet<Object> namesCopy = new HashSet<Object>();
+ Iterator<?> i = names.iterator();
+ while (i.hasNext()) {
+ Object nameObject = i.next();
+ if (!(nameObject instanceof byte []) &&
+ !(nameObject instanceof String))
+ throw new IOException("name not byte array or String");
+ if (nameObject instanceof byte [])
+ namesCopy.add(((byte []) nameObject).clone());
+ else
+ namesCopy.add(nameObject);
+ }
+ return(namesCopy);
+ }
+
+ /**
+ * Clone an argument of the form passed to setIssuerNames.
+ * Throw a RuntimeException if the argument is malformed.
+ * <p>
+ * This method wraps cloneAndCheckIssuerNames, changing any IOException
+ * into a RuntimeException. This method should be used when the object being
+ * cloned has already been checked, so there should never be any exceptions.
+ *
+ * @param names a {@code Collection} of names. Each entry is a
+ * String or a byte array (the name, in string or ASN.1
+ * DER encoded form, respectively). {@code null} is
+ * not an acceptable value.
+ * @return a deep copy of the specified {@code Collection}
+ * @throws RuntimeException if a parsing error occurs
+ */
+ private static HashSet<Object> cloneIssuerNames(Collection<Object> names) {
+ try {
+ return cloneAndCheckIssuerNames(names);
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ /**
+ * Parse an argument of the form passed to setIssuerNames,
+ * returning a Collection of issuerX500Principals.
+ * Throw an IOException if the argument is malformed.
+ *
+ * @param names a {@code Collection} of names. Each entry is a
+ * String or a byte array (the name, in string or ASN.1
+ * DER encoded form, respectively). <Code>Null</Code> is
+ * not an acceptable value.
+ * @return a HashSet of issuerX500Principals
+ * @throws IOException if a parsing error occurs
+ */
+ private static HashSet<X500Principal> parseIssuerNames(Collection<Object> names)
+ throws IOException {
+ HashSet<X500Principal> x500Principals = new HashSet<X500Principal>();
+ for (Iterator<Object> t = names.iterator(); t.hasNext(); ) {
+ Object nameObject = t.next();
+ if (nameObject instanceof String) {
+ x500Principals.add(new X500Name((String)nameObject).asX500Principal());
+ } else {
+ try {
+ x500Principals.add(new X500Principal((byte[])nameObject));
+ } catch (IllegalArgumentException e) {
+ throw (IOException)new IOException("Invalid name").initCause(e);
+ }
+ }
+ }
+ return x500Principals;
+ }
+
+ /**
+ * Sets the minCRLNumber criterion. The {@code X509CRL} must have a
+ * CRL number extension whose value is greater than or equal to the
+ * specified value. If {@code null}, no minCRLNumber check will be
+ * done.
+ *
+ * @param minCRL the minimum CRL number accepted (or {@code null})
+ */
+ public void setMinCRLNumber(BigInteger minCRL) {
+ this.minCRL = minCRL;
+ }
+
+ /**
+ * Sets the maxCRLNumber criterion. The {@code X509CRL} must have a
+ * CRL number extension whose value is less than or equal to the
+ * specified value. If {@code null}, no maxCRLNumber check will be
+ * done.
+ *
+ * @param maxCRL the maximum CRL number accepted (or {@code null})
+ */
+ public void setMaxCRLNumber(BigInteger maxCRL) {
+ this.maxCRL = maxCRL;
+ }
+
+ /**
+ * Sets the dateAndTime criterion. The specified date must be
+ * equal to or later than the value of the thisUpdate component
+ * of the {@code X509CRL} and earlier than the value of the
+ * nextUpdate component. There is no match if the {@code X509CRL}
+ * does not contain a nextUpdate component.
+ * If {@code null}, no dateAndTime check will be done.
+ * <p>
+ * Note that the {@code Date} supplied here is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param dateAndTime the {@code Date} to match against
+ * (or {@code null})
+ * @see #getDateAndTime
+ */
+ public void setDateAndTime(Date dateAndTime) {
+ if (dateAndTime == null)
+ this.dateAndTime = null;
+ else
+ this.dateAndTime = new Date(dateAndTime.getTime());
+ this.skew = 0;
+ }
+
+ /**
+ * Sets the dateAndTime criterion and allows for the specified clock skew
+ * (in milliseconds) when checking against the validity period of the CRL.
+ */
+ void setDateAndTime(Date dateAndTime, long skew) {
+ this.dateAndTime =
+ (dateAndTime == null ? null : new Date(dateAndTime.getTime()));
+ this.skew = skew;
+ }
+
+ /**
+ * Sets the certificate being checked. This is not a criterion. Rather,
+ * it is optional information that may help a {@code CertStore}
+ * find CRLs that would be relevant when checking revocation for the
+ * specified certificate. If {@code null} is specified, then no
+ * such optional information is provided.
+ *
+ * @param cert the {@code X509Certificate} being checked
+ * (or {@code null})
+ * @see #getCertificateChecking
+ */
+ public void setCertificateChecking(X509Certificate cert) {
+ certChecking = cert;
+ }
+
+ /**
+ * Returns the issuerNames criterion. The issuer distinguished
+ * name in the {@code X509CRL} must match at least one of the specified
+ * distinguished names. If the value returned is {@code null}, any
+ * issuer distinguished name will do.
+ * <p>
+ * If the value returned is not {@code null}, it is a
+ * unmodifiable {@code Collection} of {@code X500Principal}s.
+ *
+ * @return an unmodifiable {@code Collection} of names
+ * (or {@code null})
+ * @see #setIssuers
+ * @since 1.5
+ */
+ public Collection<X500Principal> getIssuers() {
+ if (issuerX500Principals == null) {
+ return null;
+ }
+ return Collections.unmodifiableCollection(issuerX500Principals);
+ }
+
+ /**
+ * Returns a copy of the issuerNames criterion. The issuer distinguished
+ * name in the {@code X509CRL} must match at least one of the specified
+ * distinguished names. If the value returned is {@code null}, any
+ * issuer distinguished name will do.
+ * <p>
+ * If the value returned is not {@code null}, it is a
+ * {@code Collection} of names. Each name is a {@code String}
+ * or a byte array representing a distinguished name (in RFC 2253 or
+ * ASN.1 DER encoded form, respectively). Note that the
+ * {@code Collection} returned may contain duplicate names.
+ * <p>
+ * If a name is specified as a byte array, it should contain a single DER
+ * encoded distinguished name, as defined in X.501. The ASN.1 notation for
+ * this structure is given in the documentation for
+ * {@link #setIssuerNames setIssuerNames(Collection names)}.
+ * <p>
+ * Note that a deep copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @return a {@code Collection} of names (or {@code null})
+ * @see #setIssuerNames
+ */
+ public Collection<Object> getIssuerNames() {
+ if (issuerNames == null) {
+ return null;
+ }
+ return cloneIssuerNames(issuerNames);
+ }
+
+ /**
+ * Returns the minCRLNumber criterion. The {@code X509CRL} must have a
+ * CRL number extension whose value is greater than or equal to the
+ * specified value. If {@code null}, no minCRLNumber check will be done.
+ *
+ * @return the minimum CRL number accepted (or {@code null})
+ */
+ public BigInteger getMinCRL() {
+ return minCRL;
+ }
+
+ /**
+ * Returns the maxCRLNumber criterion. The {@code X509CRL} must have a
+ * CRL number extension whose value is less than or equal to the
+ * specified value. If {@code null}, no maxCRLNumber check will be
+ * done.
+ *
+ * @return the maximum CRL number accepted (or {@code null})
+ */
+ public BigInteger getMaxCRL() {
+ return maxCRL;
+ }
+
+ /**
+ * Returns the dateAndTime criterion. The specified date must be
+ * equal to or later than the value of the thisUpdate component
+ * of the {@code X509CRL} and earlier than the value of the
+ * nextUpdate component. There is no match if the
+ * {@code X509CRL} does not contain a nextUpdate component.
+ * If {@code null}, no dateAndTime check will be done.
+ * <p>
+ * Note that the {@code Date} returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the {@code Date} to match against (or {@code null})
+ * @see #setDateAndTime
+ */
+ public Date getDateAndTime() {
+ if (dateAndTime == null)
+ return null;
+ return (Date) dateAndTime.clone();
+ }
+
+ /**
+ * Returns the certificate being checked. This is not a criterion. Rather,
+ * it is optional information that may help a {@code CertStore}
+ * find CRLs that would be relevant when checking revocation for the
+ * specified certificate. If the value returned is {@code null}, then
+ * no such optional information is provided.
+ *
+ * @return the certificate being checked (or {@code null})
+ * @see #setCertificateChecking
+ */
+ public X509Certificate getCertificateChecking() {
+ return certChecking;
+ }
+
+ /**
+ * Returns a printable representation of the {@code X509CRLSelector}.
+ *
+ * @return a {@code String} describing the contents of the
+ * {@code X509CRLSelector}.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("X509CRLSelector: [\n");
+ if (issuerNames != null) {
+ sb.append(" IssuerNames:\n");
+ Iterator<Object> i = issuerNames.iterator();
+ while (i.hasNext())
+ sb.append(" " + i.next() + "\n");
+ }
+ if (minCRL != null)
+ sb.append(" minCRLNumber: " + minCRL + "\n");
+ if (maxCRL != null)
+ sb.append(" maxCRLNumber: " + maxCRL + "\n");
+ if (dateAndTime != null)
+ sb.append(" dateAndTime: " + dateAndTime + "\n");
+ if (certChecking != null)
+ sb.append(" Certificate being checked: " + certChecking + "\n");
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /**
+ * Decides whether a {@code CRL} should be selected.
+ *
+ * @param crl the {@code CRL} to be checked
+ * @return {@code true} if the {@code CRL} should be selected,
+ * {@code false} otherwise
+ */
+ public boolean match(CRL crl) {
+ if (!(crl instanceof X509CRL)) {
+ return false;
+ }
+ X509CRL xcrl = (X509CRL)crl;
+
+ /* match on issuer name */
+ if (issuerNames != null) {
+ X500Principal issuer = xcrl.getIssuerX500Principal();
+ Iterator<X500Principal> i = issuerX500Principals.iterator();
+ boolean found = false;
+ while (!found && i.hasNext()) {
+ if (i.next().equals(issuer)) {
+ found = true;
+ }
+ }
+ if (!found) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: issuer DNs "
+ + "don't match");
+ }
+ return false;
+ }
+ }
+
+ if ((minCRL != null) || (maxCRL != null)) {
+ /* Get CRL number extension from CRL */
+ byte[] crlNumExtVal = xcrl.getExtensionValue("2.5.29.20");
+ if (crlNumExtVal == null) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: no CRLNumber");
+ }
+ }
+ BigInteger crlNum;
+ try {
+ DerInputStream in = new DerInputStream(crlNumExtVal);
+ byte[] encoded = in.getOctetString();
+ CRLNumberExtension crlNumExt =
+ new CRLNumberExtension(Boolean.FALSE, encoded);
+ crlNum = crlNumExt.get(CRLNumberExtension.NUMBER);
+ } catch (IOException ex) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: exception in "
+ + "decoding CRL number");
+ }
+ return false;
+ }
+
+ /* match on minCRLNumber */
+ if (minCRL != null) {
+ if (crlNum.compareTo(minCRL) < 0) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: CRLNumber too small");
+ }
+ return false;
+ }
+ }
+
+ /* match on maxCRLNumber */
+ if (maxCRL != null) {
+ if (crlNum.compareTo(maxCRL) > 0) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: CRLNumber too large");
+ }
+ return false;
+ }
+ }
+ }
+
+
+ /* match on dateAndTime */
+ if (dateAndTime != null) {
+ Date crlThisUpdate = xcrl.getThisUpdate();
+ Date nextUpdate = xcrl.getNextUpdate();
+ if (nextUpdate == null) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: nextUpdate null");
+ }
+ return false;
+ }
+ Date nowPlusSkew = dateAndTime;
+ Date nowMinusSkew = dateAndTime;
+ if (skew > 0) {
+ nowPlusSkew = new Date(dateAndTime.getTime() + skew);
+ nowMinusSkew = new Date(dateAndTime.getTime() - skew);
+ }
+
+ // Check that the test date is within the validity interval:
+ // [ thisUpdate - MAX_CLOCK_SKEW,
+ // nextUpdate + MAX_CLOCK_SKEW ]
+ if (nowMinusSkew.after(nextUpdate)
+ || nowPlusSkew.before(crlThisUpdate)) {
+ if (debug != null) {
+ debug.println("X509CRLSelector.match: update out-of-range");
+ }
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return the copy
+ */
+ public Object clone() {
+ try {
+ X509CRLSelector copy = (X509CRLSelector)super.clone();
+ if (issuerNames != null) {
+ copy.issuerNames =
+ new HashSet<Object>(issuerNames);
+ copy.issuerX500Principals =
+ new HashSet<X500Principal>(issuerX500Principals);
+ }
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+}
diff --git a/java/security/cert/X509CertSelector.java b/java/security/cert/X509CertSelector.java
new file mode 100644
index 0000000..d4952da
--- /dev/null
+++ b/java/security/cert/X509CertSelector.java
@@ -0,0 +1,2624 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.util.*;
+import javax.security.auth.x500.X500Principal;
+
+import sun.misc.HexDumpEncoder;
+import sun.security.util.Debug;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerValue;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.*;
+
+/**
+ * A {@code CertSelector} that selects {@code X509Certificates} that
+ * match all specified criteria. This class is particularly useful when
+ * selecting certificates from a {@code CertStore} to build a
+ * PKIX-compliant certification path.
+ * <p>
+ * When first constructed, an {@code X509CertSelector} has no criteria
+ * enabled and each of the {@code get} methods return a default value
+ * ({@code null}, or {@code -1} for the {@link #getBasicConstraints
+ * getBasicConstraints} method). Therefore, the {@link #match match}
+ * method would return {@code true} for any {@code X509Certificate}.
+ * Typically, several criteria are enabled (by calling
+ * {@link #setIssuer setIssuer} or
+ * {@link #setKeyUsage setKeyUsage}, for instance) and then the
+ * {@code X509CertSelector} is passed to
+ * {@link CertStore#getCertificates CertStore.getCertificates} or some similar
+ * method.
+ * <p>
+ * Several criteria can be enabled (by calling {@link #setIssuer setIssuer}
+ * and {@link #setSerialNumber setSerialNumber},
+ * for example) such that the {@code match} method
+ * usually uniquely matches a single {@code X509Certificate}. We say
+ * usually, since it is possible for two issuing CAs to have the same
+ * distinguished name and each issue a certificate with the same serial
+ * number. Other unique combinations include the issuer, subject,
+ * subjectKeyIdentifier and/or the subjectPublicKey criteria.
+ * <p>
+ * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for
+ * definitions of the X.509 certificate extensions mentioned below.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @see CertSelector
+ * @see X509Certificate
+ *
+ * @since 1.4
+ * @author Steve Hanna
+ */
+public class X509CertSelector implements CertSelector {
+
+ private static final Debug debug = Debug.getInstance("certpath");
+
+ private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
+ ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0});
+
+ static {
+ CertPathHelperImpl.initialize();
+ }
+
+ private BigInteger serialNumber;
+ private X500Principal issuer;
+ private X500Principal subject;
+ private byte[] subjectKeyID;
+ private byte[] authorityKeyID;
+ private Date certificateValid;
+ private Date privateKeyValid;
+ private ObjectIdentifier subjectPublicKeyAlgID;
+ private PublicKey subjectPublicKey;
+ private byte[] subjectPublicKeyBytes;
+ private boolean[] keyUsage;
+ private Set<String> keyPurposeSet;
+ private Set<ObjectIdentifier> keyPurposeOIDSet;
+ private Set<List<?>> subjectAlternativeNames;
+ private Set<GeneralNameInterface> subjectAlternativeGeneralNames;
+ private CertificatePolicySet policy;
+ private Set<String> policySet;
+ private Set<List<?>> pathToNames;
+ private Set<GeneralNameInterface> pathToGeneralNames;
+ private NameConstraintsExtension nc;
+ private byte[] ncBytes;
+ private int basicConstraints = -1;
+ private X509Certificate x509Cert;
+ private boolean matchAllSubjectAltNames = true;
+
+ private static final Boolean FALSE = Boolean.FALSE;
+
+ private static final int PRIVATE_KEY_USAGE_ID = 0;
+ private static final int SUBJECT_ALT_NAME_ID = 1;
+ private static final int NAME_CONSTRAINTS_ID = 2;
+ private static final int CERT_POLICIES_ID = 3;
+ private static final int EXTENDED_KEY_USAGE_ID = 4;
+ private static final int NUM_OF_EXTENSIONS = 5;
+ private static final String[] EXTENSION_OIDS = new String[NUM_OF_EXTENSIONS];
+
+ static {
+ EXTENSION_OIDS[PRIVATE_KEY_USAGE_ID] = "2.5.29.16";
+ EXTENSION_OIDS[SUBJECT_ALT_NAME_ID] = "2.5.29.17";
+ EXTENSION_OIDS[NAME_CONSTRAINTS_ID] = "2.5.29.30";
+ EXTENSION_OIDS[CERT_POLICIES_ID] = "2.5.29.32";
+ EXTENSION_OIDS[EXTENDED_KEY_USAGE_ID] = "2.5.29.37";
+ };
+
+ /* Constants representing the GeneralName types */
+ static final int NAME_ANY = 0;
+ static final int NAME_RFC822 = 1;
+ static final int NAME_DNS = 2;
+ static final int NAME_X400 = 3;
+ static final int NAME_DIRECTORY = 4;
+ static final int NAME_EDI = 5;
+ static final int NAME_URI = 6;
+ static final int NAME_IP = 7;
+ static final int NAME_OID = 8;
+
+ /**
+ * Creates an {@code X509CertSelector}. Initially, no criteria are set
+ * so any {@code X509Certificate} will match.
+ */
+ public X509CertSelector() {
+ // empty
+ }
+
+ /**
+ * Sets the certificateEquals criterion. The specified
+ * {@code X509Certificate} must be equal to the
+ * {@code X509Certificate} passed to the {@code match} method.
+ * If {@code null}, then this check is not applied.
+ *
+ * <p>This method is particularly useful when it is necessary to
+ * match a single certificate. Although other criteria can be specified
+ * in conjunction with the certificateEquals criterion, it is usually not
+ * practical or necessary.
+ *
+ * @param cert the {@code X509Certificate} to match (or
+ * {@code null})
+ * @see #getCertificate
+ */
+ public void setCertificate(X509Certificate cert) {
+ x509Cert = cert;
+ }
+
+ /**
+ * Sets the serialNumber criterion. The specified serial number
+ * must match the certificate serial number in the
+ * {@code X509Certificate}. If {@code null}, any certificate
+ * serial number will do.
+ *
+ * @param serial the certificate serial number to match
+ * (or {@code null})
+ * @see #getSerialNumber
+ */
+ public void setSerialNumber(BigInteger serial) {
+ serialNumber = serial;
+ }
+
+ /**
+ * Sets the issuer criterion. The specified distinguished name
+ * must match the issuer distinguished name in the
+ * {@code X509Certificate}. If {@code null}, any issuer
+ * distinguished name will do.
+ *
+ * @param issuer a distinguished name as X500Principal
+ * (or {@code null})
+ * @since 1.5
+ */
+ public void setIssuer(X500Principal issuer) {
+ this.issuer = issuer;
+ }
+
+ /**
+ * <strong>Denigrated</strong>, use {@linkplain #setIssuer(X500Principal)}
+ * or {@linkplain #setIssuer(byte[])} instead. This method should not be
+ * relied on as it can fail to match some certificates because of a loss of
+ * encoding information in the
+ * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a> String form
+ * of some distinguished names.
+ * <p>
+ * Sets the issuer criterion. The specified distinguished name
+ * must match the issuer distinguished name in the
+ * {@code X509Certificate}. If {@code null}, any issuer
+ * distinguished name will do.
+ * <p>
+ * If {@code issuerDN} is not {@code null}, it should contain a
+ * distinguished name, in RFC 2253 format.
+ *
+ * @param issuerDN a distinguished name in RFC 2253 format
+ * (or {@code null})
+ * @throws IOException if a parsing error occurs (incorrect form for DN)
+ */
+ public void setIssuer(String issuerDN) throws IOException {
+ if (issuerDN == null) {
+ issuer = null;
+ } else {
+ issuer = new X500Name(issuerDN).asX500Principal();
+ }
+ }
+
+ /**
+ * Sets the issuer criterion. The specified distinguished name
+ * must match the issuer distinguished name in the
+ * {@code X509Certificate}. If {@code null} is specified,
+ * the issuer criterion is disabled and any issuer distinguished name will
+ * do.
+ * <p>
+ * If {@code issuerDN} is not {@code null}, it should contain a
+ * single DER encoded distinguished name, as defined in X.501. The ASN.1
+ * notation for this structure is as follows.
+ * <pre>{@code
+ * Name ::= CHOICE {
+ * RDNSequence }
+ *
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ *
+ * RelativeDistinguishedName ::=
+ * SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+ *
+ * AttributeTypeAndValue ::= SEQUENCE {
+ * type AttributeType,
+ * value AttributeValue }
+ *
+ * AttributeType ::= OBJECT IDENTIFIER
+ *
+ * AttributeValue ::= ANY DEFINED BY AttributeType
+ * ....
+ * DirectoryString ::= CHOICE {
+ * teletexString TeletexString (SIZE (1..MAX)),
+ * printableString PrintableString (SIZE (1..MAX)),
+ * universalString UniversalString (SIZE (1..MAX)),
+ * utf8String UTF8String (SIZE (1.. MAX)),
+ * bmpString BMPString (SIZE (1..MAX)) }
+ * }</pre>
+ * <p>
+ * Note that the byte array specified here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param issuerDN a byte array containing the distinguished name
+ * in ASN.1 DER encoded form (or {@code null})
+ * @throws IOException if an encoding error occurs (incorrect form for DN)
+ */
+ public void setIssuer(byte[] issuerDN) throws IOException {
+ try {
+ issuer = (issuerDN == null ? null : new X500Principal(issuerDN));
+ } catch (IllegalArgumentException e) {
+ throw new IOException("Invalid name", e);
+ }
+ }
+
+ /**
+ * Sets the subject criterion. The specified distinguished name
+ * must match the subject distinguished name in the
+ * {@code X509Certificate}. If {@code null}, any subject
+ * distinguished name will do.
+ *
+ * @param subject a distinguished name as X500Principal
+ * (or {@code null})
+ * @since 1.5
+ */
+ public void setSubject(X500Principal subject) {
+ this.subject = subject;
+ }
+
+ /**
+ * <strong>Denigrated</strong>, use {@linkplain #setSubject(X500Principal)}
+ * or {@linkplain #setSubject(byte[])} instead. This method should not be
+ * relied on as it can fail to match some certificates because of a loss of
+ * encoding information in the RFC 2253 String form of some distinguished
+ * names.
+ * <p>
+ * Sets the subject criterion. The specified distinguished name
+ * must match the subject distinguished name in the
+ * {@code X509Certificate}. If {@code null}, any subject
+ * distinguished name will do.
+ * <p>
+ * If {@code subjectDN} is not {@code null}, it should contain a
+ * distinguished name, in RFC 2253 format.
+ *
+ * @param subjectDN a distinguished name in RFC 2253 format
+ * (or {@code null})
+ * @throws IOException if a parsing error occurs (incorrect form for DN)
+ */
+ public void setSubject(String subjectDN) throws IOException {
+ if (subjectDN == null) {
+ subject = null;
+ } else {
+ subject = new X500Name(subjectDN).asX500Principal();
+ }
+ }
+
+ /**
+ * Sets the subject criterion. The specified distinguished name
+ * must match the subject distinguished name in the
+ * {@code X509Certificate}. If {@code null}, any subject
+ * distinguished name will do.
+ * <p>
+ * If {@code subjectDN} is not {@code null}, it should contain a
+ * single DER encoded distinguished name, as defined in X.501. For the ASN.1
+ * notation for this structure, see
+ * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
+ *
+ * @param subjectDN a byte array containing the distinguished name in
+ * ASN.1 DER format (or {@code null})
+ * @throws IOException if an encoding error occurs (incorrect form for DN)
+ */
+ public void setSubject(byte[] subjectDN) throws IOException {
+ try {
+ subject = (subjectDN == null ? null : new X500Principal(subjectDN));
+ } catch (IllegalArgumentException e) {
+ throw new IOException("Invalid name", e);
+ }
+ }
+
+ /**
+ * Sets the subjectKeyIdentifier criterion. The
+ * {@code X509Certificate} must contain a SubjectKeyIdentifier
+ * extension for which the contents of the extension
+ * matches the specified criterion value.
+ * If the criterion value is {@code null}, no
+ * subjectKeyIdentifier check will be done.
+ * <p>
+ * If {@code subjectKeyID} is not {@code null}, it
+ * should contain a single DER encoded value corresponding to the contents
+ * of the extension value (not including the object identifier,
+ * criticality setting, and encapsulating OCTET STRING)
+ * for a SubjectKeyIdentifier extension.
+ * The ASN.1 notation for this structure follows.
+ *
+ * <pre>{@code
+ * SubjectKeyIdentifier ::= KeyIdentifier
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * }</pre>
+ * <p>
+ * Since the format of subject key identifiers is not mandated by
+ * any standard, subject key identifiers are not parsed by the
+ * {@code X509CertSelector}. Instead, the values are compared using
+ * a byte-by-byte comparison.
+ * <p>
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param subjectKeyID the subject key identifier (or {@code null})
+ * @see #getSubjectKeyIdentifier
+ */
+ public void setSubjectKeyIdentifier(byte[] subjectKeyID) {
+ if (subjectKeyID == null) {
+ this.subjectKeyID = null;
+ } else {
+ this.subjectKeyID = subjectKeyID.clone();
+ }
+ }
+
+ /**
+ * Sets the authorityKeyIdentifier criterion. The
+ * {@code X509Certificate} must contain an
+ * AuthorityKeyIdentifier extension for which the contents of the
+ * extension value matches the specified criterion value.
+ * If the criterion value is {@code null}, no
+ * authorityKeyIdentifier check will be done.
+ * <p>
+ * If {@code authorityKeyID} is not {@code null}, it
+ * should contain a single DER encoded value corresponding to the contents
+ * of the extension value (not including the object identifier,
+ * criticality setting, and encapsulating OCTET STRING)
+ * for an AuthorityKeyIdentifier extension.
+ * The ASN.1 notation for this structure follows.
+ *
+ * <pre>{@code
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ * keyIdentifier [0] KeyIdentifier OPTIONAL,
+ * authorityCertIssuer [1] GeneralNames OPTIONAL,
+ * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ * KeyIdentifier ::= OCTET STRING
+ * }</pre>
+ * <p>
+ * Authority key identifiers are not parsed by the
+ * {@code X509CertSelector}. Instead, the values are
+ * compared using a byte-by-byte comparison.
+ * <p>
+ * When the {@code keyIdentifier} field of
+ * {@code AuthorityKeyIdentifier} is populated, the value is
+ * usually taken from the {@code SubjectKeyIdentifier} extension
+ * in the issuer's certificate. Note, however, that the result of
+ * {@code X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object
+ * Identifier>)} on the issuer's certificate may NOT be used
+ * directly as the input to {@code setAuthorityKeyIdentifier}.
+ * This is because the SubjectKeyIdentifier contains
+ * only a KeyIdentifier OCTET STRING, and not a SEQUENCE of
+ * KeyIdentifier, GeneralNames, and CertificateSerialNumber.
+ * In order to use the extension value of the issuer certificate's
+ * {@code SubjectKeyIdentifier}
+ * extension, it will be necessary to extract the value of the embedded
+ * {@code KeyIdentifier} OCTET STRING, then DER encode this OCTET
+ * STRING inside a SEQUENCE.
+ * For more details on SubjectKeyIdentifier, see
+ * {@link #setSubjectKeyIdentifier(byte[] subjectKeyID)}.
+ * <p>
+ * Note also that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param authorityKeyID the authority key identifier
+ * (or {@code null})
+ * @see #getAuthorityKeyIdentifier
+ */
+ public void setAuthorityKeyIdentifier(byte[] authorityKeyID) {
+ if (authorityKeyID == null) {
+ this.authorityKeyID = null;
+ } else {
+ this.authorityKeyID = authorityKeyID.clone();
+ }
+ }
+
+ /**
+ * Sets the certificateValid criterion. The specified date must fall
+ * within the certificate validity period for the
+ * {@code X509Certificate}. If {@code null}, no certificateValid
+ * check will be done.
+ * <p>
+ * Note that the {@code Date} supplied here is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param certValid the {@code Date} to check (or {@code null})
+ * @see #getCertificateValid
+ */
+ public void setCertificateValid(Date certValid) {
+ if (certValid == null) {
+ certificateValid = null;
+ } else {
+ certificateValid = (Date)certValid.clone();
+ }
+ }
+
+ /**
+ * Sets the privateKeyValid criterion. The specified date must fall
+ * within the private key validity period for the
+ * {@code X509Certificate}. If {@code null}, no privateKeyValid
+ * check will be done.
+ * <p>
+ * Note that the {@code Date} supplied here is cloned to protect
+ * against subsequent modifications.
+ *
+ * @param privateKeyValid the {@code Date} to check (or
+ * {@code null})
+ * @see #getPrivateKeyValid
+ */
+ public void setPrivateKeyValid(Date privateKeyValid) {
+ if (privateKeyValid == null) {
+ this.privateKeyValid = null;
+ } else {
+ this.privateKeyValid = (Date)privateKeyValid.clone();
+ }
+ }
+
+ /**
+ * Sets the subjectPublicKeyAlgID criterion. The
+ * {@code X509Certificate} must contain a subject public key
+ * with the specified algorithm. If {@code null}, no
+ * subjectPublicKeyAlgID check will be done.
+ *
+ * @param oid The object identifier (OID) of the algorithm to check
+ * for (or {@code null}). An OID is represented by a
+ * set of nonnegative integers separated by periods.
+ * @throws IOException if the OID is invalid, such as
+ * the first component being not 0, 1 or 2 or the second component
+ * being greater than 39.
+ *
+ * @see #getSubjectPublicKeyAlgID
+ */
+ public void setSubjectPublicKeyAlgID(String oid) throws IOException {
+ if (oid == null) {
+ subjectPublicKeyAlgID = null;
+ } else {
+ subjectPublicKeyAlgID = new ObjectIdentifier(oid);
+ }
+ }
+
+ /**
+ * Sets the subjectPublicKey criterion. The
+ * {@code X509Certificate} must contain the specified subject public
+ * key. If {@code null}, no subjectPublicKey check will be done.
+ *
+ * @param key the subject public key to check for (or {@code null})
+ * @see #getSubjectPublicKey
+ */
+ public void setSubjectPublicKey(PublicKey key) {
+ if (key == null) {
+ subjectPublicKey = null;
+ subjectPublicKeyBytes = null;
+ } else {
+ subjectPublicKey = key;
+ subjectPublicKeyBytes = key.getEncoded();
+ }
+ }
+
+ /**
+ * Sets the subjectPublicKey criterion. The {@code X509Certificate}
+ * must contain the specified subject public key. If {@code null},
+ * no subjectPublicKey check will be done.
+ * <p>
+ * Because this method allows the public key to be specified as a byte
+ * array, it may be used for unknown key types.
+ * <p>
+ * If {@code key} is not {@code null}, it should contain a
+ * single DER encoded SubjectPublicKeyInfo structure, as defined in X.509.
+ * The ASN.1 notation for this structure is as follows.
+ * <pre>{@code
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * -- contains a value of the type
+ * -- registered for use with the
+ * -- algorithm object identifier value
+ * }</pre>
+ * <p>
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param key a byte array containing the subject public key in ASN.1 DER
+ * form (or {@code null})
+ * @throws IOException if an encoding error occurs (incorrect form for
+ * subject public key)
+ * @see #getSubjectPublicKey
+ */
+ public void setSubjectPublicKey(byte[] key) throws IOException {
+ if (key == null) {
+ subjectPublicKey = null;
+ subjectPublicKeyBytes = null;
+ } else {
+ subjectPublicKeyBytes = key.clone();
+ subjectPublicKey = X509Key.parse(new DerValue(subjectPublicKeyBytes));
+ }
+ }
+
+ /**
+ * Sets the keyUsage criterion. The {@code X509Certificate}
+ * must allow the specified keyUsage values. If {@code null}, no
+ * keyUsage check will be done. Note that an {@code X509Certificate}
+ * that has no keyUsage extension implicitly allows all keyUsage values.
+ * <p>
+ * Note that the boolean array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param keyUsage a boolean array in the same format as the boolean
+ * array returned by
+ * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
+ * Or {@code null}.
+ * @see #getKeyUsage
+ */
+ public void setKeyUsage(boolean[] keyUsage) {
+ if (keyUsage == null) {
+ this.keyUsage = null;
+ } else {
+ this.keyUsage = keyUsage.clone();
+ }
+ }
+
+ /**
+ * Sets the extendedKeyUsage criterion. The {@code X509Certificate}
+ * must allow the specified key purposes in its extended key usage
+ * extension. If {@code keyPurposeSet} is empty or {@code null},
+ * no extendedKeyUsage check will be done. Note that an
+ * {@code X509Certificate} that has no extendedKeyUsage extension
+ * implicitly allows all key purposes.
+ * <p>
+ * Note that the {@code Set} is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param keyPurposeSet a {@code Set} of key purpose OIDs in string
+ * format (or {@code null}). Each OID is represented by a set of
+ * nonnegative integers separated by periods.
+ * @throws IOException if the OID is invalid, such as
+ * the first component being not 0, 1 or 2 or the second component
+ * being greater than 39.
+ * @see #getExtendedKeyUsage
+ */
+ public void setExtendedKeyUsage(Set<String> keyPurposeSet) throws IOException {
+ if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
+ this.keyPurposeSet = null;
+ keyPurposeOIDSet = null;
+ } else {
+ this.keyPurposeSet =
+ Collections.unmodifiableSet(new HashSet<String>(keyPurposeSet));
+ keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
+ for (String s : this.keyPurposeSet) {
+ keyPurposeOIDSet.add(new ObjectIdentifier(s));
+ }
+ }
+ }
+
+ /**
+ * Enables/disables matching all of the subjectAlternativeNames
+ * specified in the {@link #setSubjectAlternativeNames
+ * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
+ * addSubjectAlternativeName} methods. If enabled,
+ * the {@code X509Certificate} must contain all of the
+ * specified subject alternative names. If disabled, the
+ * {@code X509Certificate} must contain at least one of the
+ * specified subject alternative names.
+ *
+ * <p>The matchAllNames flag is {@code true} by default.
+ *
+ * @param matchAllNames if {@code true}, the flag is enabled;
+ * if {@code false}, the flag is disabled.
+ * @see #getMatchAllSubjectAltNames
+ */
+ public void setMatchAllSubjectAltNames(boolean matchAllNames) {
+ this.matchAllSubjectAltNames = matchAllNames;
+ }
+
+ /**
+ * Sets the subjectAlternativeNames criterion. The
+ * {@code X509Certificate} must contain all or at least one of the
+ * specified subjectAlternativeNames, depending on the value of
+ * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
+ * setMatchAllSubjectAltNames}).
+ * <p>
+ * This method allows the caller to specify, with a single method call,
+ * the complete set of subject alternative names for the
+ * subjectAlternativeNames criterion. The specified value replaces
+ * the previous value for the subjectAlternativeNames criterion.
+ * <p>
+ * The {@code names} parameter (if not {@code null}) is a
+ * {@code Collection} with one
+ * entry for each name to be included in the subject alternative name
+ * criterion. Each entry is a {@code List} whose first entry is an
+ * {@code Integer} (the name type, 0-8) and whose second
+ * entry is a {@code String} or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type. If {@code null}
+ * is supplied as the value for this argument, no
+ * subjectAlternativeNames check will be performed.
+ * <p>
+ * Each subject alternative name in the {@code Collection}
+ * may be specified either as a {@code String} or as an ASN.1 encoded
+ * byte array. For more details about the formats used, see
+ * {@link #addSubjectAlternativeName(int type, String name)
+ * addSubjectAlternativeName(int type, String name)} and
+ * {@link #addSubjectAlternativeName(int type, byte [] name)
+ * addSubjectAlternativeName(int type, byte [] name)}.
+ * <p>
+ * <strong>Note:</strong> for distinguished names, specify the byte
+ * array form instead of the String form. See the note in
+ * {@link #addSubjectAlternativeName(int, String)} for more information.
+ * <p>
+ * Note that the {@code names} parameter can contain duplicate
+ * names (same name and name type), but they may be removed from the
+ * {@code Collection} of names returned by the
+ * {@link #getSubjectAlternativeNames getSubjectAlternativeNames} method.
+ * <p>
+ * Note that a deep copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @param names a {@code Collection} of names (or {@code null})
+ * @throws IOException if a parsing error occurs
+ * @see #getSubjectAlternativeNames
+ */
+ public void setSubjectAlternativeNames(Collection<List<?>> names)
+ throws IOException {
+ if (names == null) {
+ subjectAlternativeNames = null;
+ subjectAlternativeGeneralNames = null;
+ } else {
+ if (names.isEmpty()) {
+ subjectAlternativeNames = null;
+ subjectAlternativeGeneralNames = null;
+ return;
+ }
+ Set<List<?>> tempNames = cloneAndCheckNames(names);
+ // Ensure that we either set both of these or neither
+ subjectAlternativeGeneralNames = parseNames(tempNames);
+ subjectAlternativeNames = tempNames;
+ }
+ }
+
+ /**
+ * Adds a name to the subjectAlternativeNames criterion. The
+ * {@code X509Certificate} must contain all or at least one
+ * of the specified subjectAlternativeNames, depending on the value of
+ * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
+ * setMatchAllSubjectAltNames}).
+ * <p>
+ * This method allows the caller to add a name to the set of subject
+ * alternative names.
+ * The specified name is added to any previous value for the
+ * subjectAlternativeNames criterion. If the specified name is a
+ * duplicate, it may be ignored.
+ * <p>
+ * The name is provided in string format.
+ * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
+ * names use the well-established string formats for those types (subject to
+ * the restrictions included in RFC 3280). IPv4 address names are
+ * supplied using dotted quad notation. OID address names are represented
+ * as a series of nonnegative integers separated by periods. And
+ * directory names (distinguished names) are supplied in RFC 2253 format.
+ * No standard string format is defined for otherNames, X.400 names,
+ * EDI party names, IPv6 address names, or any other type of names. They
+ * should be specified using the
+ * {@link #addSubjectAlternativeName(int type, byte [] name)
+ * addSubjectAlternativeName(int type, byte [] name)}
+ * method.
+ * <p>
+ * <strong>Note:</strong> for distinguished names, use
+ * {@linkplain #addSubjectAlternativeName(int, byte[])} instead.
+ * This method should not be relied on as it can fail to match some
+ * certificates because of a loss of encoding information in the RFC 2253
+ * String form of some distinguished names.
+ *
+ * @param type the name type (0-8, as specified in
+ * RFC 3280, section 4.2.1.7)
+ * @param name the name in string form (not {@code null})
+ * @throws IOException if a parsing error occurs
+ */
+ public void addSubjectAlternativeName(int type, String name)
+ throws IOException {
+ addSubjectAlternativeNameInternal(type, name);
+ }
+
+ /**
+ * Adds a name to the subjectAlternativeNames criterion. The
+ * {@code X509Certificate} must contain all or at least one
+ * of the specified subjectAlternativeNames, depending on the value of
+ * the matchAllNames flag (see {@link #setMatchAllSubjectAltNames
+ * setMatchAllSubjectAltNames}).
+ * <p>
+ * This method allows the caller to add a name to the set of subject
+ * alternative names.
+ * The specified name is added to any previous value for the
+ * subjectAlternativeNames criterion. If the specified name is a
+ * duplicate, it may be ignored.
+ * <p>
+ * The name is provided as a byte array. This byte array should contain
+ * the DER encoded name, as it would appear in the GeneralName structure
+ * defined in RFC 3280 and X.509. The encoded byte array should only contain
+ * the encoded value of the name, and should not include the tag associated
+ * with the name in the GeneralName structure. The ASN.1 definition of this
+ * structure appears below.
+ * <pre>{@code
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ * }</pre>
+ * <p>
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param type the name type (0-8, as listed above)
+ * @param name a byte array containing the name in ASN.1 DER encoded form
+ * @throws IOException if a parsing error occurs
+ */
+ public void addSubjectAlternativeName(int type, byte[] name)
+ throws IOException {
+ // clone because byte arrays are modifiable
+ addSubjectAlternativeNameInternal(type, name.clone());
+ }
+
+ /**
+ * A private method that adds a name (String or byte array) to the
+ * subjectAlternativeNames criterion. The {@code X509Certificate}
+ * must contain the specified subjectAlternativeName.
+ *
+ * @param type the name type (0-8, as specified in
+ * RFC 3280, section 4.2.1.7)
+ * @param name the name in string or byte array form
+ * @throws IOException if a parsing error occurs
+ */
+ private void addSubjectAlternativeNameInternal(int type, Object name)
+ throws IOException {
+ // First, ensure that the name parses
+ GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
+ if (subjectAlternativeNames == null) {
+ subjectAlternativeNames = new HashSet<List<?>>();
+ }
+ if (subjectAlternativeGeneralNames == null) {
+ subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
+ }
+ List<Object> list = new ArrayList<Object>(2);
+ list.add(Integer.valueOf(type));
+ list.add(name);
+ subjectAlternativeNames.add(list);
+ subjectAlternativeGeneralNames.add(tempName);
+ }
+
+ /**
+ * Parse an argument of the form passed to setSubjectAlternativeNames,
+ * returning a {@code Collection} of
+ * {@code GeneralNameInterface}s.
+ * Throw an IllegalArgumentException or a ClassCastException
+ * if the argument is malformed.
+ *
+ * @param names a Collection with one entry per name.
+ * Each entry is a {@code List} whose first entry
+ * is an Integer (the name type, 0-8) and whose second
+ * entry is a String or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type. Null is
+ * not an acceptable value.
+ * @return a Set of {@code GeneralNameInterface}s
+ * @throws IOException if a parsing error occurs
+ */
+ private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException {
+ Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
+ for (List<?> nameList : names) {
+ if (nameList.size() != 2) {
+ throw new IOException("name list size not 2");
+ }
+ Object o = nameList.get(0);
+ if (!(o instanceof Integer)) {
+ throw new IOException("expected an Integer");
+ }
+ int nameType = ((Integer)o).intValue();
+ o = nameList.get(1);
+ genNames.add(makeGeneralNameInterface(nameType, o));
+ }
+
+ return genNames;
+ }
+
+ /**
+ * Compare for equality two objects of the form passed to
+ * setSubjectAlternativeNames (or X509CRLSelector.setIssuerNames).
+ * Throw an {@code IllegalArgumentException} or a
+ * {@code ClassCastException} if one of the objects is malformed.
+ *
+ * @param object1 a Collection containing the first object to compare
+ * @param object2 a Collection containing the second object to compare
+ * @return true if the objects are equal, false otherwise
+ */
+ static boolean equalNames(Collection<?> object1, Collection<?> object2) {
+ if ((object1 == null) || (object2 == null)) {
+ return object1 == object2;
+ }
+ return object1.equals(object2);
+ }
+
+ /**
+ * Make a {@code GeneralNameInterface} out of a name type (0-8) and an
+ * Object that may be a byte array holding the ASN.1 DER encoded
+ * name or a String form of the name. Except for X.509
+ * Distinguished Names, the String form of the name must not be the
+ * result from calling toString on an existing GeneralNameInterface
+ * implementing class. The output of toString is not compatible
+ * with the String constructors for names other than Distinguished
+ * Names.
+ *
+ * @param type name type (0-8)
+ * @param name name as ASN.1 Der-encoded byte array or String
+ * @return a GeneralNameInterface name
+ * @throws IOException if a parsing error occurs
+ */
+ static GeneralNameInterface makeGeneralNameInterface(int type, Object name)
+ throws IOException {
+ GeneralNameInterface result;
+ if (debug != null) {
+ debug.println("X509CertSelector.makeGeneralNameInterface("
+ + type + ")...");
+ }
+
+ if (name instanceof String) {
+ if (debug != null) {
+ debug.println("X509CertSelector.makeGeneralNameInterface() "
+ + "name is String: " + name);
+ }
+ switch (type) {
+ case NAME_RFC822:
+ result = new RFC822Name((String)name);
+ break;
+ case NAME_DNS:
+ result = new DNSName((String)name);
+ break;
+ case NAME_DIRECTORY:
+ result = new X500Name((String)name);
+ break;
+ case NAME_URI:
+ result = new URIName((String)name);
+ break;
+ case NAME_IP:
+ result = new IPAddressName((String)name);
+ break;
+ case NAME_OID:
+ result = new OIDName((String)name);
+ break;
+ default:
+ throw new IOException("unable to parse String names of type "
+ + type);
+ }
+ if (debug != null) {
+ debug.println("X509CertSelector.makeGeneralNameInterface() "
+ + "result: " + result.toString());
+ }
+ } else if (name instanceof byte[]) {
+ DerValue val = new DerValue((byte[]) name);
+ if (debug != null) {
+ debug.println
+ ("X509CertSelector.makeGeneralNameInterface() is byte[]");
+ }
+
+ switch (type) {
+ case NAME_ANY:
+ result = new OtherName(val);
+ break;
+ case NAME_RFC822:
+ result = new RFC822Name(val);
+ break;
+ case NAME_DNS:
+ result = new DNSName(val);
+ break;
+ case NAME_X400:
+ result = new X400Address(val);
+ break;
+ case NAME_DIRECTORY:
+ result = new X500Name(val);
+ break;
+ case NAME_EDI:
+ result = new EDIPartyName(val);
+ break;
+ case NAME_URI:
+ result = new URIName(val);
+ break;
+ case NAME_IP:
+ result = new IPAddressName(val);
+ break;
+ case NAME_OID:
+ result = new OIDName(val);
+ break;
+ default:
+ throw new IOException("unable to parse byte array names of "
+ + "type " + type);
+ }
+ if (debug != null) {
+ debug.println("X509CertSelector.makeGeneralNameInterface() result: "
+ + result.toString());
+ }
+ } else {
+ if (debug != null) {
+ debug.println("X509CertSelector.makeGeneralName() input name "
+ + "not String or byte array");
+ }
+ throw new IOException("name not String or byte array");
+ }
+ return result;
+ }
+
+
+ /**
+ * Sets the name constraints criterion. The {@code X509Certificate}
+ * must have subject and subject alternative names that
+ * meet the specified name constraints.
+ * <p>
+ * The name constraints are specified as a byte array. This byte array
+ * should contain the DER encoded form of the name constraints, as they
+ * would appear in the NameConstraints structure defined in RFC 3280
+ * and X.509. The ASN.1 definition of this structure appears below.
+ *
+ * <pre>{@code
+ * NameConstraints ::= SEQUENCE {
+ * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+ *
+ * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+ *
+ * GeneralSubtree ::= SEQUENCE {
+ * base GeneralName,
+ * minimum [0] BaseDistance DEFAULT 0,
+ * maximum [1] BaseDistance OPTIONAL }
+ *
+ * BaseDistance ::= INTEGER (0..MAX)
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ * }</pre>
+ * <p>
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param bytes a byte array containing the ASN.1 DER encoding of
+ * a NameConstraints extension to be used for checking
+ * name constraints. Only the value of the extension is
+ * included, not the OID or criticality flag. Can be
+ * {@code null},
+ * in which case no name constraints check will be performed.
+ * @throws IOException if a parsing error occurs
+ * @see #getNameConstraints
+ */
+ public void setNameConstraints(byte[] bytes) throws IOException {
+ if (bytes == null) {
+ ncBytes = null;
+ nc = null;
+ } else {
+ ncBytes = bytes.clone();
+ nc = new NameConstraintsExtension(FALSE, bytes);
+ }
+ }
+
+ /**
+ * Sets the basic constraints constraint. If the value is greater than or
+ * equal to zero, {@code X509Certificates} must include a
+ * basicConstraints extension with
+ * a pathLen of at least this value. If the value is -2, only end-entity
+ * certificates are accepted. If the value is -1, no check is done.
+ * <p>
+ * This constraint is useful when building a certification path forward
+ * (from the target toward the trust anchor. If a partial path has been
+ * built, any candidate certificate must have a maxPathLen value greater
+ * than or equal to the number of certificates in the partial path.
+ *
+ * @param minMaxPathLen the value for the basic constraints constraint
+ * @throws IllegalArgumentException if the value is less than -2
+ * @see #getBasicConstraints
+ */
+ public void setBasicConstraints(int minMaxPathLen) {
+ if (minMaxPathLen < -2) {
+ throw new IllegalArgumentException("basic constraints less than -2");
+ }
+ basicConstraints = minMaxPathLen;
+ }
+
+ /**
+ * Sets the policy constraint. The {@code X509Certificate} must
+ * include at least one of the specified policies in its certificate
+ * policies extension. If {@code certPolicySet} is empty, then the
+ * {@code X509Certificate} must include at least some specified policy
+ * in its certificate policies extension. If {@code certPolicySet} is
+ * {@code null}, no policy check will be performed.
+ * <p>
+ * Note that the {@code Set} is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param certPolicySet a {@code Set} of certificate policy OIDs in
+ * string format (or {@code null}). Each OID is
+ * represented by a set of nonnegative integers
+ * separated by periods.
+ * @throws IOException if a parsing error occurs on the OID such as
+ * the first component is not 0, 1 or 2 or the second component is
+ * greater than 39.
+ * @see #getPolicy
+ */
+ public void setPolicy(Set<String> certPolicySet) throws IOException {
+ if (certPolicySet == null) {
+ policySet = null;
+ policy = null;
+ } else {
+ // Snapshot set and parse it
+ Set<String> tempSet = Collections.unmodifiableSet
+ (new HashSet<String>(certPolicySet));
+ /* Convert to Vector of ObjectIdentifiers */
+ Iterator<String> i = tempSet.iterator();
+ Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>();
+ while (i.hasNext()) {
+ Object o = i.next();
+ if (!(o instanceof String)) {
+ throw new IOException("non String in certPolicySet");
+ }
+ polIdVector.add(new CertificatePolicyId(new ObjectIdentifier(
+ (String)o)));
+ }
+ // If everything went OK, make the changes
+ policySet = tempSet;
+ policy = new CertificatePolicySet(polIdVector);
+ }
+ }
+
+ /**
+ * Sets the pathToNames criterion. The {@code X509Certificate} must
+ * not include name constraints that would prohibit building a
+ * path to the specified names.
+ * <p>
+ * This method allows the caller to specify, with a single method call,
+ * the complete set of names which the {@code X509Certificates}'s
+ * name constraints must permit. The specified value replaces
+ * the previous value for the pathToNames criterion.
+ * <p>
+ * This constraint is useful when building a certification path forward
+ * (from the target toward the trust anchor. If a partial path has been
+ * built, any candidate certificate must not include name constraints that
+ * would prohibit building a path to any of the names in the partial path.
+ * <p>
+ * The {@code names} parameter (if not {@code null}) is a
+ * {@code Collection} with one
+ * entry for each name to be included in the pathToNames
+ * criterion. Each entry is a {@code List} whose first entry is an
+ * {@code Integer} (the name type, 0-8) and whose second
+ * entry is a {@code String} or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type. If {@code null}
+ * is supplied as the value for this argument, no
+ * pathToNames check will be performed.
+ * <p>
+ * Each name in the {@code Collection}
+ * may be specified either as a {@code String} or as an ASN.1 encoded
+ * byte array. For more details about the formats used, see
+ * {@link #addPathToName(int type, String name)
+ * addPathToName(int type, String name)} and
+ * {@link #addPathToName(int type, byte [] name)
+ * addPathToName(int type, byte [] name)}.
+ * <p>
+ * <strong>Note:</strong> for distinguished names, specify the byte
+ * array form instead of the String form. See the note in
+ * {@link #addPathToName(int, String)} for more information.
+ * <p>
+ * Note that the {@code names} parameter can contain duplicate
+ * names (same name and name type), but they may be removed from the
+ * {@code Collection} of names returned by the
+ * {@link #getPathToNames getPathToNames} method.
+ * <p>
+ * Note that a deep copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @param names a {@code Collection} with one entry per name
+ * (or {@code null})
+ * @throws IOException if a parsing error occurs
+ * @see #getPathToNames
+ */
+ public void setPathToNames(Collection<List<?>> names) throws IOException {
+ if ((names == null) || names.isEmpty()) {
+ pathToNames = null;
+ pathToGeneralNames = null;
+ } else {
+ Set<List<?>> tempNames = cloneAndCheckNames(names);
+ pathToGeneralNames = parseNames(tempNames);
+ // Ensure that we either set both of these or neither
+ pathToNames = tempNames;
+ }
+ }
+
+ // called from CertPathHelper
+ void setPathToNamesInternal(Set<GeneralNameInterface> names) {
+ // set names to non-null dummy value
+ // this breaks getPathToNames()
+ pathToNames = Collections.<List<?>>emptySet();
+ pathToGeneralNames = names;
+ }
+
+ /**
+ * Adds a name to the pathToNames criterion. The {@code X509Certificate}
+ * must not include name constraints that would prohibit building a
+ * path to the specified name.
+ * <p>
+ * This method allows the caller to add a name to the set of names which
+ * the {@code X509Certificates}'s name constraints must permit.
+ * The specified name is added to any previous value for the
+ * pathToNames criterion. If the name is a duplicate, it may be ignored.
+ * <p>
+ * The name is provided in string format. RFC 822, DNS, and URI names
+ * use the well-established string formats for those types (subject to
+ * the restrictions included in RFC 3280). IPv4 address names are
+ * supplied using dotted quad notation. OID address names are represented
+ * as a series of nonnegative integers separated by periods. And
+ * directory names (distinguished names) are supplied in RFC 2253 format.
+ * No standard string format is defined for otherNames, X.400 names,
+ * EDI party names, IPv6 address names, or any other type of names. They
+ * should be specified using the
+ * {@link #addPathToName(int type, byte [] name)
+ * addPathToName(int type, byte [] name)} method.
+ * <p>
+ * <strong>Note:</strong> for distinguished names, use
+ * {@linkplain #addPathToName(int, byte[])} instead.
+ * This method should not be relied on as it can fail to match some
+ * certificates because of a loss of encoding information in the RFC 2253
+ * String form of some distinguished names.
+ *
+ * @param type the name type (0-8, as specified in
+ * RFC 3280, section 4.2.1.7)
+ * @param name the name in string form
+ * @throws IOException if a parsing error occurs
+ */
+ public void addPathToName(int type, String name) throws IOException {
+ addPathToNameInternal(type, name);
+ }
+
+ /**
+ * Adds a name to the pathToNames criterion. The {@code X509Certificate}
+ * must not include name constraints that would prohibit building a
+ * path to the specified name.
+ * <p>
+ * This method allows the caller to add a name to the set of names which
+ * the {@code X509Certificates}'s name constraints must permit.
+ * The specified name is added to any previous value for the
+ * pathToNames criterion. If the name is a duplicate, it may be ignored.
+ * <p>
+ * The name is provided as a byte array. This byte array should contain
+ * the DER encoded name, as it would appear in the GeneralName structure
+ * defined in RFC 3280 and X.509. The ASN.1 definition of this structure
+ * appears in the documentation for
+ * {@link #addSubjectAlternativeName(int type, byte [] name)
+ * addSubjectAlternativeName(int type, byte [] name)}.
+ * <p>
+ * Note that the byte array supplied here is cloned to protect against
+ * subsequent modifications.
+ *
+ * @param type the name type (0-8, as specified in
+ * RFC 3280, section 4.2.1.7)
+ * @param name a byte array containing the name in ASN.1 DER encoded form
+ * @throws IOException if a parsing error occurs
+ */
+ public void addPathToName(int type, byte [] name) throws IOException {
+ // clone because byte arrays are modifiable
+ addPathToNameInternal(type, name.clone());
+ }
+
+ /**
+ * A private method that adds a name (String or byte array) to the
+ * pathToNames criterion. The {@code X509Certificate} must contain
+ * the specified pathToName.
+ *
+ * @param type the name type (0-8, as specified in
+ * RFC 3280, section 4.2.1.7)
+ * @param name the name in string or byte array form
+ * @throws IOException if an encoding error occurs (incorrect form for DN)
+ */
+ private void addPathToNameInternal(int type, Object name)
+ throws IOException {
+ // First, ensure that the name parses
+ GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
+ if (pathToGeneralNames == null) {
+ pathToNames = new HashSet<List<?>>();
+ pathToGeneralNames = new HashSet<GeneralNameInterface>();
+ }
+ List<Object> list = new ArrayList<Object>(2);
+ list.add(Integer.valueOf(type));
+ list.add(name);
+ pathToNames.add(list);
+ pathToGeneralNames.add(tempName);
+ }
+
+ /**
+ * Returns the certificateEquals criterion. The specified
+ * {@code X509Certificate} must be equal to the
+ * {@code X509Certificate} passed to the {@code match} method.
+ * If {@code null}, this check is not applied.
+ *
+ * @return the {@code X509Certificate} to match (or {@code null})
+ * @see #setCertificate
+ */
+ public X509Certificate getCertificate() {
+ return x509Cert;
+ }
+
+ /**
+ * Returns the serialNumber criterion. The specified serial number
+ * must match the certificate serial number in the
+ * {@code X509Certificate}. If {@code null}, any certificate
+ * serial number will do.
+ *
+ * @return the certificate serial number to match
+ * (or {@code null})
+ * @see #setSerialNumber
+ */
+ public BigInteger getSerialNumber() {
+ return serialNumber;
+ }
+
+ /**
+ * Returns the issuer criterion as an {@code X500Principal}. This
+ * distinguished name must match the issuer distinguished name in the
+ * {@code X509Certificate}. If {@code null}, the issuer criterion
+ * is disabled and any issuer distinguished name will do.
+ *
+ * @return the required issuer distinguished name as X500Principal
+ * (or {@code null})
+ * @since 1.5
+ */
+ public X500Principal getIssuer() {
+ return issuer;
+ }
+
+ /**
+ * <strong>Denigrated</strong>, use {@linkplain #getIssuer()} or
+ * {@linkplain #getIssuerAsBytes()} instead. This method should not be
+ * relied on as it can fail to match some certificates because of a loss of
+ * encoding information in the RFC 2253 String form of some distinguished
+ * names.
+ * <p>
+ * Returns the issuer criterion as a {@code String}. This
+ * distinguished name must match the issuer distinguished name in the
+ * {@code X509Certificate}. If {@code null}, the issuer criterion
+ * is disabled and any issuer distinguished name will do.
+ * <p>
+ * If the value returned is not {@code null}, it is a
+ * distinguished name, in RFC 2253 format.
+ *
+ * @return the required issuer distinguished name in RFC 2253 format
+ * (or {@code null})
+ */
+ public String getIssuerAsString() {
+ return (issuer == null ? null : issuer.getName());
+ }
+
+ /**
+ * Returns the issuer criterion as a byte array. This distinguished name
+ * must match the issuer distinguished name in the
+ * {@code X509Certificate}. If {@code null}, the issuer criterion
+ * is disabled and any issuer distinguished name will do.
+ * <p>
+ * If the value returned is not {@code null}, it is a byte
+ * array containing a single DER encoded distinguished name, as defined in
+ * X.501. The ASN.1 notation for this structure is supplied in the
+ * documentation for
+ * {@link #setIssuer(byte [] issuerDN) setIssuer(byte [] issuerDN)}.
+ * <p>
+ * Note that the byte array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return a byte array containing the required issuer distinguished name
+ * in ASN.1 DER format (or {@code null})
+ * @throws IOException if an encoding error occurs
+ */
+ public byte[] getIssuerAsBytes() throws IOException {
+ return (issuer == null ? null: issuer.getEncoded());
+ }
+
+ /**
+ * Returns the subject criterion as an {@code X500Principal}. This
+ * distinguished name must match the subject distinguished name in the
+ * {@code X509Certificate}. If {@code null}, the subject criterion
+ * is disabled and any subject distinguished name will do.
+ *
+ * @return the required subject distinguished name as X500Principal
+ * (or {@code null})
+ * @since 1.5
+ */
+ public X500Principal getSubject() {
+ return subject;
+ }
+
+ /**
+ * <strong>Denigrated</strong>, use {@linkplain #getSubject()} or
+ * {@linkplain #getSubjectAsBytes()} instead. This method should not be
+ * relied on as it can fail to match some certificates because of a loss of
+ * encoding information in the RFC 2253 String form of some distinguished
+ * names.
+ * <p>
+ * Returns the subject criterion as a {@code String}. This
+ * distinguished name must match the subject distinguished name in the
+ * {@code X509Certificate}. If {@code null}, the subject criterion
+ * is disabled and any subject distinguished name will do.
+ * <p>
+ * If the value returned is not {@code null}, it is a
+ * distinguished name, in RFC 2253 format.
+ *
+ * @return the required subject distinguished name in RFC 2253 format
+ * (or {@code null})
+ */
+ public String getSubjectAsString() {
+ return (subject == null ? null : subject.getName());
+ }
+
+ /**
+ * Returns the subject criterion as a byte array. This distinguished name
+ * must match the subject distinguished name in the
+ * {@code X509Certificate}. If {@code null}, the subject criterion
+ * is disabled and any subject distinguished name will do.
+ * <p>
+ * If the value returned is not {@code null}, it is a byte
+ * array containing a single DER encoded distinguished name, as defined in
+ * X.501. The ASN.1 notation for this structure is supplied in the
+ * documentation for
+ * {@link #setSubject(byte [] subjectDN) setSubject(byte [] subjectDN)}.
+ * <p>
+ * Note that the byte array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return a byte array containing the required subject distinguished name
+ * in ASN.1 DER format (or {@code null})
+ * @throws IOException if an encoding error occurs
+ */
+ public byte[] getSubjectAsBytes() throws IOException {
+ return (subject == null ? null : subject.getEncoded());
+ }
+
+ /**
+ * Returns the subjectKeyIdentifier criterion. The
+ * {@code X509Certificate} must contain a SubjectKeyIdentifier
+ * extension with the specified value. If {@code null}, no
+ * subjectKeyIdentifier check will be done.
+ * <p>
+ * Note that the byte array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the key identifier (or {@code null})
+ * @see #setSubjectKeyIdentifier
+ */
+ public byte[] getSubjectKeyIdentifier() {
+ if (subjectKeyID == null) {
+ return null;
+ }
+ return subjectKeyID.clone();
+ }
+
+ /**
+ * Returns the authorityKeyIdentifier criterion. The
+ * {@code X509Certificate} must contain a AuthorityKeyIdentifier
+ * extension with the specified value. If {@code null}, no
+ * authorityKeyIdentifier check will be done.
+ * <p>
+ * Note that the byte array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the key identifier (or {@code null})
+ * @see #setAuthorityKeyIdentifier
+ */
+ public byte[] getAuthorityKeyIdentifier() {
+ if (authorityKeyID == null) {
+ return null;
+ }
+ return authorityKeyID.clone();
+ }
+
+ /**
+ * Returns the certificateValid criterion. The specified date must fall
+ * within the certificate validity period for the
+ * {@code X509Certificate}. If {@code null}, no certificateValid
+ * check will be done.
+ * <p>
+ * Note that the {@code Date} returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the {@code Date} to check (or {@code null})
+ * @see #setCertificateValid
+ */
+ public Date getCertificateValid() {
+ if (certificateValid == null) {
+ return null;
+ }
+ return (Date)certificateValid.clone();
+ }
+
+ /**
+ * Returns the privateKeyValid criterion. The specified date must fall
+ * within the private key validity period for the
+ * {@code X509Certificate}. If {@code null}, no privateKeyValid
+ * check will be done.
+ * <p>
+ * Note that the {@code Date} returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return the {@code Date} to check (or {@code null})
+ * @see #setPrivateKeyValid
+ */
+ public Date getPrivateKeyValid() {
+ if (privateKeyValid == null) {
+ return null;
+ }
+ return (Date)privateKeyValid.clone();
+ }
+
+ /**
+ * Returns the subjectPublicKeyAlgID criterion. The
+ * {@code X509Certificate} must contain a subject public key
+ * with the specified algorithm. If {@code null}, no
+ * subjectPublicKeyAlgID check will be done.
+ *
+ * @return the object identifier (OID) of the signature algorithm to check
+ * for (or {@code null}). An OID is represented by a set of
+ * nonnegative integers separated by periods.
+ * @see #setSubjectPublicKeyAlgID
+ */
+ public String getSubjectPublicKeyAlgID() {
+ if (subjectPublicKeyAlgID == null) {
+ return null;
+ }
+ return subjectPublicKeyAlgID.toString();
+ }
+
+ /**
+ * Returns the subjectPublicKey criterion. The
+ * {@code X509Certificate} must contain the specified subject
+ * public key. If {@code null}, no subjectPublicKey check will be done.
+ *
+ * @return the subject public key to check for (or {@code null})
+ * @see #setSubjectPublicKey
+ */
+ public PublicKey getSubjectPublicKey() {
+ return subjectPublicKey;
+ }
+
+ /**
+ * Returns the keyUsage criterion. The {@code X509Certificate}
+ * must allow the specified keyUsage values. If null, no keyUsage
+ * check will be done.
+ * <p>
+ * Note that the boolean array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return a boolean array in the same format as the boolean
+ * array returned by
+ * {@link X509Certificate#getKeyUsage() X509Certificate.getKeyUsage()}.
+ * Or {@code null}.
+ * @see #setKeyUsage
+ */
+ public boolean[] getKeyUsage() {
+ if (keyUsage == null) {
+ return null;
+ }
+ return keyUsage.clone();
+ }
+
+ /**
+ * Returns the extendedKeyUsage criterion. The {@code X509Certificate}
+ * must allow the specified key purposes in its extended key usage
+ * extension. If the {@code keyPurposeSet} returned is empty or
+ * {@code null}, no extendedKeyUsage check will be done. Note that an
+ * {@code X509Certificate} that has no extendedKeyUsage extension
+ * implicitly allows all key purposes.
+ *
+ * @return an immutable {@code Set} of key purpose OIDs in string
+ * format (or {@code null})
+ * @see #setExtendedKeyUsage
+ */
+ public Set<String> getExtendedKeyUsage() {
+ return keyPurposeSet;
+ }
+
+ /**
+ * Indicates if the {@code X509Certificate} must contain all
+ * or at least one of the subjectAlternativeNames
+ * specified in the {@link #setSubjectAlternativeNames
+ * setSubjectAlternativeNames} or {@link #addSubjectAlternativeName
+ * addSubjectAlternativeName} methods. If {@code true},
+ * the {@code X509Certificate} must contain all of the
+ * specified subject alternative names. If {@code false}, the
+ * {@code X509Certificate} must contain at least one of the
+ * specified subject alternative names.
+ *
+ * @return {@code true} if the flag is enabled;
+ * {@code false} if the flag is disabled. The flag is
+ * {@code true} by default.
+ * @see #setMatchAllSubjectAltNames
+ */
+ public boolean getMatchAllSubjectAltNames() {
+ return matchAllSubjectAltNames;
+ }
+
+ /**
+ * Returns a copy of the subjectAlternativeNames criterion.
+ * The {@code X509Certificate} must contain all or at least one
+ * of the specified subjectAlternativeNames, depending on the value
+ * of the matchAllNames flag (see {@link #getMatchAllSubjectAltNames
+ * getMatchAllSubjectAltNames}). If the value returned is
+ * {@code null}, no subjectAlternativeNames check will be performed.
+ * <p>
+ * If the value returned is not {@code null}, it is a
+ * {@code Collection} with
+ * one entry for each name to be included in the subject alternative name
+ * criterion. Each entry is a {@code List} whose first entry is an
+ * {@code Integer} (the name type, 0-8) and whose second
+ * entry is a {@code String} or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type. Note that the
+ * {@code Collection} returned may contain duplicate names (same name
+ * and name type).
+ * <p>
+ * Each subject alternative name in the {@code Collection}
+ * may be specified either as a {@code String} or as an ASN.1 encoded
+ * byte array. For more details about the formats used, see
+ * {@link #addSubjectAlternativeName(int type, String name)
+ * addSubjectAlternativeName(int type, String name)} and
+ * {@link #addSubjectAlternativeName(int type, byte [] name)
+ * addSubjectAlternativeName(int type, byte [] name)}.
+ * <p>
+ * Note that a deep copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @return a {@code Collection} of names (or {@code null})
+ * @see #setSubjectAlternativeNames
+ */
+ public Collection<List<?>> getSubjectAlternativeNames() {
+ if (subjectAlternativeNames == null) {
+ return null;
+ }
+ return cloneNames(subjectAlternativeNames);
+ }
+
+ /**
+ * Clone an object of the form passed to
+ * setSubjectAlternativeNames and setPathToNames.
+ * Throw a {@code RuntimeException} if the argument is malformed.
+ * <p>
+ * This method wraps cloneAndCheckNames, changing any
+ * {@code IOException} into a {@code RuntimeException}. This
+ * method should be used when the object being
+ * cloned has already been checked, so there should never be any exceptions.
+ *
+ * @param names a {@code Collection} with one entry per name.
+ * Each entry is a {@code List} whose first entry
+ * is an Integer (the name type, 0-8) and whose second
+ * entry is a String or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type. Null
+ * is not an acceptable value.
+ * @return a deep copy of the specified {@code Collection}
+ * @throws RuntimeException if a parsing error occurs
+ */
+ private static Set<List<?>> cloneNames(Collection<List<?>> names) {
+ try {
+ return cloneAndCheckNames(names);
+ } catch (IOException e) {
+ throw new RuntimeException("cloneNames encountered IOException: " +
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Clone and check an argument of the form passed to
+ * setSubjectAlternativeNames and setPathToNames.
+ * Throw an {@code IOException} if the argument is malformed.
+ *
+ * @param names a {@code Collection} with one entry per name.
+ * Each entry is a {@code List} whose first entry
+ * is an Integer (the name type, 0-8) and whose second
+ * entry is a String or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type.
+ * {@code null} is not an acceptable value.
+ * @return a deep copy of the specified {@code Collection}
+ * @throws IOException if a parsing error occurs
+ */
+ private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
+ // Copy the Lists and Collection
+ Set<List<?>> namesCopy = new HashSet<List<?>>();
+ for (List<?> o : names)
+ {
+ namesCopy.add(new ArrayList<Object>(o));
+ }
+
+ // Check the contents of the Lists and clone any byte arrays
+ for (List<?> list : namesCopy) {
+ @SuppressWarnings("unchecked") // See javadoc for parameter "names".
+ List<Object> nameList = (List<Object>)list;
+ if (nameList.size() != 2) {
+ throw new IOException("name list size not 2");
+ }
+ Object o = nameList.get(0);
+ if (!(o instanceof Integer)) {
+ throw new IOException("expected an Integer");
+ }
+ int nameType = ((Integer)o).intValue();
+ if ((nameType < 0) || (nameType > 8)) {
+ throw new IOException("name type not 0-8");
+ }
+ Object nameObject = nameList.get(1);
+ if (!(nameObject instanceof byte[]) &&
+ !(nameObject instanceof String)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.cloneAndCheckNames() "
+ + "name not byte array");
+ }
+ throw new IOException("name not byte array or String");
+ }
+ if (nameObject instanceof byte[]) {
+ nameList.set(1, ((byte[]) nameObject).clone());
+ }
+ }
+ return namesCopy;
+ }
+
+ /**
+ * Returns the name constraints criterion. The {@code X509Certificate}
+ * must have subject and subject alternative names that
+ * meet the specified name constraints.
+ * <p>
+ * The name constraints are returned as a byte array. This byte array
+ * contains the DER encoded form of the name constraints, as they
+ * would appear in the NameConstraints structure defined in RFC 3280
+ * and X.509. The ASN.1 notation for this structure is supplied in the
+ * documentation for
+ * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
+ * <p>
+ * Note that the byte array returned is cloned to protect against
+ * subsequent modifications.
+ *
+ * @return a byte array containing the ASN.1 DER encoding of
+ * a NameConstraints extension used for checking name constraints.
+ * {@code null} if no name constraints check will be performed.
+ * @see #setNameConstraints
+ */
+ public byte[] getNameConstraints() {
+ if (ncBytes == null) {
+ return null;
+ } else {
+ return ncBytes.clone();
+ }
+ }
+
+ /**
+ * Returns the basic constraints constraint. If the value is greater than
+ * or equal to zero, the {@code X509Certificates} must include a
+ * basicConstraints extension with a pathLen of at least this value.
+ * If the value is -2, only end-entity certificates are accepted. If
+ * the value is -1, no basicConstraints check is done.
+ *
+ * @return the value for the basic constraints constraint
+ * @see #setBasicConstraints
+ */
+ public int getBasicConstraints() {
+ return basicConstraints;
+ }
+
+ /**
+ * Returns the policy criterion. The {@code X509Certificate} must
+ * include at least one of the specified policies in its certificate policies
+ * extension. If the {@code Set} returned is empty, then the
+ * {@code X509Certificate} must include at least some specified policy
+ * in its certificate policies extension. If the {@code Set} returned is
+ * {@code null}, no policy check will be performed.
+ *
+ * @return an immutable {@code Set} of certificate policy OIDs in
+ * string format (or {@code null})
+ * @see #setPolicy
+ */
+ public Set<String> getPolicy() {
+ return policySet;
+ }
+
+ /**
+ * Returns a copy of the pathToNames criterion. The
+ * {@code X509Certificate} must not include name constraints that would
+ * prohibit building a path to the specified names. If the value
+ * returned is {@code null}, no pathToNames check will be performed.
+ * <p>
+ * If the value returned is not {@code null}, it is a
+ * {@code Collection} with one
+ * entry for each name to be included in the pathToNames
+ * criterion. Each entry is a {@code List} whose first entry is an
+ * {@code Integer} (the name type, 0-8) and whose second
+ * entry is a {@code String} or a byte array (the name, in
+ * string or ASN.1 DER encoded form, respectively).
+ * There can be multiple names of the same type. Note that the
+ * {@code Collection} returned may contain duplicate names (same
+ * name and name type).
+ * <p>
+ * Each name in the {@code Collection}
+ * may be specified either as a {@code String} or as an ASN.1 encoded
+ * byte array. For more details about the formats used, see
+ * {@link #addPathToName(int type, String name)
+ * addPathToName(int type, String name)} and
+ * {@link #addPathToName(int type, byte [] name)
+ * addPathToName(int type, byte [] name)}.
+ * <p>
+ * Note that a deep copy is performed on the {@code Collection} to
+ * protect against subsequent modifications.
+ *
+ * @return a {@code Collection} of names (or {@code null})
+ * @see #setPathToNames
+ */
+ public Collection<List<?>> getPathToNames() {
+ if (pathToNames == null) {
+ return null;
+ }
+ return cloneNames(pathToNames);
+ }
+
+ /**
+ * Return a printable representation of the {@code CertSelector}.
+ *
+ * @return a {@code String} describing the contents of the
+ * {@code CertSelector}
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("X509CertSelector: [\n");
+ if (x509Cert != null) {
+ sb.append(" Certificate: " + x509Cert.toString() + "\n");
+ }
+ if (serialNumber != null) {
+ sb.append(" Serial Number: " + serialNumber.toString() + "\n");
+ }
+ if (issuer != null) {
+ sb.append(" Issuer: " + getIssuerAsString() + "\n");
+ }
+ if (subject != null) {
+ sb.append(" Subject: " + getSubjectAsString() + "\n");
+ }
+ sb.append(" matchAllSubjectAltNames flag: "
+ + String.valueOf(matchAllSubjectAltNames) + "\n");
+ if (subjectAlternativeNames != null) {
+ sb.append(" SubjectAlternativeNames:\n");
+ Iterator<List<?>> i = subjectAlternativeNames.iterator();
+ while (i.hasNext()) {
+ List<?> list = i.next();
+ sb.append(" type " + list.get(0) +
+ ", name " + list.get(1) + "\n");
+ }
+ }
+ if (subjectKeyID != null) {
+ HexDumpEncoder enc = new HexDumpEncoder();
+ sb.append(" Subject Key Identifier: " +
+ enc.encodeBuffer(subjectKeyID) + "\n");
+ }
+ if (authorityKeyID != null) {
+ HexDumpEncoder enc = new HexDumpEncoder();
+ sb.append(" Authority Key Identifier: " +
+ enc.encodeBuffer(authorityKeyID) + "\n");
+ }
+ if (certificateValid != null) {
+ sb.append(" Certificate Valid: " +
+ certificateValid.toString() + "\n");
+ }
+ if (privateKeyValid != null) {
+ sb.append(" Private Key Valid: " +
+ privateKeyValid.toString() + "\n");
+ }
+ if (subjectPublicKeyAlgID != null) {
+ sb.append(" Subject Public Key AlgID: " +
+ subjectPublicKeyAlgID.toString() + "\n");
+ }
+ if (subjectPublicKey != null) {
+ sb.append(" Subject Public Key: " +
+ subjectPublicKey.toString() + "\n");
+ }
+ if (keyUsage != null) {
+ sb.append(" Key Usage: " + keyUsageToString(keyUsage) + "\n");
+ }
+ if (keyPurposeSet != null) {
+ sb.append(" Extended Key Usage: " +
+ keyPurposeSet.toString() + "\n");
+ }
+ if (policy != null) {
+ sb.append(" Policy: " + policy.toString() + "\n");
+ }
+ if (pathToGeneralNames != null) {
+ sb.append(" Path to names:\n");
+ Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator();
+ while (i.hasNext()) {
+ sb.append(" " + i.next() + "\n");
+ }
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ // Copied from sun.security.x509.KeyUsageExtension
+ // (without calling the superclass)
+ /**
+ * Returns a printable representation of the KeyUsage.
+ */
+ private static String keyUsageToString(boolean[] k) {
+ String s = "KeyUsage [\n";
+ try {
+ if (k[0]) {
+ s += " DigitalSignature\n";
+ }
+ if (k[1]) {
+ s += " Non_repudiation\n";
+ }
+ if (k[2]) {
+ s += " Key_Encipherment\n";
+ }
+ if (k[3]) {
+ s += " Data_Encipherment\n";
+ }
+ if (k[4]) {
+ s += " Key_Agreement\n";
+ }
+ if (k[5]) {
+ s += " Key_CertSign\n";
+ }
+ if (k[6]) {
+ s += " Crl_Sign\n";
+ }
+ if (k[7]) {
+ s += " Encipher_Only\n";
+ }
+ if (k[8]) {
+ s += " Decipher_Only\n";
+ }
+ } catch (ArrayIndexOutOfBoundsException ex) {}
+
+ s += "]\n";
+
+ return (s);
+ }
+
+ /**
+ * Returns an Extension object given any X509Certificate and extension oid.
+ * Throw an {@code IOException} if the extension byte value is
+ * malformed.
+ *
+ * @param cert a {@code X509Certificate}
+ * @param extId an {@code integer} which specifies the extension index.
+ * Currently, the supported extensions are as follows:
+ * index 0 - PrivateKeyUsageExtension
+ * index 1 - SubjectAlternativeNameExtension
+ * index 2 - NameConstraintsExtension
+ * index 3 - CertificatePoliciesExtension
+ * index 4 - ExtendedKeyUsageExtension
+ * @return an {@code Extension} object whose real type is as specified
+ * by the extension oid.
+ * @throws IOException if cannot construct the {@code Extension}
+ * object with the extension encoding retrieved from the passed in
+ * {@code X509Certificate}.
+ */
+ private static Extension getExtensionObject(X509Certificate cert, int extId)
+ throws IOException {
+ if (cert instanceof X509CertImpl) {
+ X509CertImpl impl = (X509CertImpl)cert;
+ switch (extId) {
+ case PRIVATE_KEY_USAGE_ID:
+ return impl.getPrivateKeyUsageExtension();
+ case SUBJECT_ALT_NAME_ID:
+ return impl.getSubjectAlternativeNameExtension();
+ case NAME_CONSTRAINTS_ID:
+ return impl.getNameConstraintsExtension();
+ case CERT_POLICIES_ID:
+ return impl.getCertificatePoliciesExtension();
+ case EXTENDED_KEY_USAGE_ID:
+ return impl.getExtendedKeyUsageExtension();
+ default:
+ return null;
+ }
+ }
+ byte[] rawExtVal = cert.getExtensionValue(EXTENSION_OIDS[extId]);
+ if (rawExtVal == null) {
+ return null;
+ }
+ DerInputStream in = new DerInputStream(rawExtVal);
+ byte[] encoded = in.getOctetString();
+ switch (extId) {
+ case PRIVATE_KEY_USAGE_ID:
+ try {
+ return new PrivateKeyUsageExtension(FALSE, encoded);
+ } catch (CertificateException ex) {
+ throw new IOException(ex.getMessage());
+ }
+ case SUBJECT_ALT_NAME_ID:
+ return new SubjectAlternativeNameExtension(FALSE, encoded);
+ case NAME_CONSTRAINTS_ID:
+ return new NameConstraintsExtension(FALSE, encoded);
+ case CERT_POLICIES_ID:
+ return new CertificatePoliciesExtension(FALSE, encoded);
+ case EXTENDED_KEY_USAGE_ID:
+ return new ExtendedKeyUsageExtension(FALSE, encoded);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Decides whether a {@code Certificate} should be selected.
+ *
+ * @param cert the {@code Certificate} to be checked
+ * @return {@code true} if the {@code Certificate} should be
+ * selected, {@code false} otherwise
+ */
+ public boolean match(Certificate cert) {
+ if (!(cert instanceof X509Certificate)) {
+ return false;
+ }
+ X509Certificate xcert = (X509Certificate)cert;
+
+ if (debug != null) {
+ debug.println("X509CertSelector.match(SN: "
+ + (xcert.getSerialNumber()).toString(16) + "\n Issuer: "
+ + xcert.getIssuerDN() + "\n Subject: " + xcert.getSubjectDN()
+ + ")");
+ }
+
+ /* match on X509Certificate */
+ if (x509Cert != null) {
+ if (!x509Cert.equals(xcert)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "certs don't match");
+ }
+ return false;
+ }
+ }
+
+ /* match on serial number */
+ if (serialNumber != null) {
+ if (!serialNumber.equals(xcert.getSerialNumber())) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "serial numbers don't match");
+ }
+ return false;
+ }
+ }
+
+ /* match on issuer name */
+ if (issuer != null) {
+ if (!issuer.equals(xcert.getIssuerX500Principal())) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "issuer DNs don't match");
+ }
+ return false;
+ }
+ }
+
+ /* match on subject name */
+ if (subject != null) {
+ if (!subject.equals(xcert.getSubjectX500Principal())) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "subject DNs don't match");
+ }
+ return false;
+ }
+ }
+
+ /* match on certificate validity range */
+ if (certificateValid != null) {
+ try {
+ xcert.checkValidity(certificateValid);
+ } catch (CertificateException e) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "certificate not within validity period");
+ }
+ return false;
+ }
+ }
+
+ /* match on subject public key */
+ if (subjectPublicKeyBytes != null) {
+ byte[] certKey = xcert.getPublicKey().getEncoded();
+ if (!Arrays.equals(subjectPublicKeyBytes, certKey)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "subject public keys don't match");
+ }
+ return false;
+ }
+ }
+
+ boolean result = matchBasicConstraints(xcert)
+ && matchKeyUsage(xcert)
+ && matchExtendedKeyUsage(xcert)
+ && matchSubjectKeyID(xcert)
+ && matchAuthorityKeyID(xcert)
+ && matchPrivateKeyValid(xcert)
+ && matchSubjectPublicKeyAlgID(xcert)
+ && matchPolicy(xcert)
+ && matchSubjectAlternativeNames(xcert)
+ && matchPathToNames(xcert)
+ && matchNameConstraints(xcert);
+
+ if (result && (debug != null)) {
+ debug.println("X509CertSelector.match returning: true");
+ }
+ return result;
+ }
+
+ /* match on subject key identifier extension value */
+ private boolean matchSubjectKeyID(X509Certificate xcert) {
+ if (subjectKeyID == null) {
+ return true;
+ }
+ try {
+ byte[] extVal = xcert.getExtensionValue("2.5.29.14");
+ if (extVal == null) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "no subject key ID extension");
+ }
+ return false;
+ }
+ DerInputStream in = new DerInputStream(extVal);
+ byte[] certSubjectKeyID = in.getOctetString();
+ if (certSubjectKeyID == null ||
+ !Arrays.equals(subjectKeyID, certSubjectKeyID)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "subject key IDs don't match");
+ }
+ return false;
+ }
+ } catch (IOException ex) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "exception in subject key ID check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on authority key identifier extension value */
+ private boolean matchAuthorityKeyID(X509Certificate xcert) {
+ if (authorityKeyID == null) {
+ return true;
+ }
+ try {
+ byte[] extVal = xcert.getExtensionValue("2.5.29.35");
+ if (extVal == null) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "no authority key ID extension");
+ }
+ return false;
+ }
+ DerInputStream in = new DerInputStream(extVal);
+ byte[] certAuthKeyID = in.getOctetString();
+ if (certAuthKeyID == null ||
+ !Arrays.equals(authorityKeyID, certAuthKeyID)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "authority key IDs don't match");
+ }
+ return false;
+ }
+ } catch (IOException ex) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "exception in authority key ID check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on private key usage range */
+ private boolean matchPrivateKeyValid(X509Certificate xcert) {
+ if (privateKeyValid == null) {
+ return true;
+ }
+ PrivateKeyUsageExtension ext = null;
+ try {
+ ext = (PrivateKeyUsageExtension)
+ getExtensionObject(xcert, PRIVATE_KEY_USAGE_ID);
+ if (ext != null) {
+ ext.valid(privateKeyValid);
+ }
+ } catch (CertificateExpiredException e1) {
+ if (debug != null) {
+ String time = "n/a";
+ try {
+ Date notAfter = ext.get(PrivateKeyUsageExtension.NOT_AFTER);
+ time = notAfter.toString();
+ } catch (CertificateException ex) {
+ // not able to retrieve notAfter value
+ }
+ debug.println("X509CertSelector.match: private key usage not "
+ + "within validity date; ext.NOT_After: "
+ + time + "; X509CertSelector: "
+ + this.toString());
+ e1.printStackTrace();
+ }
+ return false;
+ } catch (CertificateNotYetValidException e2) {
+ if (debug != null) {
+ String time = "n/a";
+ try {
+ Date notBefore = ext.get(PrivateKeyUsageExtension.NOT_BEFORE);
+ time = notBefore.toString();
+ } catch (CertificateException ex) {
+ // not able to retrieve notBefore value
+ }
+ debug.println("X509CertSelector.match: private key usage not "
+ + "within validity date; ext.NOT_BEFORE: "
+ + time + "; X509CertSelector: "
+ + this.toString());
+ e2.printStackTrace();
+ }
+ return false;
+ } catch (IOException e4) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: IOException in "
+ + "private key usage check; X509CertSelector: "
+ + this.toString());
+ e4.printStackTrace();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on subject public key algorithm OID */
+ private boolean matchSubjectPublicKeyAlgID(X509Certificate xcert) {
+ if (subjectPublicKeyAlgID == null) {
+ return true;
+ }
+ try {
+ byte[] encodedKey = xcert.getPublicKey().getEncoded();
+ DerValue val = new DerValue(encodedKey);
+ if (val.tag != DerValue.tag_Sequence) {
+ throw new IOException("invalid key format");
+ }
+
+ AlgorithmId algID = AlgorithmId.parse(val.data.getDerValue());
+ if (debug != null) {
+ debug.println("X509CertSelector.match: subjectPublicKeyAlgID = "
+ + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = "
+ + algID.getOID());
+ }
+ if (!subjectPublicKeyAlgID.equals((Object)algID.getOID())) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "subject public key alg IDs don't match");
+ }
+ return false;
+ }
+ } catch (IOException e5) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: IOException in subject "
+ + "public key algorithm OID check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on key usage extension value */
+ private boolean matchKeyUsage(X509Certificate xcert) {
+ if (keyUsage == null) {
+ return true;
+ }
+ boolean[] certKeyUsage = xcert.getKeyUsage();
+ if (certKeyUsage != null) {
+ for (int keyBit = 0; keyBit < keyUsage.length; keyBit++) {
+ if (keyUsage[keyBit] &&
+ ((keyBit >= certKeyUsage.length) || !certKeyUsage[keyBit])) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "key usage bits don't match");
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /* match on extended key usage purpose OIDs */
+ private boolean matchExtendedKeyUsage(X509Certificate xcert) {
+ if ((keyPurposeSet == null) || keyPurposeSet.isEmpty()) {
+ return true;
+ }
+ try {
+ ExtendedKeyUsageExtension ext =
+ (ExtendedKeyUsageExtension)getExtensionObject(xcert,
+ EXTENDED_KEY_USAGE_ID);
+ if (ext != null) {
+ Vector<ObjectIdentifier> certKeyPurposeVector =
+ ext.get(ExtendedKeyUsageExtension.USAGES);
+ if (!certKeyPurposeVector.contains(ANY_EXTENDED_KEY_USAGE)
+ && !certKeyPurposeVector.containsAll(keyPurposeOIDSet)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: cert failed "
+ + "extendedKeyUsage criterion");
+ }
+ return false;
+ }
+ }
+ } catch (IOException ex) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "IOException in extended key usage check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on subject alternative name extension names */
+ private boolean matchSubjectAlternativeNames(X509Certificate xcert) {
+ if ((subjectAlternativeNames == null) || subjectAlternativeNames.isEmpty()) {
+ return true;
+ }
+ try {
+ SubjectAlternativeNameExtension sanExt =
+ (SubjectAlternativeNameExtension) getExtensionObject(xcert,
+ SUBJECT_ALT_NAME_ID);
+ if (sanExt == null) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "no subject alternative name extension");
+ }
+ return false;
+ }
+ GeneralNames certNames =
+ sanExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+ Iterator<GeneralNameInterface> i =
+ subjectAlternativeGeneralNames.iterator();
+ while (i.hasNext()) {
+ GeneralNameInterface matchName = i.next();
+ boolean found = false;
+ for (Iterator<GeneralName> t = certNames.iterator();
+ t.hasNext() && !found; ) {
+ GeneralNameInterface certName = (t.next()).getName();
+ found = certName.equals(matchName);
+ }
+ if (!found && (matchAllSubjectAltNames || !i.hasNext())) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: subject alternative "
+ + "name " + matchName + " not found");
+ }
+ return false;
+ } else if (found && !matchAllSubjectAltNames) {
+ break;
+ }
+ }
+ } catch (IOException ex) {
+ if (debug != null)
+ debug.println("X509CertSelector.match: IOException in subject "
+ + "alternative name check");
+ return false;
+ }
+ return true;
+ }
+
+ /* match on name constraints */
+ private boolean matchNameConstraints(X509Certificate xcert) {
+ if (nc == null) {
+ return true;
+ }
+ try {
+ if (!nc.verify(xcert)) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "name constraints not satisfied");
+ }
+ return false;
+ }
+ } catch (IOException e) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "IOException in name constraints check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on policy OIDs */
+ private boolean matchPolicy(X509Certificate xcert) {
+ if (policy == null) {
+ return true;
+ }
+ try {
+ CertificatePoliciesExtension ext = (CertificatePoliciesExtension)
+ getExtensionObject(xcert, CERT_POLICIES_ID);
+ if (ext == null) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "no certificate policy extension");
+ }
+ return false;
+ }
+ List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);
+ /*
+ * Convert the Vector of PolicyInformation to a Vector
+ * of CertificatePolicyIds for easier comparison.
+ */
+ List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
+ for (PolicyInformation info : policies) {
+ policyIDs.add(info.getPolicyIdentifier());
+ }
+ if (policy != null) {
+ boolean foundOne = false;
+ /*
+ * if the user passes in an empty policy Set, then
+ * we just want to make sure that the candidate certificate
+ * has some policy OID in its CertPoliciesExtension
+ */
+ if (policy.getCertPolicyIds().isEmpty()) {
+ if (policyIDs.isEmpty()) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "cert failed policyAny criterion");
+ }
+ return false;
+ }
+ } else {
+ for (CertificatePolicyId id : policy.getCertPolicyIds()) {
+ if (policyIDs.contains(id)) {
+ foundOne = true;
+ break;
+ }
+ }
+ if (!foundOne) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "cert failed policyAny criterion");
+ }
+ return false;
+ }
+ }
+ }
+ } catch (IOException ex) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "IOException in certificate policy ID check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /* match on pathToNames */
+ private boolean matchPathToNames(X509Certificate xcert) {
+ if (pathToGeneralNames == null) {
+ return true;
+ }
+ try {
+ NameConstraintsExtension ext = (NameConstraintsExtension)
+ getExtensionObject(xcert, NAME_CONSTRAINTS_ID);
+ if (ext == null) {
+ return true;
+ }
+ if ((debug != null) && Debug.isOn("certpath")) {
+ debug.println("X509CertSelector.match pathToNames:\n");
+ Iterator<GeneralNameInterface> i =
+ pathToGeneralNames.iterator();
+ while (i.hasNext()) {
+ debug.println(" " + i.next() + "\n");
+ }
+ }
+
+ GeneralSubtrees permitted =
+ ext.get(NameConstraintsExtension.PERMITTED_SUBTREES);
+ GeneralSubtrees excluded =
+ ext.get(NameConstraintsExtension.EXCLUDED_SUBTREES);
+ if (excluded != null) {
+ if (matchExcluded(excluded) == false) {
+ return false;
+ }
+ }
+ if (permitted != null) {
+ if (matchPermitted(permitted) == false) {
+ return false;
+ }
+ }
+ } catch (IOException ex) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: "
+ + "IOException in name constraints check");
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private boolean matchExcluded(GeneralSubtrees excluded) {
+ /*
+ * Enumerate through excluded and compare each entry
+ * to all pathToNames. If any pathToName is within any of the
+ * subtrees listed in excluded, return false.
+ */
+ for (Iterator<GeneralSubtree> t = excluded.iterator(); t.hasNext(); ) {
+ GeneralSubtree tree = t.next();
+ GeneralNameInterface excludedName = tree.getName().getName();
+ Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator();
+ while (i.hasNext()) {
+ GeneralNameInterface pathToName = i.next();
+ if (excludedName.getType() == pathToName.getType()) {
+ switch (pathToName.constrains(excludedName)) {
+ case GeneralNameInterface.NAME_WIDENS:
+ case GeneralNameInterface.NAME_MATCH:
+ if (debug != null) {
+ debug.println("X509CertSelector.match: name constraints "
+ + "inhibit path to specified name");
+ debug.println("X509CertSelector.match: excluded name: " +
+ pathToName);
+ }
+ return false;
+ default:
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean matchPermitted(GeneralSubtrees permitted) {
+ /*
+ * Enumerate through pathToNames, checking that each pathToName
+ * is in at least one of the subtrees listed in permitted.
+ * If not, return false. However, if no subtrees of a given type
+ * are listed, all names of that type are permitted.
+ */
+ Iterator<GeneralNameInterface> i = pathToGeneralNames.iterator();
+ while (i.hasNext()) {
+ GeneralNameInterface pathToName = i.next();
+ Iterator<GeneralSubtree> t = permitted.iterator();
+ boolean permittedNameFound = false;
+ boolean nameTypeFound = false;
+ String names = "";
+ while (t.hasNext() && !permittedNameFound) {
+ GeneralSubtree tree = t.next();
+ GeneralNameInterface permittedName = tree.getName().getName();
+ if (permittedName.getType() == pathToName.getType()) {
+ nameTypeFound = true;
+ names = names + " " + permittedName;
+ switch (pathToName.constrains(permittedName)) {
+ case GeneralNameInterface.NAME_WIDENS:
+ case GeneralNameInterface.NAME_MATCH:
+ permittedNameFound = true;
+ break;
+ default:
+ }
+ }
+ }
+ if (!permittedNameFound && nameTypeFound) {
+ if (debug != null)
+ debug.println("X509CertSelector.match: " +
+ "name constraints inhibit path to specified name; " +
+ "permitted names of type " + pathToName.getType() +
+ ": " + names);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* match on basic constraints */
+ private boolean matchBasicConstraints(X509Certificate xcert) {
+ if (basicConstraints == -1) {
+ return true;
+ }
+ int maxPathLen = xcert.getBasicConstraints();
+ if (basicConstraints == -2) {
+ if (maxPathLen != -1) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: not an EE cert");
+ }
+ return false;
+ }
+ } else {
+ if (maxPathLen < basicConstraints) {
+ if (debug != null) {
+ debug.println("X509CertSelector.match: cert's maxPathLen " +
+ "is less than the min maxPathLen set by " +
+ "basicConstraints. " +
+ "(" + maxPathLen + " < " + basicConstraints + ")");
+ }
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
+ private static <T> Set<T> cloneSet(Set<T> set) {
+ if (set instanceof HashSet) {
+ Object clone = ((HashSet<T>)set).clone();
+ return (Set<T>)clone;
+ } else {
+ return new HashSet<T>(set);
+ }
+ }
+
+ /**
+ * Returns a copy of this object.
+ *
+ * @return the copy
+ */
+ public Object clone() {
+ try {
+ X509CertSelector copy = (X509CertSelector)super.clone();
+ // Must clone these because addPathToName et al. modify them
+ if (subjectAlternativeNames != null) {
+ copy.subjectAlternativeNames =
+ cloneSet(subjectAlternativeNames);
+ copy.subjectAlternativeGeneralNames =
+ cloneSet(subjectAlternativeGeneralNames);
+ }
+ if (pathToGeneralNames != null) {
+ copy.pathToNames = cloneSet(pathToNames);
+ copy.pathToGeneralNames = cloneSet(pathToGeneralNames);
+ }
+ return copy;
+ } catch (CloneNotSupportedException e) {
+ /* Cannot happen */
+ throw new InternalError(e.toString(), e);
+ }
+ }
+}
diff --git a/java/security/cert/X509Certificate.java b/java/security/cert/X509Certificate.java
new file mode 100644
index 0000000..042eefd
--- /dev/null
+++ b/java/security/cert/X509Certificate.java
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.math.BigInteger;
+import java.security.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * <p>
+ * Abstract class for X.509 certificates. This provides a standard
+ * way to access all the attributes of an X.509 certificate.
+ * <p>
+ * In June of 1996, the basic X.509 v3 format was completed by
+ * ISO/IEC and ANSI X9, which is described below in ASN.1:
+ * <pre>
+ * Certificate ::= SEQUENCE {
+ * tbsCertificate TBSCertificate,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING }
+ * </pre>
+ * <p>
+ * These certificates are widely used to support authentication and
+ * other functionality in Internet security systems. Common applications
+ * include Privacy Enhanced Mail (PEM), Transport Layer Security (SSL),
+ * code signing for trusted software distribution, and Secure Electronic
+ * Transactions (SET).
+ * <p>
+ * These certificates are managed and vouched for by <em>Certificate
+ * Authorities</em> (CAs). CAs are services which create certificates by
+ * placing data in the X.509 standard format and then digitally signing
+ * that data. CAs act as trusted third parties, making introductions
+ * between principals who have no direct knowledge of each other.
+ * CA certificates are either signed by themselves, or by some other
+ * CA such as a "root" CA.
+ * <p>
+ * More information can be found in
+ * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * Public Key Infrastructure Certificate and CRL Profile</a>.
+ * <p>
+ * The ASN.1 definition of {@code tbsCertificate} is:
+ * <pre>
+ * TBSCertificate ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * serialNumber CertificateSerialNumber,
+ * signature AlgorithmIdentifier,
+ * issuer Name,
+ * validity Validity,
+ * subject Name,
+ * subjectPublicKeyInfo SubjectPublicKeyInfo,
+ * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version must be v2 or v3
+ * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ * -- If present, version must be v2 or v3
+ * extensions [3] EXPLICIT Extensions OPTIONAL
+ * -- If present, version must be v3
+ * }
+ * </pre>
+ * <p>
+ * Certificates are instantiated using a certificate factory. The following is
+ * an example of how to instantiate an X.509 certificate:
+ * <pre>
+ * try (InputStream inStream = new FileInputStream("fileName-of-cert")) {
+ * CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ * X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
+ * }
+ * </pre>
+ *
+ * @author Hemma Prafullchandra
+ *
+ *
+ * @see Certificate
+ * @see CertificateFactory
+ * @see X509Extension
+ */
+
+public abstract class X509Certificate extends Certificate
+implements X509Extension {
+
+ private static final long serialVersionUID = -2491127588187038216L;
+
+ private transient X500Principal subjectX500Principal, issuerX500Principal;
+
+ /**
+ * Constructor for X.509 certificates.
+ */
+ protected X509Certificate() {
+ super("X.509");
+ }
+
+ /**
+ * Checks that the certificate is currently valid. It is if
+ * the current date and time are within the validity period given in the
+ * certificate.
+ * <p>
+ * The validity period consists of two date/time values:
+ * the first and last dates (and times) on which the certificate
+ * is valid. It is defined in
+ * ASN.1 as:
+ * <pre>
+ * validity Validity
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore CertificateValidityDate,
+ * notAfter CertificateValidityDate }
+ *
+ * CertificateValidityDate ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ *
+ * @exception CertificateExpiredException if the certificate has expired.
+ * @exception CertificateNotYetValidException if the certificate is not
+ * yet valid.
+ */
+ public abstract void checkValidity()
+ throws CertificateExpiredException, CertificateNotYetValidException;
+
+ /**
+ * Checks that the given date is within the certificate's
+ * validity period. In other words, this determines whether the
+ * certificate would be valid at the given date/time.
+ *
+ * @param date the Date to check against to see if this certificate
+ * is valid at that date/time.
+ *
+ * @exception CertificateExpiredException if the certificate has expired
+ * with respect to the {@code date} supplied.
+ * @exception CertificateNotYetValidException if the certificate is not
+ * yet valid with respect to the {@code date} supplied.
+ *
+ * @see #checkValidity()
+ */
+ public abstract void checkValidity(Date date)
+ throws CertificateExpiredException, CertificateNotYetValidException;
+
+ /**
+ * Gets the {@code version} (version number) value from the
+ * certificate.
+ * The ASN.1 definition for this is:
+ * <pre>
+ * version [0] EXPLICIT Version DEFAULT v1
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ * </pre>
+ * @return the version number, i.e. 1, 2 or 3.
+ */
+ public abstract int getVersion();
+
+ /**
+ * Gets the {@code serialNumber} value from the certificate.
+ * The serial number is an integer assigned by the certification
+ * authority to each certificate. It must be unique for each
+ * certificate issued by a given CA (i.e., the issuer name and
+ * serial number identify a unique certificate).
+ * The ASN.1 definition for this is:
+ * <pre>
+ * serialNumber CertificateSerialNumber
+ *
+ * CertificateSerialNumber ::= INTEGER
+ * </pre>
+ *
+ * @return the serial number.
+ */
+ public abstract BigInteger getSerialNumber();
+
+ /**
+ * <strong>Denigrated</strong>, replaced by {@linkplain
+ * #getIssuerX500Principal()}. This method returns the {@code issuer}
+ * as an implementation specific Principal object, which should not be
+ * relied upon by portable code.
+ *
+ * <p>
+ * Gets the {@code issuer} (issuer distinguished name) value from
+ * the certificate. The issuer name identifies the entity that signed (and
+ * issued) the certificate.
+ *
+ * <p>The issuer name field contains an
+ * X.500 distinguished name (DN).
+ * The ASN.1 definition for this is:
+ * <pre>
+ * issuer Name
+ *
+ * Name ::= CHOICE { RDNSequence }
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ * RelativeDistinguishedName ::=
+ * SET OF AttributeValueAssertion
+ *
+ * AttributeValueAssertion ::= SEQUENCE {
+ * AttributeType,
+ * AttributeValue }
+ * AttributeType ::= OBJECT IDENTIFIER
+ * AttributeValue ::= ANY
+ * </pre>
+ * The {@code Name} describes a hierarchical name composed of
+ * attributes,
+ * such as country name, and corresponding values, such as US.
+ * The type of the {@code AttributeValue} component is determined by
+ * the {@code AttributeType}; in general it will be a
+ * {@code directoryString}. A {@code directoryString} is usually
+ * one of {@code PrintableString},
+ * {@code TeletexString} or {@code UniversalString}.
+ *
+ * @return a Principal whose name is the issuer distinguished name.
+ */
+ public abstract Principal getIssuerDN();
+
+ /**
+ * Returns the issuer (issuer distinguished name) value from the
+ * certificate as an {@code X500Principal}.
+ * <p>
+ * It is recommended that subclasses override this method.
+ *
+ * @return an {@code X500Principal} representing the issuer
+ * distinguished name
+ * @since 1.4
+ */
+ public X500Principal getIssuerX500Principal() {
+ if (issuerX500Principal == null) {
+ issuerX500Principal = X509CertImpl.getIssuerX500Principal(this);
+ }
+ return issuerX500Principal;
+ }
+
+ /**
+ * <strong>Denigrated</strong>, replaced by {@linkplain
+ * #getSubjectX500Principal()}. This method returns the {@code subject}
+ * as an implementation specific Principal object, which should not be
+ * relied upon by portable code.
+ *
+ * <p>
+ * Gets the {@code subject} (subject distinguished name) value
+ * from the certificate. If the {@code subject} value is empty,
+ * then the {@code getName()} method of the returned
+ * {@code Principal} object returns an empty string ("").
+ *
+ * <p> The ASN.1 definition for this is:
+ * <pre>
+ * subject Name
+ * </pre>
+ *
+ * <p>See {@link #getIssuerDN() getIssuerDN} for {@code Name}
+ * and other relevant definitions.
+ *
+ * @return a Principal whose name is the subject name.
+ */
+ public abstract Principal getSubjectDN();
+
+ /**
+ * Returns the subject (subject distinguished name) value from the
+ * certificate as an {@code X500Principal}. If the subject value
+ * is empty, then the {@code getName()} method of the returned
+ * {@code X500Principal} object returns an empty string ("").
+ * <p>
+ * It is recommended that subclasses override this method.
+ *
+ * @return an {@code X500Principal} representing the subject
+ * distinguished name
+ * @since 1.4
+ */
+ public X500Principal getSubjectX500Principal() {
+ if (subjectX500Principal == null) {
+ subjectX500Principal = X509CertImpl.getSubjectX500Principal(this);
+ }
+ return subjectX500Principal;
+ }
+
+ /**
+ * Gets the {@code notBefore} date from the validity period of
+ * the certificate.
+ * The relevant ASN.1 definitions are:
+ * <pre>
+ * validity Validity
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore CertificateValidityDate,
+ * notAfter CertificateValidityDate }
+ *
+ * CertificateValidityDate ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ * </pre>
+ *
+ * @return the start date of the validity period.
+ * @see #checkValidity
+ */
+ public abstract Date getNotBefore();
+
+ /**
+ * Gets the {@code notAfter} date from the validity period of
+ * the certificate. See {@link #getNotBefore() getNotBefore}
+ * for relevant ASN.1 definitions.
+ *
+ * @return the end date of the validity period.
+ * @see #checkValidity
+ */
+ public abstract Date getNotAfter();
+
+ /**
+ * Gets the DER-encoded certificate information, the
+ * {@code tbsCertificate} from this certificate.
+ * This can be used to verify the signature independently.
+ *
+ * @return the DER-encoded certificate information.
+ * @exception CertificateEncodingException if an encoding error occurs.
+ */
+ public abstract byte[] getTBSCertificate()
+ throws CertificateEncodingException;
+
+ /**
+ * Gets the {@code signature} value (the raw signature bits) from
+ * the certificate.
+ * The ASN.1 definition for this is:
+ * <pre>
+ * signature BIT STRING
+ * </pre>
+ *
+ * @return the signature.
+ */
+ public abstract byte[] getSignature();
+
+ /**
+ * Gets the signature algorithm name for the certificate
+ * signature algorithm. An example is the string "SHA256withRSA".
+ * The ASN.1 definition for this is:
+ * <pre>
+ * signatureAlgorithm AlgorithmIdentifier
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ * -- contains a value of the type
+ * -- registered for use with the
+ * -- algorithm object identifier value
+ * </pre>
+ *
+ * <p>The algorithm name is determined from the {@code algorithm}
+ * OID string.
+ *
+ * @return the signature algorithm name.
+ */
+ public abstract String getSigAlgName();
+
+ /**
+ * Gets the signature algorithm OID string from the certificate.
+ * An OID is represented by a set of nonnegative whole numbers separated
+ * by periods.
+ * For example, the string "1.2.840.10040.4.3" identifies the SHA-1
+ * with DSA signature algorithm defined in
+ * <a href="http://www.ietf.org/rfc/rfc3279.txt">RFC 3279: Algorithms and
+ * Identifiers for the Internet X.509 Public Key Infrastructure Certificate
+ * and CRL Profile</a>.
+ *
+ * <p>See {@link #getSigAlgName() getSigAlgName} for
+ * relevant ASN.1 definitions.
+ *
+ * @return the signature algorithm OID string.
+ */
+ public abstract String getSigAlgOID();
+
+ /**
+ * Gets the DER-encoded signature algorithm parameters from this
+ * certificate's signature algorithm. In most cases, the signature
+ * algorithm parameters are null; the parameters are usually
+ * supplied with the certificate's public key.
+ * If access to individual parameter values is needed then use
+ * {@link java.security.AlgorithmParameters AlgorithmParameters}
+ * and instantiate with the name returned by
+ * {@link #getSigAlgName() getSigAlgName}.
+ *
+ * <p>See {@link #getSigAlgName() getSigAlgName} for
+ * relevant ASN.1 definitions.
+ *
+ * @return the DER-encoded signature algorithm parameters, or
+ * null if no parameters are present.
+ */
+ public abstract byte[] getSigAlgParams();
+
+ /**
+ * Gets the {@code issuerUniqueID} value from the certificate.
+ * The issuer unique identifier is present in the certificate
+ * to handle the possibility of reuse of issuer names over time.
+ * RFC 3280 recommends that names not be reused and that
+ * conforming certificates not make use of unique identifiers.
+ * Applications conforming to that profile should be capable of
+ * parsing unique identifiers and making comparisons.
+ *
+ * <p>The ASN.1 definition for this is:
+ * <pre>
+ * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL
+ *
+ * UniqueIdentifier ::= BIT STRING
+ * </pre>
+ *
+ * @return the issuer unique identifier or null if it is not
+ * present in the certificate.
+ */
+ public abstract boolean[] getIssuerUniqueID();
+
+ /**
+ * Gets the {@code subjectUniqueID} value from the certificate.
+ *
+ * <p>The ASN.1 definition for this is:
+ * <pre>
+ * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL
+ *
+ * UniqueIdentifier ::= BIT STRING
+ * </pre>
+ *
+ * @return the subject unique identifier or null if it is not
+ * present in the certificate.
+ */
+ public abstract boolean[] getSubjectUniqueID();
+
+ /**
+ * Gets a boolean array representing bits of
+ * the {@code KeyUsage} extension, (OID = 2.5.29.15).
+ * The key usage extension defines the purpose (e.g., encipherment,
+ * signature, certificate signing) of the key contained in the
+ * certificate.
+ * The ASN.1 definition for this is:
+ * <pre>
+ * KeyUsage ::= BIT STRING {
+ * digitalSignature (0),
+ * nonRepudiation (1),
+ * keyEncipherment (2),
+ * dataEncipherment (3),
+ * keyAgreement (4),
+ * keyCertSign (5),
+ * cRLSign (6),
+ * encipherOnly (7),
+ * decipherOnly (8) }
+ * </pre>
+ * RFC 3280 recommends that when used, this be marked
+ * as a critical extension.
+ *
+ * @return the KeyUsage extension of this certificate, represented as
+ * an array of booleans. The order of KeyUsage values in the array is
+ * the same as in the above ASN.1 definition. The array will contain a
+ * value for each KeyUsage defined above. If the KeyUsage list encoded
+ * in the certificate is longer than the above list, it will not be
+ * truncated. Returns null if this certificate does not
+ * contain a KeyUsage extension.
+ */
+ public abstract boolean[] getKeyUsage();
+
+ /**
+ * Gets an unmodifiable list of Strings representing the OBJECT
+ * IDENTIFIERs of the {@code ExtKeyUsageSyntax} field of the
+ * extended key usage extension, (OID = 2.5.29.37). It indicates
+ * one or more purposes for which the certified public key may be
+ * used, in addition to or in place of the basic purposes
+ * indicated in the key usage extension field. The ASN.1
+ * definition for this is:
+ * <pre>
+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ * </pre>
+ *
+ * Key purposes may be defined by any organization with a
+ * need. Object identifiers used to identify key purposes shall be
+ * assigned in accordance with IANA or ITU-T Rec. X.660 |
+ * ISO/IEC/ITU 9834-1.
+ * <p>
+ * This method was added to version 1.4 of the Java 2 Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method is not {@code abstract}
+ * and it provides a default implementation. Subclasses
+ * should override this method with a correct implementation.
+ *
+ * @return the ExtendedKeyUsage extension of this certificate,
+ * as an unmodifiable list of object identifiers represented
+ * as Strings. Returns null if this certificate does not
+ * contain an ExtendedKeyUsage extension.
+ * @throws CertificateParsingException if the extension cannot be decoded
+ * @since 1.4
+ */
+ public List<String> getExtendedKeyUsage() throws CertificateParsingException {
+ return X509CertImpl.getExtendedKeyUsage(this);
+ }
+
+ /**
+ * Gets the certificate constraints path length from the
+ * critical {@code BasicConstraints} extension, (OID = 2.5.29.19).
+ * <p>
+ * The basic constraints extension identifies whether the subject
+ * of the certificate is a Certificate Authority (CA) and
+ * how deep a certification path may exist through that CA. The
+ * {@code pathLenConstraint} field (see below) is meaningful
+ * only if {@code cA} is set to TRUE. In this case, it gives the
+ * maximum number of CA certificates that may follow this certificate in a
+ * certification path. A value of zero indicates that only an end-entity
+ * certificate may follow in the path.
+ * <p>
+ * The ASN.1 definition for this is:
+ * <pre>
+ * BasicConstraints ::= SEQUENCE {
+ * cA BOOLEAN DEFAULT FALSE,
+ * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+ * </pre>
+ *
+ * @return the value of {@code pathLenConstraint} if the
+ * BasicConstraints extension is present in the certificate and the
+ * subject of the certificate is a CA, otherwise -1.
+ * If the subject of the certificate is a CA and
+ * {@code pathLenConstraint} does not appear,
+ * {@code Integer.MAX_VALUE} is returned to indicate that there is no
+ * limit to the allowed length of the certification path.
+ */
+ public abstract int getBasicConstraints();
+
+ /**
+ * Gets an immutable collection of subject alternative names from the
+ * {@code SubjectAltName} extension, (OID = 2.5.29.17).
+ * <p>
+ * The ASN.1 definition of the {@code SubjectAltName} extension is:
+ * <pre>
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames :: = SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ * otherName [0] OtherName,
+ * rfc822Name [1] IA5String,
+ * dNSName [2] IA5String,
+ * x400Address [3] ORAddress,
+ * directoryName [4] Name,
+ * ediPartyName [5] EDIPartyName,
+ * uniformResourceIdentifier [6] IA5String,
+ * iPAddress [7] OCTET STRING,
+ * registeredID [8] OBJECT IDENTIFIER}
+ * </pre>
+ * <p>
+ * If this certificate does not contain a {@code SubjectAltName}
+ * extension, {@code null} is returned. Otherwise, a
+ * {@code Collection} is returned with an entry representing each
+ * {@code GeneralName} included in the extension. Each entry is a
+ * {@code List} whose first entry is an {@code Integer}
+ * (the name type, 0-8) and whose second entry is a {@code String}
+ * or a byte array (the name, in string or ASN.1 DER encoded form,
+ * respectively).
+ * <p>
+ * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
+ * names are returned as {@code String}s,
+ * using the well-established string formats for those types (subject to
+ * the restrictions included in RFC 3280). IPv4 address names are
+ * returned using dotted quad notation. IPv6 address names are returned
+ * in the form "a1:a2:...:a8", where a1-a8 are hexadecimal values
+ * representing the eight 16-bit pieces of the address. OID names are
+ * returned as {@code String}s represented as a series of nonnegative
+ * integers separated by periods. And directory names (distinguished names)
+ * are returned in <a href="http://www.ietf.org/rfc/rfc2253.txt">
+ * RFC 2253</a> string format. No standard string format is
+ * defined for otherNames, X.400 names, EDI party names, or any
+ * other type of names. They are returned as byte arrays
+ * containing the ASN.1 DER encoded form of the name.
+ * <p>
+ * Note that the {@code Collection} returned may contain more
+ * than one name of the same type. Also, note that the returned
+ * {@code Collection} is immutable and any entries containing byte
+ * arrays are cloned to protect against subsequent modifications.
+ * <p>
+ * This method was added to version 1.4 of the Java 2 Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method is not {@code abstract}
+ * and it provides a default implementation. Subclasses
+ * should override this method with a correct implementation.
+ *
+ * @return an immutable {@code Collection} of subject alternative
+ * names (or {@code null})
+ * @throws CertificateParsingException if the extension cannot be decoded
+ * @since 1.4
+ */
+ public Collection<List<?>> getSubjectAlternativeNames()
+ throws CertificateParsingException {
+ return X509CertImpl.getSubjectAlternativeNames(this);
+ }
+
+ /**
+ * Gets an immutable collection of issuer alternative names from the
+ * {@code IssuerAltName} extension, (OID = 2.5.29.18).
+ * <p>
+ * The ASN.1 definition of the {@code IssuerAltName} extension is:
+ * <pre>
+ * IssuerAltName ::= GeneralNames
+ * </pre>
+ * The ASN.1 definition of {@code GeneralNames} is defined
+ * in {@link #getSubjectAlternativeNames getSubjectAlternativeNames}.
+ * <p>
+ * If this certificate does not contain an {@code IssuerAltName}
+ * extension, {@code null} is returned. Otherwise, a
+ * {@code Collection} is returned with an entry representing each
+ * {@code GeneralName} included in the extension. Each entry is a
+ * {@code List} whose first entry is an {@code Integer}
+ * (the name type, 0-8) and whose second entry is a {@code String}
+ * or a byte array (the name, in string or ASN.1 DER encoded form,
+ * respectively). For more details about the formats used for each
+ * name type, see the {@code getSubjectAlternativeNames} method.
+ * <p>
+ * Note that the {@code Collection} returned may contain more
+ * than one name of the same type. Also, note that the returned
+ * {@code Collection} is immutable and any entries containing byte
+ * arrays are cloned to protect against subsequent modifications.
+ * <p>
+ * This method was added to version 1.4 of the Java 2 Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method is not {@code abstract}
+ * and it provides a default implementation. Subclasses
+ * should override this method with a correct implementation.
+ *
+ * @return an immutable {@code Collection} of issuer alternative
+ * names (or {@code null})
+ * @throws CertificateParsingException if the extension cannot be decoded
+ * @since 1.4
+ */
+ public Collection<List<?>> getIssuerAlternativeNames()
+ throws CertificateParsingException {
+ return X509CertImpl.getIssuerAlternativeNames(this);
+ }
+
+ /**
+ * Verifies that this certificate was signed using the
+ * private key that corresponds to the specified public key.
+ * This method uses the signature verification engine
+ * supplied by the specified provider. Note that the specified
+ * Provider object does not have to be registered in the provider list.
+ *
+ * This method was added to version 1.8 of the Java Platform Standard
+ * Edition. In order to maintain backwards compatibility with existing
+ * service providers, this method is not {@code abstract}
+ * and it provides a default implementation.
+ *
+ * @param key the PublicKey used to carry out the verification.
+ * @param sigProvider the signature provider.
+ *
+ * @exception NoSuchAlgorithmException on unsupported signature
+ * algorithms.
+ * @exception InvalidKeyException on incorrect key.
+ * @exception SignatureException on signature errors.
+ * @exception CertificateException on encoding errors.
+ * @exception UnsupportedOperationException if the method is not supported
+ * @since 1.8
+ */
+ public void verify(PublicKey key, Provider sigProvider)
+ throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, SignatureException {
+ // Android-changed: Use Certificate default implementation that
+ // throws UnsupportedOperationException.
+ // The method X509CertImpl calls this method, thus entering an
+ // infinite loop. This strange behaviour was checked to be not
+ // specific to libcore by running a test with vogar --mode=jvm
+ //
+ // X509CertImpl.verify(this, key, sigProvider);
+ super.verify(key, sigProvider);
+ }
+}
diff --git a/java/security/cert/X509Extension.java b/java/security/cert/X509Extension.java
new file mode 100644
index 0000000..0346960
--- /dev/null
+++ b/java/security/cert/X509Extension.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.util.Set;
+
+/**
+ * Interface for an X.509 extension.
+ *
+ * <p>The extensions defined for X.509 v3
+ * {@link X509Certificate Certificates} and v2
+ * {@link X509CRL CRLs} (Certificate Revocation
+ * Lists) provide methods
+ * for associating additional attributes with users or public keys,
+ * for managing the certification hierarchy, and for managing CRL
+ * distribution. The X.509 extensions format also allows communities
+ * to define private extensions to carry information unique to those
+ * communities.
+ *
+ * <p>Each extension in a certificate/CRL may be designated as
+ * critical or non-critical. A certificate/CRL-using system (an application
+ * validating a certificate/CRL) must reject the certificate/CRL if it
+ * encounters a critical extension it does not recognize. A non-critical
+ * extension may be ignored if it is not recognized.
+ * <p>
+ * The ASN.1 definition for this is:
+ * <pre>
+ * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+ *
+ * Extension ::= SEQUENCE {
+ * extnId OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING
+ * -- contains a DER encoding of a value
+ * -- of the type registered for use with
+ * -- the extnId object identifier value
+ * }
+ * </pre>
+ * Since not all extensions are known, the {@code getExtensionValue}
+ * method returns the DER-encoded OCTET STRING of the
+ * extension value (i.e., the {@code extnValue}). This can then
+ * be handled by a <em>Class</em> that understands the extension.
+ *
+ * @author Hemma Prafullchandra
+ */
+
+public interface X509Extension {
+
+ /**
+ * Check if there is a critical extension that is not supported.
+ *
+ * @return {@code true} if a critical extension is found that is
+ * not supported, otherwise {@code false}.
+ */
+ public boolean hasUnsupportedCriticalExtension();
+
+ /**
+ * Gets a Set of the OID strings for the extension(s) marked
+ * CRITICAL in the certificate/CRL managed by the object
+ * implementing this interface.
+ *
+ * Here is sample code to get a Set of critical extensions from an
+ * X509Certificate and print the OIDs:
+ * <pre>{@code
+ * X509Certificate cert = null;
+ * try (InputStream inStrm = new FileInputStream("DER-encoded-Cert")) {
+ * CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ * cert = (X509Certificate)cf.generateCertificate(inStrm);
+ * }
+ *
+ * Set<String> critSet = cert.getCriticalExtensionOIDs();
+ * if (critSet != null && !critSet.isEmpty()) {
+ * System.out.println("Set of critical extensions:");
+ * for (String oid : critSet) {
+ * System.out.println(oid);
+ * }
+ * }
+ * }</pre>
+ * @return a Set (or an empty Set if none are marked critical) of
+ * the extension OID strings for extensions that are marked critical.
+ * If there are no extensions present at all, then this method returns
+ * null.
+ */
+ public Set<String> getCriticalExtensionOIDs();
+
+ /**
+ * Gets a Set of the OID strings for the extension(s) marked
+ * NON-CRITICAL in the certificate/CRL managed by the object
+ * implementing this interface.
+ *
+ * Here is sample code to get a Set of non-critical extensions from an
+ * X509CRL revoked certificate entry and print the OIDs:
+ * <pre>{@code
+ * CertificateFactory cf = null;
+ * X509CRL crl = null;
+ * try (InputStream inStrm = new FileInputStream("DER-encoded-CRL")) {
+ * cf = CertificateFactory.getInstance("X.509");
+ * crl = (X509CRL)cf.generateCRL(inStrm);
+ * }
+ *
+ * byte[] certData = <DER-encoded certificate data>
+ * ByteArrayInputStream bais = new ByteArrayInputStream(certData);
+ * X509Certificate cert = (X509Certificate)cf.generateCertificate(bais);
+ * X509CRLEntry badCert =
+ * crl.getRevokedCertificate(cert.getSerialNumber());
+ *
+ * if (badCert != null) {
+ * Set<String> nonCritSet = badCert.getNonCriticalExtensionOIDs();
+ * if (nonCritSet != null)
+ * for (String oid : nonCritSet) {
+ * System.out.println(oid);
+ * }
+ * }
+ * }</pre>
+ *
+ * @return a Set (or an empty Set if none are marked non-critical) of
+ * the extension OID strings for extensions that are marked non-critical.
+ * If there are no extensions present at all, then this method returns
+ * null.
+ */
+ public Set<String> getNonCriticalExtensionOIDs();
+
+ /**
+ * Gets the DER-encoded OCTET string for the extension value
+ * (<em>extnValue</em>) identified by the passed-in {@code oid}
+ * String.
+ * The {@code oid} string is
+ * represented by a set of nonnegative whole numbers separated
+ * by periods.
+ *
+ * <p>For example:<br>
+ * <table border=groove summary="Examples of OIDs and extension names">
+ * <tr>
+ * <th>OID <em>(Object Identifier)</em></th>
+ * <th>Extension Name</th></tr>
+ * <tr><td>2.5.29.14</td>
+ * <td>SubjectKeyIdentifier</td></tr>
+ * <tr><td>2.5.29.15</td>
+ * <td>KeyUsage</td></tr>
+ * <tr><td>2.5.29.16</td>
+ * <td>PrivateKeyUsage</td></tr>
+ * <tr><td>2.5.29.17</td>
+ * <td>SubjectAlternativeName</td></tr>
+ * <tr><td>2.5.29.18</td>
+ * <td>IssuerAlternativeName</td></tr>
+ * <tr><td>2.5.29.19</td>
+ * <td>BasicConstraints</td></tr>
+ * <tr><td>2.5.29.30</td>
+ * <td>NameConstraints</td></tr>
+ * <tr><td>2.5.29.33</td>
+ * <td>PolicyMappings</td></tr>
+ * <tr><td>2.5.29.35</td>
+ * <td>AuthorityKeyIdentifier</td></tr>
+ * <tr><td>2.5.29.36</td>
+ * <td>PolicyConstraints</td></tr>
+ * </table>
+ *
+ * @param oid the Object Identifier value for the extension.
+ * @return the DER-encoded octet string of the extension value or
+ * null if it is not present.
+ */
+ public byte[] getExtensionValue(String oid);
+}
diff --git a/java/security/cert/package-info.java b/java/security/cert/package-info.java
new file mode 100644
index 0000000..0ef896b
--- /dev/null
+++ b/java/security/cert/package-info.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides classes and interfaces for parsing and managing
+ * certificates, certificate revocation lists (CRLs), and
+ * certification paths. It contains support for X.509 v3
+ * certificates and X.509 v2 CRLs.
+ *
+ * <h2>Package Specification</h2>
+ *
+ * <ul>
+ * <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * <b>Java™
+ * Cryptography Architecture (JCA) Reference Guide</b></a>
+ * <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and
+ * Certificate Revocation List (CRL) Profile
+ * <li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate
+ * Status Protocol - OCSP
+ * <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html">
+ * <b>Java™
+ * Cryptography Architecture Standard Algorithm Name
+ * Documentation</b></a></li>
+ * </ul>
+ *
+ * <h2>Related Documentation</h2>
+ *
+ * For information about X.509 certificates and CRLs, please see:
+ * <ul>
+ * <li><a href="http://www.ietf.org/rfc/rfc5280.txt">
+ * http://www.ietf.org/rfc/rfc5280.txt</a>
+ * <li><a href=
+ * "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
+ * <b>Java™
+ * PKI Programmer's Guide</b></a>
+ * <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/cert3.html">
+ * <b>X.509 Certificates and Certificate Revocation Lists (CRLs)</b></a>
+ * </ul>
+ *
+ * @since 1.2
+ */
+package java.security.cert;
diff --git a/java/security/interfaces/DSAKey.java b/java/security/interfaces/DSAKey.java
new file mode 100644
index 0000000..d78b3e1
--- /dev/null
+++ b/java/security/interfaces/DSAKey.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1996, 1998, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+/**
+ * The interface to a DSA public or private key. DSA (Digital Signature
+ * Algorithm) is defined in NIST's FIPS-186.
+ *
+ * @see DSAParams
+ * @see java.security.Key
+ * @see java.security.Signature
+ *
+ * @author Benjamin Renaud
+ * @author Josh Bloch
+ */
+public interface DSAKey {
+
+ /**
+ * Returns the DSA-specific key parameters. These parameters are
+ * never secret.
+ *
+ * @return the DSA-specific key parameters.
+ *
+ * @see DSAParams
+ */
+ public DSAParams getParams();
+}
diff --git a/java/security/interfaces/DSAKeyPairGenerator.java b/java/security/interfaces/DSAKeyPairGenerator.java
new file mode 100644
index 0000000..e50cfd2
--- /dev/null
+++ b/java/security/interfaces/DSAKeyPairGenerator.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.security.*;
+
+/**
+ * An interface to an object capable of generating DSA key pairs.
+ *
+ * <p>The {@code initialize} methods may each be called any number
+ * of times. If no {@code initialize} method is called on a
+ * DSAKeyPairGenerator, the default is to generate 1024-bit keys, using
+ * precomputed p, q and g parameters and an instance of SecureRandom as
+ * the random bit source.
+ *
+ * <p>Users wishing to indicate DSA-specific parameters, and to generate a key
+ * pair suitable for use with the DSA algorithm typically
+ *
+ * <ol>
+ *
+ * <li>Get a key pair generator for the DSA algorithm by calling the
+ * KeyPairGenerator {@code getInstance} method with "DSA"
+ * as its argument.
+ *
+ * <li>Initialize the generator by casting the result to a DSAKeyPairGenerator
+ * and calling one of the
+ * {@code initialize} methods from this DSAKeyPairGenerator interface.
+ *
+ * <li>Generate a key pair by calling the {@code generateKeyPair}
+ * method from the KeyPairGenerator class.
+ *
+ * </ol>
+ *
+ * <p>Note: it is not always necessary to do do algorithm-specific
+ * initialization for a DSA key pair generator. That is, it is not always
+ * necessary to call an {@code initialize} method in this interface.
+ * Algorithm-independent initialization using the {@code initialize} method
+ * in the KeyPairGenerator
+ * interface is all that is needed when you accept defaults for algorithm-specific
+ * parameters.
+ *
+ * <p>Note: Some earlier implementations of this interface may not support
+ * larger sizes of DSA parameters such as 2048 and 3072-bit.
+ *
+ * @see java.security.KeyPairGenerator
+ */
+public interface DSAKeyPairGenerator {
+
+ /**
+ * Initializes the key pair generator using the DSA family parameters
+ * (p,q and g) and an optional SecureRandom bit source. If a
+ * SecureRandom bit source is needed but not supplied, i.e. null, a
+ * default SecureRandom instance will be used.
+ *
+ * @param params the parameters to use to generate the keys.
+ *
+ * @param random the random bit source to use to generate key bits;
+ * can be null.
+ *
+ * @exception InvalidParameterException if the {@code params}
+ * value is invalid, null, or unsupported.
+ */
+ public void initialize(DSAParams params, SecureRandom random)
+ throws InvalidParameterException;
+
+ /**
+ * Initializes the key pair generator for a given modulus length
+ * (instead of parameters), and an optional SecureRandom bit source.
+ * If a SecureRandom bit source is needed but not supplied, i.e.
+ * null, a default SecureRandom instance will be used.
+ *
+ * <p>If {@code genParams} is true, this method generates new
+ * p, q and g parameters. If it is false, the method uses precomputed
+ * parameters for the modulus length requested. If there are no
+ * precomputed parameters for that modulus length, an exception will be
+ * thrown. It is guaranteed that there will always be
+ * default parameters for modulus lengths of 512 and 1024 bits.
+ *
+ * @param modlen the modulus length in bits. Valid values are any
+ * multiple of 64 between 512 and 1024, inclusive, 2048, and 3072.
+ *
+ * @param random the random bit source to use to generate key bits;
+ * can be null.
+ *
+ * @param genParams whether or not to generate new parameters for
+ * the modulus length requested.
+ *
+ * @exception InvalidParameterException if {@code modlen} is
+ * invalid, or unsupported, or if {@code genParams} is false and there
+ * are no precomputed parameters for the requested modulus length.
+ */
+ public void initialize(int modlen, boolean genParams, SecureRandom random)
+ throws InvalidParameterException;
+}
diff --git a/java/security/interfaces/DSAParams.java b/java/security/interfaces/DSAParams.java
new file mode 100644
index 0000000..8c46ed5
--- /dev/null
+++ b/java/security/interfaces/DSAParams.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * Interface to a DSA-specific set of key parameters, which defines a
+ * DSA <em>key family</em>. DSA (Digital Signature Algorithm) is defined
+ * in NIST's FIPS-186.
+ *
+ * @see DSAKey
+ * @see java.security.Key
+ * @see java.security.Signature
+ *
+ * @author Benjamin Renaud
+ * @author Josh Bloch
+ */
+public interface DSAParams {
+
+ /**
+ * Returns the prime, {@code p}.
+ *
+ * @return the prime, {@code p}.
+ */
+ public BigInteger getP();
+
+ /**
+ * Returns the subprime, {@code q}.
+ *
+ * @return the subprime, {@code q}.
+ */
+ public BigInteger getQ();
+
+ /**
+ * Returns the base, {@code g}.
+ *
+ * @return the base, {@code g}.
+ */
+ public BigInteger getG();
+}
diff --git a/java/security/interfaces/DSAPrivateKey.java b/java/security/interfaces/DSAPrivateKey.java
new file mode 100644
index 0000000..81ab358
--- /dev/null
+++ b/java/security/interfaces/DSAPrivateKey.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * The standard interface to a DSA private key. DSA (Digital Signature
+ * Algorithm) is defined in NIST's FIPS-186.
+ *
+ * @see java.security.Key
+ * @see java.security.Signature
+ * @see DSAKey
+ * @see DSAPublicKey
+ *
+ * @author Benjamin Renaud
+ */
+public interface DSAPrivateKey extends DSAKey, java.security.PrivateKey {
+
+ // Declare serialVersionUID to be compatible with JDK1.1
+
+ /**
+ * The class fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the class.
+ */
+ static final long serialVersionUID = 7776497482533790279L;
+
+ /**
+ * Returns the value of the private key, {@code x}.
+ *
+ * @return the value of the private key, {@code x}.
+ */
+ public BigInteger getX();
+}
diff --git a/java/security/interfaces/DSAPublicKey.java b/java/security/interfaces/DSAPublicKey.java
new file mode 100644
index 0000000..e56b795
--- /dev/null
+++ b/java/security/interfaces/DSAPublicKey.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * The interface to a DSA public key. DSA (Digital Signature Algorithm)
+ * is defined in NIST's FIPS-186.
+ *
+ * @see java.security.Key
+ * @see java.security.Signature
+ * @see DSAKey
+ * @see DSAPrivateKey
+ *
+ * @author Benjamin Renaud
+ */
+public interface DSAPublicKey extends DSAKey, java.security.PublicKey {
+
+ // Declare serialVersionUID to be compatible with JDK1.1
+
+ /**
+ * The class fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the class.
+ */
+ static final long serialVersionUID = 1234526332779022332L;
+
+ /**
+ * Returns the value of the public key, {@code y}.
+ *
+ * @return the value of the public key, {@code y}.
+ */
+ public BigInteger getY();
+}
diff --git a/java/security/interfaces/ECKey.java b/java/security/interfaces/ECKey.java
new file mode 100644
index 0000000..dd4b9d1
--- /dev/null
+++ b/java/security/interfaces/ECKey.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.spec.ECParameterSpec;
+
+/**
+ * The interface to an elliptic curve (EC) key.
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public interface ECKey {
+ /**
+ * Returns the domain parameters associated
+ * with this key. The domain parameters are
+ * either explicitly specified or implicitly
+ * created during key generation.
+ * @return the associated domain parameters.
+ */
+ ECParameterSpec getParams();
+}
diff --git a/java/security/interfaces/ECPrivateKey.java b/java/security/interfaces/ECPrivateKey.java
new file mode 100644
index 0000000..0ccdc2d
--- /dev/null
+++ b/java/security/interfaces/ECPrivateKey.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PrivateKey;
+
+/**
+ * The interface to an elliptic curve (EC) private key.
+ *
+ * @author Valerie Peng
+ *
+ *
+ * @see PrivateKey
+ * @see ECKey
+ *
+ * @since 1.5
+ */
+public interface ECPrivateKey extends PrivateKey, ECKey {
+ /**
+ * The class fingerprint that is set to indicate
+ * serialization compatibility.
+ */
+ static final long serialVersionUID = -7896394956925609184L;
+
+ /**
+ * Returns the private value S.
+ * @return the private value S.
+ */
+ BigInteger getS();
+}
diff --git a/java/security/interfaces/ECPublicKey.java b/java/security/interfaces/ECPublicKey.java
new file mode 100644
index 0000000..6d16157
--- /dev/null
+++ b/java/security/interfaces/ECPublicKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.PublicKey;
+import java.security.spec.ECPoint;
+
+/**
+ * The interface to an elliptic curve (EC) public key.
+ *
+ * @author Valerie Peng
+ *
+ *
+ * @see PublicKey
+ * @see ECKey
+ * @see java.security.spec.ECPoint
+ *
+ * @since 1.5
+ */
+public interface ECPublicKey extends PublicKey, ECKey {
+
+ /**
+ * The class fingerprint that is set to indicate
+ * serialization compatibility.
+ */
+ static final long serialVersionUID = -3314988629879632826L;
+
+ /**
+ * Returns the public point W.
+ * @return the public point W.
+ */
+ ECPoint getW();
+}
diff --git a/java/security/interfaces/RSAKey.java b/java/security/interfaces/RSAKey.java
new file mode 100644
index 0000000..67fbe2b
--- /dev/null
+++ b/java/security/interfaces/RSAKey.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * The interface to an RSA public or private key.
+ *
+ * @author Jan Luehe
+ *
+ * @see RSAPublicKey
+ * @see RSAPrivateKey
+ *
+ * @since 1.3
+ */
+
+public interface RSAKey {
+
+ /**
+ * Returns the modulus.
+ *
+ * @return the modulus
+ */
+ public BigInteger getModulus();
+}
diff --git a/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
new file mode 100644
index 0000000..f85d96a
--- /dev/null
+++ b/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.spec.RSAOtherPrimeInfo;
+
+/**
+ * The interface to an RSA multi-prime private key, as defined in the
+ * PKCS#1 v2.1, using the <i>Chinese Remainder Theorem</i>
+ * (CRT) information values.
+ *
+ * @author Valerie Peng
+ *
+ *
+ * @see java.security.spec.RSAPrivateKeySpec
+ * @see java.security.spec.RSAMultiPrimePrivateCrtKeySpec
+ * @see RSAPrivateKey
+ * @see RSAPrivateCrtKey
+ *
+ * @since 1.4
+ */
+
+public interface RSAMultiPrimePrivateCrtKey extends RSAPrivateKey {
+
+ /**
+ * The type fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the type.
+ */
+ static final long serialVersionUID = 618058533534628008L;
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent.
+ */
+ public BigInteger getPublicExponent();
+
+ /**
+ * Returns the primeP.
+ *
+ * @return the primeP.
+ */
+ public BigInteger getPrimeP();
+
+ /**
+ * Returns the primeQ.
+ *
+ * @return the primeQ.
+ */
+ public BigInteger getPrimeQ();
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @return the primeExponentP.
+ */
+ public BigInteger getPrimeExponentP();
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @return the primeExponentQ.
+ */
+ public BigInteger getPrimeExponentQ();
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @return the crtCoefficient.
+ */
+ public BigInteger getCrtCoefficient();
+
+ /**
+ * Returns the otherPrimeInfo or null if there are only
+ * two prime factors (p and q).
+ *
+ * @return the otherPrimeInfo.
+ */
+ public RSAOtherPrimeInfo[] getOtherPrimeInfo();
+}
diff --git a/java/security/interfaces/RSAPrivateCrtKey.java b/java/security/interfaces/RSAPrivateCrtKey.java
new file mode 100644
index 0000000..0408fea
--- /dev/null
+++ b/java/security/interfaces/RSAPrivateCrtKey.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * The interface to an RSA private key, as defined in the PKCS#1 standard,
+ * using the <i>Chinese Remainder Theorem</i> (CRT) information values.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see RSAPrivateKey
+ */
+
+public interface RSAPrivateCrtKey extends RSAPrivateKey {
+
+ /**
+ * The type fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the type.
+ */
+ static final long serialVersionUID = -5682214253527700368L;
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent
+ */
+ public BigInteger getPublicExponent();
+
+ /**
+ * Returns the primeP.
+
+ * @return the primeP
+ */
+ public BigInteger getPrimeP();
+
+ /**
+ * Returns the primeQ.
+ *
+ * @return the primeQ
+ */
+ public BigInteger getPrimeQ();
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @return the primeExponentP
+ */
+ public BigInteger getPrimeExponentP();
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @return the primeExponentQ
+ */
+ public BigInteger getPrimeExponentQ();
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @return the crtCoefficient
+ */
+ public BigInteger getCrtCoefficient();
+}
diff --git a/java/security/interfaces/RSAPrivateKey.java b/java/security/interfaces/RSAPrivateKey.java
new file mode 100644
index 0000000..5d69ad6
--- /dev/null
+++ b/java/security/interfaces/RSAPrivateKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * The interface to an RSA private key.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see RSAPrivateCrtKey
+ */
+
+public interface RSAPrivateKey extends java.security.PrivateKey, RSAKey
+{
+
+ /**
+ * The type fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the type.
+ */
+ static final long serialVersionUID = 5187144804936595022L;
+
+ /**
+ * Returns the private exponent.
+ *
+ * @return the private exponent
+ */
+ public BigInteger getPrivateExponent();
+}
diff --git a/java/security/interfaces/RSAPublicKey.java b/java/security/interfaces/RSAPublicKey.java
new file mode 100644
index 0000000..a698c05
--- /dev/null
+++ b/java/security/interfaces/RSAPublicKey.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.interfaces;
+
+import java.math.BigInteger;
+
+/**
+ * The interface to an RSA public key.
+ *
+ * @author Jan Luehe
+ *
+ */
+
+public interface RSAPublicKey extends java.security.PublicKey, RSAKey
+{
+ /**
+ * The type fingerprint that is set to indicate
+ * serialization compatibility with a previous
+ * version of the type.
+ */
+ static final long serialVersionUID = -8727434096241101194L;
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent
+ */
+ public BigInteger getPublicExponent();
+}
diff --git a/java/security/interfaces/package-info.java b/java/security/interfaces/package-info.java
new file mode 100644
index 0000000..a2d77da
--- /dev/null
+++ b/java/security/interfaces/package-info.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides interfaces for generating RSA (Rivest, Shamir and
+ * Adleman AsymmetricCipher algorithm)
+ * keys as defined in the RSA Laboratory Technical Note
+ * PKCS#1, and DSA (Digital Signature
+ * Algorithm) keys as defined in NIST's FIPS-186.
+ * <P>
+ * Note that these interfaces are intended only for key
+ * implementations whose key material is accessible and
+ * available. These interfaces are not intended for key
+ * implementations whose key material resides in
+ * inaccessible, protected storage (such as in a
+ * hardware device).
+ * <P>
+ * For more developer information on how to use these
+ * interfaces, including information on how to design
+ * {@code Key} classes for hardware devices, please refer
+ * to these cryptographic provider developer guides:
+ * <ul>
+ * <li><a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/HowToImplAProvider.html">
+ * <b>How to Implement a Provider for the
+ * Java™ Cryptography Architecture
+ * </b></a></li>
+ * </ul>
+ *
+ * <h2>Package Specification</h2>
+ *
+ * <ul>
+ * <li>PKCS #1: RSA Encryption Standard, Version 1.5, November 1993 </li>
+ * <li>Federal Information Processing Standards Publication (FIPS PUB) 186:
+ * Digital Signature Standard (DSS) </li>
+ * </ul>
+ *
+ * <h2>Related Documentation</h2>
+ *
+ * For further documentation, please see:
+ * <ul>
+ * <li>
+ * <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * <b>Java™
+ * Cryptography Architecture API Specification and Reference
+ * </b></a></li>
+ * </ul>
+ *
+ * @since JDK1.1
+ */
+package java.security.interfaces;
diff --git a/java/security/package-info.java b/java/security/package-info.java
new file mode 100644
index 0000000..376aa9d
--- /dev/null
+++ b/java/security/package-info.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides the classes and interfaces for the security framework.
+ * This includes classes that implement an easily configurable,
+ * fine-grained access control security architecture.
+ * This package also supports
+ * the generation and storage of cryptographic public key pairs,
+ * as well as a number of exportable cryptographic operations
+ * including those for message digest and signature generation. Finally,
+ * this package provides classes that support signed/guarded objects
+ * and secure random number generation.
+ *
+ * Many of the classes provided in this package (the cryptographic
+ * and secure random number generator classes in particular) are
+ * provider-based. The class itself defines a programming interface
+ * to which applications may write. The implementations themselves may
+ * then be written by independent third-party vendors and plugged
+ * in seamlessly as needed. Therefore application developers may
+ * take advantage of any number of provider-based implementations
+ * without having to add or rewrite code.
+ *
+ * <h2>Package Specification</h2>
+ *
+ * <ul>
+ * <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/crypto/CryptoSpec.html">
+ * <b>Java™
+ * Cryptography Architecture (JCA) Reference Guide</b></a></li>
+ *
+ * <li>PKCS #8: Private-Key Information Syntax Standard, Version 1.2,
+ * November 1993</li>
+ *
+ * <li><a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/StandardNames.html">
+ * <b>Java™
+ * Cryptography Architecture Standard Algorithm Name
+ * Documentation</b></a></li>
+ * </ul>
+ *
+ * <h2>Related Documentation</h2>
+ *
+ * For further documentation, please see:
+ * <ul>
+ * <li><a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/spec/security-spec.doc.html">
+ * <b>Java™
+ * SE Platform Security Architecture</b></a></li>
+ *
+ * <li><a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/crypto/HowToImplAProvider.html">
+ * <b>How to Implement a Provider in the
+ * Java™ Cryptography Architecture
+ * </b></a></li>
+ *
+ * <li><a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/PolicyFiles.html"><b>
+ * Default Policy Implementation and Policy File Syntax
+ * </b></a></li>
+ *
+ * <li><a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/permissions.html"><b>
+ * Permissions in the
+ * Java™ SE Development Kit (JDK)
+ * </b></a></li>
+ *
+ * <li><a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/guides/security/SecurityToolsSummary.html"><b>
+ * Summary of Tools for
+ * Java™ Platform Security
+ * </b></a></li>
+ *
+ * <li><b>keytool</b>
+ * (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/unix/keytool.html">
+ * for Solaris/Linux</a>)
+ * (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/windows/keytool.html">
+ * for Windows</a>)
+ * </li>
+ *
+ * <li><b>jarsigner</b>
+ * (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/unix/jarsigner.html">
+ * for Solaris/Linux</a>)
+ * (<a href="{@docRoot}openjdk-redirect.html?v=8&path=/../technotes/tools/windows/jarsigner.html">
+ * for Windows</a>)
+ * </li>
+ *
+ * </ul>
+ *
+ * @since 1.1
+ */
+package java.security;
diff --git a/java/security/spec/AlgorithmParameterSpec.java b/java/security/spec/AlgorithmParameterSpec.java
new file mode 100644
index 0000000..7714c30
--- /dev/null
+++ b/java/security/spec/AlgorithmParameterSpec.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1997, 1999, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+/**
+ * A (transparent) specification of cryptographic parameters.
+ *
+ * <P> This interface contains no methods or constants. Its only purpose
+ * is to group (and provide type safety for) all parameter specifications.
+ * All parameter specifications must implement this interface.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.AlgorithmParameters
+ * @see DSAParameterSpec
+ *
+ * @since 1.2
+ */
+
+public interface AlgorithmParameterSpec { }
diff --git a/java/security/spec/DSAParameterSpec.java b/java/security/spec/DSAParameterSpec.java
new file mode 100644
index 0000000..eed6bdc
--- /dev/null
+++ b/java/security/spec/DSAParameterSpec.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies the set of parameters used with the DSA algorithm.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see AlgorithmParameterSpec
+ *
+ * @since 1.2
+ */
+
+public class DSAParameterSpec implements AlgorithmParameterSpec,
+java.security.interfaces.DSAParams {
+
+ BigInteger p;
+ BigInteger q;
+ BigInteger g;
+
+ /**
+ * Creates a new DSAParameterSpec with the specified parameter values.
+ *
+ * @param p the prime.
+ *
+ * @param q the sub-prime.
+ *
+ * @param g the base.
+ */
+ public DSAParameterSpec(BigInteger p, BigInteger q, BigInteger g) {
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ /**
+ * Returns the prime {@code p}.
+ *
+ * @return the prime {@code p}.
+ */
+ public BigInteger getP() {
+ return this.p;
+ }
+
+ /**
+ * Returns the sub-prime {@code q}.
+ *
+ * @return the sub-prime {@code q}.
+ */
+ public BigInteger getQ() {
+ return this.q;
+ }
+
+ /**
+ * Returns the base {@code g}.
+ *
+ * @return the base {@code g}.
+ */
+ public BigInteger getG() {
+ return this.g;
+ }
+}
diff --git a/java/security/spec/DSAPrivateKeySpec.java b/java/security/spec/DSAPrivateKeySpec.java
new file mode 100644
index 0000000..a004de7
--- /dev/null
+++ b/java/security/spec/DSAPrivateKeySpec.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies a DSA private key with its associated parameters.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see DSAPublicKeySpec
+ * @see PKCS8EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public class DSAPrivateKeySpec implements KeySpec {
+
+ private BigInteger x;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ /**
+ * Creates a new DSAPrivateKeySpec with the specified parameter values.
+ *
+ * @param x the private key.
+ *
+ * @param p the prime.
+ *
+ * @param q the sub-prime.
+ *
+ * @param g the base.
+ */
+ public DSAPrivateKeySpec(BigInteger x, BigInteger p, BigInteger q,
+ BigInteger g) {
+ this.x = x;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ /**
+ * Returns the private key {@code x}.
+ *
+ * @return the private key {@code x}.
+ */
+ public BigInteger getX() {
+ return this.x;
+ }
+
+ /**
+ * Returns the prime {@code p}.
+ *
+ * @return the prime {@code p}.
+ */
+ public BigInteger getP() {
+ return this.p;
+ }
+
+ /**
+ * Returns the sub-prime {@code q}.
+ *
+ * @return the sub-prime {@code q}.
+ */
+ public BigInteger getQ() {
+ return this.q;
+ }
+
+ /**
+ * Returns the base {@code g}.
+ *
+ * @return the base {@code g}.
+ */
+ public BigInteger getG() {
+ return this.g;
+ }
+}
diff --git a/java/security/spec/DSAPublicKeySpec.java b/java/security/spec/DSAPublicKeySpec.java
new file mode 100644
index 0000000..a56e6f9
--- /dev/null
+++ b/java/security/spec/DSAPublicKeySpec.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies a DSA public key with its associated parameters.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see DSAPrivateKeySpec
+ * @see X509EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public class DSAPublicKeySpec implements KeySpec {
+
+ private BigInteger y;
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+
+ /**
+ * Creates a new DSAPublicKeySpec with the specified parameter values.
+ *
+ * @param y the public key.
+ *
+ * @param p the prime.
+ *
+ * @param q the sub-prime.
+ *
+ * @param g the base.
+ */
+ public DSAPublicKeySpec(BigInteger y, BigInteger p, BigInteger q,
+ BigInteger g) {
+ this.y = y;
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ }
+
+ /**
+ * Returns the public key {@code y}.
+ *
+ * @return the public key {@code y}.
+ */
+ public BigInteger getY() {
+ return this.y;
+ }
+
+ /**
+ * Returns the prime {@code p}.
+ *
+ * @return the prime {@code p}.
+ */
+ public BigInteger getP() {
+ return this.p;
+ }
+
+ /**
+ * Returns the sub-prime {@code q}.
+ *
+ * @return the sub-prime {@code q}.
+ */
+ public BigInteger getQ() {
+ return this.q;
+ }
+
+ /**
+ * Returns the base {@code g}.
+ *
+ * @return the base {@code g}.
+ */
+ public BigInteger getG() {
+ return this.g;
+ }
+}
diff --git a/java/security/spec/ECField.java b/java/security/spec/ECField.java
new file mode 100644
index 0000000..6a42521
--- /dev/null
+++ b/java/security/spec/ECField.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+
+/**
+ * This interface represents an elliptic curve (EC) finite field.
+ * All specialized EC fields must implements this interface.
+ *
+ * @see ECFieldFp
+ * @see ECFieldF2m
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public interface ECField {
+ /**
+ * Returns the field size in bits. Note: For prime finite
+ * field ECFieldFp, size of prime p in bits is returned.
+ * For characteristic 2 finite field ECFieldF2m, m is returned.
+ * @return the field size in bits.
+ */
+ int getFieldSize();
+}
diff --git a/java/security/spec/ECFieldF2m.java b/java/security/spec/ECFieldF2m.java
new file mode 100644
index 0000000..4076fa6
--- /dev/null
+++ b/java/security/spec/ECFieldF2m.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+
+/**
+ * This immutable class defines an elliptic curve (EC)
+ * characteristic 2 finite field.
+ *
+ * @see ECField
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECFieldF2m implements ECField {
+
+ private int m;
+ private int[] ks;
+ private BigInteger rp;
+
+ /**
+ * Creates an elliptic curve characteristic 2 finite
+ * field which has 2^{@code m} elements with normal basis.
+ * @param m with 2^{@code m} being the number of elements.
+ * @exception IllegalArgumentException if {@code m}
+ * is not positive.
+ */
+ public ECFieldF2m(int m) {
+ if (m <= 0) {
+ throw new IllegalArgumentException("m is not positive");
+ }
+ this.m = m;
+ this.ks = null;
+ this.rp = null;
+ }
+
+ /**
+ * Creates an elliptic curve characteristic 2 finite
+ * field which has 2^{@code m} elements with
+ * polynomial basis.
+ * The reduction polynomial for this field is based
+ * on {@code rp} whose i-th bit corresponds to
+ * the i-th coefficient of the reduction polynomial.<p>
+ * Note: A valid reduction polynomial is either a
+ * trinomial (X^{@code m} + X^{@code k} + 1
+ * with {@code m} > {@code k} >= 1) or a
+ * pentanomial (X^{@code m} + X^{@code k3}
+ * + X^{@code k2} + X^{@code k1} + 1 with
+ * {@code m} > {@code k3} > {@code k2}
+ * > {@code k1} >= 1).
+ * @param m with 2^{@code m} being the number of elements.
+ * @param rp the BigInteger whose i-th bit corresponds to
+ * the i-th coefficient of the reduction polynomial.
+ * @exception NullPointerException if {@code rp} is null.
+ * @exception IllegalArgumentException if {@code m}
+ * is not positive, or {@code rp} does not represent
+ * a valid reduction polynomial.
+ */
+ public ECFieldF2m(int m, BigInteger rp) {
+ // check m and rp
+ this.m = m;
+ this.rp = rp;
+ if (m <= 0) {
+ throw new IllegalArgumentException("m is not positive");
+ }
+ int bitCount = this.rp.bitCount();
+ if (!this.rp.testBit(0) || !this.rp.testBit(m) ||
+ ((bitCount != 3) && (bitCount != 5))) {
+ throw new IllegalArgumentException
+ ("rp does not represent a valid reduction polynomial");
+ }
+ // convert rp into ks
+ BigInteger temp = this.rp.clearBit(0).clearBit(m);
+ this.ks = new int[bitCount-2];
+ for (int i = this.ks.length-1; i >= 0; i--) {
+ int index = temp.getLowestSetBit();
+ this.ks[i] = index;
+ temp = temp.clearBit(index);
+ }
+ }
+
+ /**
+ * Creates an elliptic curve characteristic 2 finite
+ * field which has 2^{@code m} elements with
+ * polynomial basis. The reduction polynomial for this
+ * field is based on {@code ks} whose content
+ * contains the order of the middle term(s) of the
+ * reduction polynomial.
+ * Note: A valid reduction polynomial is either a
+ * trinomial (X^{@code m} + X^{@code k} + 1
+ * with {@code m} > {@code k} >= 1) or a
+ * pentanomial (X^{@code m} + X^{@code k3}
+ * + X^{@code k2} + X^{@code k1} + 1 with
+ * {@code m} > {@code k3} > {@code k2}
+ * > {@code k1} >= 1), so {@code ks} should
+ * have length 1 or 3.
+ * @param m with 2^{@code m} being the number of elements.
+ * @param ks the order of the middle term(s) of the
+ * reduction polynomial. Contents of this array are copied
+ * to protect against subsequent modification.
+ * @exception NullPointerException if {@code ks} is null.
+ * @exception IllegalArgumentException if{@code m}
+ * is not positive, or the length of {@code ks}
+ * is neither 1 nor 3, or values in {@code ks}
+ * are not between {@code m}-1 and 1 (inclusive)
+ * and in descending order.
+ */
+ public ECFieldF2m(int m, int[] ks) {
+ // check m and ks
+ this.m = m;
+ this.ks = ks.clone();
+ if (m <= 0) {
+ throw new IllegalArgumentException("m is not positive");
+ }
+ if ((this.ks.length != 1) && (this.ks.length != 3)) {
+ throw new IllegalArgumentException
+ ("length of ks is neither 1 nor 3");
+ }
+ for (int i = 0; i < this.ks.length; i++) {
+ if ((this.ks[i] < 1) || (this.ks[i] > m-1)) {
+ throw new IllegalArgumentException
+ ("ks["+ i + "] is out of range");
+ }
+ if ((i != 0) && (this.ks[i] >= this.ks[i-1])) {
+ throw new IllegalArgumentException
+ ("values in ks are not in descending order");
+ }
+ }
+ // convert ks into rp
+ this.rp = BigInteger.ONE;
+ this.rp = rp.setBit(m);
+ for (int j = 0; j < this.ks.length; j++) {
+ rp = rp.setBit(this.ks[j]);
+ }
+ }
+
+ /**
+ * Returns the field size in bits which is {@code m}
+ * for this characteristic 2 finite field.
+ * @return the field size in bits.
+ */
+ public int getFieldSize() {
+ return m;
+ }
+
+ /**
+ * Returns the value {@code m} of this characteristic
+ * 2 finite field.
+ * @return {@code m} with 2^{@code m} being the
+ * number of elements.
+ */
+ public int getM() {
+ return m;
+ }
+
+ /**
+ * Returns a BigInteger whose i-th bit corresponds to the
+ * i-th coefficient of the reduction polynomial for polynomial
+ * basis or null for normal basis.
+ * @return a BigInteger whose i-th bit corresponds to the
+ * i-th coefficient of the reduction polynomial for polynomial
+ * basis or null for normal basis.
+ */
+ public BigInteger getReductionPolynomial() {
+ return rp;
+ }
+
+ /**
+ * Returns an integer array which contains the order of the
+ * middle term(s) of the reduction polynomial for polynomial
+ * basis or null for normal basis.
+ * @return an integer array which contains the order of the
+ * middle term(s) of the reduction polynomial for polynomial
+ * basis or null for normal basis. A new array is returned
+ * each time this method is called.
+ */
+ public int[] getMidTermsOfReductionPolynomial() {
+ if (ks == null) {
+ return null;
+ } else {
+ return ks.clone();
+ }
+ }
+
+ /**
+ * Compares this finite field for equality with the
+ * specified object.
+ * @param obj the object to be compared.
+ * @return true if {@code obj} is an instance
+ * of ECFieldF2m and both {@code m} and the reduction
+ * polynomial match, false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj instanceof ECFieldF2m) {
+ // no need to compare rp here since ks and rp
+ // should be equivalent
+ return ((m == ((ECFieldF2m)obj).m) &&
+ (Arrays.equals(ks, ((ECFieldF2m) obj).ks)));
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this characteristic 2
+ * finite field.
+ * @return a hash code value.
+ */
+ public int hashCode() {
+ int value = m << 5;
+ value += (rp==null? 0:rp.hashCode());
+ // no need to involve ks here since ks and rp
+ // should be equivalent.
+ return value;
+ }
+}
diff --git a/java/security/spec/ECFieldFp.java b/java/security/spec/ECFieldFp.java
new file mode 100644
index 0000000..c578962
--- /dev/null
+++ b/java/security/spec/ECFieldFp.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+
+/**
+ * This immutable class defines an elliptic curve (EC) prime
+ * finite field.
+ *
+ * @see ECField
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECFieldFp implements ECField {
+
+ private BigInteger p;
+
+ /**
+ * Creates an elliptic curve prime finite field
+ * with the specified prime {@code p}.
+ * @param p the prime.
+ * @exception NullPointerException if {@code p} is null.
+ * @exception IllegalArgumentException if {@code p}
+ * is not positive.
+ */
+ public ECFieldFp(BigInteger p) {
+ if (p.signum() != 1) {
+ throw new IllegalArgumentException("p is not positive");
+ }
+ this.p = p;
+ }
+
+ /**
+ * Returns the field size in bits which is size of prime p
+ * for this prime finite field.
+ * @return the field size in bits.
+ */
+ public int getFieldSize() {
+ return p.bitLength();
+ };
+
+ /**
+ * Returns the prime {@code p} of this prime finite field.
+ * @return the prime.
+ */
+ public BigInteger getP() {
+ return p;
+ }
+
+ /**
+ * Compares this prime finite field for equality with the
+ * specified object.
+ * @param obj the object to be compared.
+ * @return true if {@code obj} is an instance
+ * of ECFieldFp and the prime value match, false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj instanceof ECFieldFp) {
+ return (p.equals(((ECFieldFp)obj).p));
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this prime finite field.
+ * @return a hash code value.
+ */
+ public int hashCode() {
+ return p.hashCode();
+ }
+}
diff --git a/java/security/spec/ECGenParameterSpec.java b/java/security/spec/ECGenParameterSpec.java
new file mode 100644
index 0000000..4f3f63b
--- /dev/null
+++ b/java/security/spec/ECGenParameterSpec.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+/**
+ * This immutable class specifies the set of parameters used for
+ * generating elliptic curve (EC) domain parameters.
+ *
+ * @see AlgorithmParameterSpec
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECGenParameterSpec implements AlgorithmParameterSpec {
+
+ private String name;
+
+ /**
+ * Creates a parameter specification for EC parameter
+ * generation using a standard (or predefined) name
+ * {@code stdName} in order to generate the corresponding
+ * (precomputed) elliptic curve domain parameters. For the
+ * list of supported names, please consult the documentation
+ * of provider whose implementation will be used.
+ * @param stdName the standard name of the to-be-generated EC
+ * domain parameters.
+ * @exception NullPointerException if {@code stdName}
+ * is null.
+ */
+ public ECGenParameterSpec(String stdName) {
+ if (stdName == null) {
+ throw new NullPointerException("stdName is null");
+ }
+ this.name = stdName;
+ }
+
+ /**
+ * Returns the standard or predefined name of the
+ * to-be-generated EC domain parameters.
+ * @return the standard or predefined name.
+ */
+ public String getName() {
+ return name;
+ }
+}
diff --git a/java/security/spec/ECParameterSpec.java b/java/security/spec/ECParameterSpec.java
new file mode 100644
index 0000000..65bd027
--- /dev/null
+++ b/java/security/spec/ECParameterSpec.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This immutable class specifies the set of domain parameters
+ * used with elliptic curve cryptography (ECC).
+ *
+ * @see AlgorithmParameterSpec
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECParameterSpec implements AlgorithmParameterSpec {
+
+ private final EllipticCurve curve;
+ private final ECPoint g;
+ private final BigInteger n;
+ private final int h;
+
+ /**
+ * Creates elliptic curve domain parameters based on the
+ * specified values.
+ * @param curve the elliptic curve which this parameter
+ * defines.
+ * @param g the generator which is also known as the base point.
+ * @param n the order of the generator {@code g}.
+ * @param h the cofactor.
+ * @exception NullPointerException if {@code curve},
+ * {@code g}, or {@code n} is null.
+ * @exception IllegalArgumentException if {@code n}
+ * or {@code h} is not positive.
+ */
+ public ECParameterSpec(EllipticCurve curve, ECPoint g,
+ BigInteger n, int h) {
+ if (curve == null) {
+ throw new NullPointerException("curve is null");
+ }
+ if (g == null) {
+ throw new NullPointerException("g is null");
+ }
+ if (n == null) {
+ throw new NullPointerException("n is null");
+ }
+ if (n.signum() != 1) {
+ throw new IllegalArgumentException("n is not positive");
+ }
+ if (h <= 0) {
+ throw new IllegalArgumentException("h is not positive");
+ }
+ this.curve = curve;
+ this.g = g;
+ this.n = n;
+ this.h = h;
+ }
+
+ /**
+ * Returns the elliptic curve that this parameter defines.
+ * @return the elliptic curve that this parameter defines.
+ */
+ public EllipticCurve getCurve() {
+ return curve;
+ }
+
+ /**
+ * Returns the generator which is also known as the base point.
+ * @return the generator which is also known as the base point.
+ */
+ public ECPoint getGenerator() {
+ return g;
+ }
+
+ /**
+ * Returns the order of the generator.
+ * @return the order of the generator.
+ */
+ public BigInteger getOrder() {
+ return n;
+ }
+
+ /**
+ * Returns the cofactor.
+ * @return the cofactor.
+ */
+ public int getCofactor() {
+ return h;
+ }
+ // BEGIN Android-added: Store the curve name as part of the parameters
+ // Knowing the name of the curve sometimes allows implementations to operate
+ // more efficiently.
+ private String curveName;
+
+ /**
+ * Used to set the curve name if available.
+ *
+ * @hide
+ */
+ public void setCurveName(String curveName) {
+ this.curveName = curveName;
+ }
+
+ /**
+ * Returns the name of the curve if this is a named curve. Returns
+ * {@code null} if this is not known to be a named curve.
+ *
+ * @hide
+ */
+ public String getCurveName() {
+ return curveName;
+ }
+ // END Android-added: Store the curve name as part of the parameters
+}
diff --git a/java/security/spec/ECPoint.java b/java/security/spec/ECPoint.java
new file mode 100644
index 0000000..1b051c7
--- /dev/null
+++ b/java/security/spec/ECPoint.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This immutable class represents a point on an elliptic curve (EC)
+ * in affine coordinates. Other coordinate systems can
+ * extend this class to represent this point in other
+ * coordinates.
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECPoint {
+
+ private final BigInteger x;
+ private final BigInteger y;
+
+ /**
+ * This defines the point at infinity.
+ */
+ public static final ECPoint POINT_INFINITY = new ECPoint();
+
+ // private constructor for constructing point at infinity
+ private ECPoint() {
+ this.x = null;
+ this.y = null;
+ }
+
+ /**
+ * Creates an ECPoint from the specified affine x-coordinate
+ * {@code x} and affine y-coordinate {@code y}.
+ * @param x the affine x-coordinate.
+ * @param y the affine y-coordinate.
+ * @exception NullPointerException if {@code x} or
+ * {@code y} is null.
+ */
+ public ECPoint(BigInteger x, BigInteger y) {
+ if ((x==null) || (y==null)) {
+ throw new NullPointerException("affine coordinate x or y is null");
+ }
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Returns the affine x-coordinate {@code x}.
+ * Note: POINT_INFINITY has a null affine x-coordinate.
+ * @return the affine x-coordinate.
+ */
+ public BigInteger getAffineX() {
+ return x;
+ }
+
+ /**
+ * Returns the affine y-coordinate {@code y}.
+ * Note: POINT_INFINITY has a null affine y-coordinate.
+ * @return the affine y-coordinate.
+ */
+ public BigInteger getAffineY() {
+ return y;
+ }
+
+ /**
+ * Compares this elliptic curve point for equality with
+ * the specified object.
+ * @param obj the object to be compared.
+ * @return true if {@code obj} is an instance of
+ * ECPoint and the affine coordinates match, false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (this == POINT_INFINITY) return false;
+ if (obj instanceof ECPoint) {
+ return ((x.equals(((ECPoint)obj).x)) &&
+ (y.equals(((ECPoint)obj).y)));
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this elliptic curve point.
+ * @return a hash code value.
+ */
+ public int hashCode() {
+ if (this == POINT_INFINITY) return 0;
+ return x.hashCode() << 5 + y.hashCode();
+ }
+}
diff --git a/java/security/spec/ECPrivateKeySpec.java b/java/security/spec/ECPrivateKeySpec.java
new file mode 100644
index 0000000..7f03cfd
--- /dev/null
+++ b/java/security/spec/ECPrivateKeySpec.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This immutable class specifies an elliptic curve private key with
+ * its associated parameters.
+ *
+ * @see KeySpec
+ * @see ECParameterSpec
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECPrivateKeySpec implements KeySpec {
+
+ private BigInteger s;
+ private ECParameterSpec params;
+
+ /**
+ * Creates a new ECPrivateKeySpec with the specified
+ * parameter values.
+ * @param s the private value.
+ * @param params the associated elliptic curve domain
+ * parameters.
+ * @exception NullPointerException if {@code s}
+ * or {@code params} is null.
+ */
+ public ECPrivateKeySpec(BigInteger s, ECParameterSpec params) {
+ if (s == null) {
+ throw new NullPointerException("s is null");
+ }
+ if (params == null) {
+ throw new NullPointerException("params is null");
+ }
+ this.s = s;
+ this.params = params;
+ }
+
+ /**
+ * Returns the private value S.
+ * @return the private value S.
+ */
+ public BigInteger getS() {
+ return s;
+ }
+
+ /**
+ * Returns the associated elliptic curve domain
+ * parameters.
+ * @return the EC domain parameters.
+ */
+ public ECParameterSpec getParams() {
+ return params;
+ }
+}
diff --git a/java/security/spec/ECPublicKeySpec.java b/java/security/spec/ECPublicKeySpec.java
new file mode 100644
index 0000000..e0cfb77
--- /dev/null
+++ b/java/security/spec/ECPublicKeySpec.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+/**
+ * This immutable class specifies an elliptic curve public key with
+ * its associated parameters.
+ *
+ * @see KeySpec
+ * @see ECPoint
+ * @see ECParameterSpec
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class ECPublicKeySpec implements KeySpec {
+
+ private ECPoint w;
+ private ECParameterSpec params;
+
+ /**
+ * Creates a new ECPublicKeySpec with the specified
+ * parameter values.
+ * @param w the public point.
+ * @param params the associated elliptic curve domain
+ * parameters.
+ * @exception NullPointerException if {@code w}
+ * or {@code params} is null.
+ * @exception IllegalArgumentException if {@code w}
+ * is point at infinity, i.e. ECPoint.POINT_INFINITY
+ */
+ public ECPublicKeySpec(ECPoint w, ECParameterSpec params) {
+ if (w == null) {
+ throw new NullPointerException("w is null");
+ }
+ if (params == null) {
+ throw new NullPointerException("params is null");
+ }
+ if (w == ECPoint.POINT_INFINITY) {
+ throw new IllegalArgumentException("w is ECPoint.POINT_INFINITY");
+ }
+ this.w = w;
+ this.params = params;
+ }
+
+ /**
+ * Returns the public point W.
+ * @return the public point W.
+ */
+ public ECPoint getW() {
+ return w;
+ }
+
+ /**
+ * Returns the associated elliptic curve domain
+ * parameters.
+ * @return the EC domain parameters.
+ */
+ public ECParameterSpec getParams() {
+ return params;
+ }
+}
diff --git a/java/security/spec/EllipticCurve.java b/java/security/spec/EllipticCurve.java
new file mode 100644
index 0000000..8ec97b0
--- /dev/null
+++ b/java/security/spec/EllipticCurve.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+
+/**
+ * This immutable class holds the necessary values needed to represent
+ * an elliptic curve.
+ *
+ * @see ECField
+ * @see ECFieldFp
+ * @see ECFieldF2m
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class EllipticCurve {
+
+ private final ECField field;
+ private final BigInteger a;
+ private final BigInteger b;
+ private final byte[] seed;
+
+ // Check coefficient c is a valid element in ECField field.
+ private static void checkValidity(ECField field, BigInteger c,
+ String cName) {
+ // can only perform check if field is ECFieldFp or ECFieldF2m.
+ if (field instanceof ECFieldFp) {
+ BigInteger p = ((ECFieldFp)field).getP();
+ if (p.compareTo(c) != 1) {
+ throw new IllegalArgumentException(cName + " is too large");
+ } else if (c.signum() < 0) {
+ throw new IllegalArgumentException(cName + " is negative");
+ }
+ } else if (field instanceof ECFieldF2m) {
+ int m = ((ECFieldF2m)field).getM();
+ if (c.bitLength() > m) {
+ throw new IllegalArgumentException(cName + " is too large");
+ }
+ }
+ }
+
+ /**
+ * Creates an elliptic curve with the specified elliptic field
+ * {@code field} and the coefficients {@code a} and
+ * {@code b}.
+ * @param field the finite field that this elliptic curve is over.
+ * @param a the first coefficient of this elliptic curve.
+ * @param b the second coefficient of this elliptic curve.
+ * @exception NullPointerException if {@code field},
+ * {@code a}, or {@code b} is null.
+ * @exception IllegalArgumentException if {@code a}
+ * or {@code b} is not null and not in {@code field}.
+ */
+ public EllipticCurve(ECField field, BigInteger a,
+ BigInteger b) {
+ this(field, a, b, null);
+ }
+
+ /**
+ * Creates an elliptic curve with the specified elliptic field
+ * {@code field}, the coefficients {@code a} and
+ * {@code b}, and the {@code seed} used for curve generation.
+ * @param field the finite field that this elliptic curve is over.
+ * @param a the first coefficient of this elliptic curve.
+ * @param b the second coefficient of this elliptic curve.
+ * @param seed the bytes used during curve generation for later
+ * validation. Contents of this array are copied to protect against
+ * subsequent modification.
+ * @exception NullPointerException if {@code field},
+ * {@code a}, or {@code b} is null.
+ * @exception IllegalArgumentException if {@code a}
+ * or {@code b} is not null and not in {@code field}.
+ */
+ public EllipticCurve(ECField field, BigInteger a,
+ BigInteger b, byte[] seed) {
+ if (field == null) {
+ throw new NullPointerException("field is null");
+ }
+ if (a == null) {
+ throw new NullPointerException("first coefficient is null");
+ }
+ if (b == null) {
+ throw new NullPointerException("second coefficient is null");
+ }
+ checkValidity(field, a, "first coefficient");
+ checkValidity(field, b, "second coefficient");
+ this.field = field;
+ this.a = a;
+ this.b = b;
+ if (seed != null) {
+ this.seed = seed.clone();
+ } else {
+ this.seed = null;
+ }
+ }
+
+ /**
+ * Returns the finite field {@code field} that this
+ * elliptic curve is over.
+ * @return the field {@code field} that this curve
+ * is over.
+ */
+ public ECField getField() {
+ return field;
+ }
+
+ /**
+ * Returns the first coefficient {@code a} of the
+ * elliptic curve.
+ * @return the first coefficient {@code a}.
+ */
+ public BigInteger getA() {
+ return a;
+ }
+
+ /**
+ * Returns the second coefficient {@code b} of the
+ * elliptic curve.
+ * @return the second coefficient {@code b}.
+ */
+ public BigInteger getB() {
+ return b;
+ }
+
+ /**
+ * Returns the seeding bytes {@code seed} used
+ * during curve generation. May be null if not specified.
+ * @return the seeding bytes {@code seed}. A new
+ * array is returned each time this method is called.
+ */
+ public byte[] getSeed() {
+ if (seed == null) return null;
+ else return seed.clone();
+ }
+
+ /**
+ * Compares this elliptic curve for equality with the
+ * specified object.
+ * @param obj the object to be compared.
+ * @return true if {@code obj} is an instance of
+ * EllipticCurve and the field, A, and B match, false otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj instanceof EllipticCurve) {
+ EllipticCurve curve = (EllipticCurve) obj;
+ if ((field.equals(curve.field)) &&
+ (a.equals(curve.a)) &&
+ (b.equals(curve.b))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this elliptic curve.
+ * @return a hash code value computed from the hash codes of the field, A,
+ * and B, as follows:
+ * <pre>{@code
+ * (field.hashCode() << 6) + (a.hashCode() << 4) + (b.hashCode() << 2)
+ * }</pre>
+ */
+ public int hashCode() {
+ return (field.hashCode() << 6 +
+ (a.hashCode() << 4) +
+ (b.hashCode() << 2));
+ }
+}
diff --git a/java/security/spec/EncodedKeySpec.java b/java/security/spec/EncodedKeySpec.java
new file mode 100644
index 0000000..cc3b81e
--- /dev/null
+++ b/java/security/spec/EncodedKeySpec.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+/**
+ * This class represents a public or private key in encoded format.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see X509EncodedKeySpec
+ * @see PKCS8EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public abstract class EncodedKeySpec implements KeySpec {
+
+ private byte[] encodedKey;
+
+ /**
+ * Creates a new EncodedKeySpec with the given encoded key.
+ *
+ * @param encodedKey the encoded key. The contents of the
+ * array are copied to protect against subsequent modification.
+ * @exception NullPointerException if {@code encodedKey}
+ * is null.
+ */
+ public EncodedKeySpec(byte[] encodedKey) {
+ this.encodedKey = encodedKey.clone();
+ }
+
+ /**
+ * Returns the encoded key.
+ *
+ * @return the encoded key. Returns a new array each time
+ * this method is called.
+ */
+ public byte[] getEncoded() {
+ return this.encodedKey.clone();
+ }
+
+ /**
+ * Returns the name of the encoding format associated with this
+ * key specification.
+ *
+ * <p>If the opaque representation of a key
+ * (see {@link java.security.Key Key}) can be transformed
+ * (see {@link java.security.KeyFactory KeyFactory})
+ * into this key specification (or a subclass of it),
+ * {@code getFormat} called
+ * on the opaque key returns the same value as the
+ * {@code getFormat} method
+ * of this key specification.
+ *
+ * @return a string representation of the encoding format.
+ */
+ public abstract String getFormat();
+}
diff --git a/java/security/spec/InvalidKeySpecException.java b/java/security/spec/InvalidKeySpecException.java
new file mode 100644
index 0000000..4655c4a
--- /dev/null
+++ b/java/security/spec/InvalidKeySpecException.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This is the exception for invalid key specifications.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see KeySpec
+ *
+ * @since 1.2
+ */
+
+public class InvalidKeySpecException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = 3546139293998810778L;
+
+ /**
+ * Constructs an InvalidKeySpecException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public InvalidKeySpecException() {
+ super();
+ }
+
+ /**
+ * Constructs an InvalidKeySpecException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public InvalidKeySpecException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a {@code InvalidKeySpecException} with the specified
+ * detail message and cause.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public InvalidKeySpecException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Creates a {@code InvalidKeySpecException} with the specified cause
+ * and a detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @since 1.5
+ */
+ public InvalidKeySpecException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/java/security/spec/InvalidParameterSpecException.java b/java/security/spec/InvalidParameterSpecException.java
new file mode 100644
index 0000000..3059c77
--- /dev/null
+++ b/java/security/spec/InvalidParameterSpecException.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1997, 2003, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * This is the exception for invalid parameter specifications.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.AlgorithmParameters
+ * @see AlgorithmParameterSpec
+ * @see DSAParameterSpec
+ *
+ * @since 1.2
+ */
+
+public class InvalidParameterSpecException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -970468769593399342L;
+
+ /**
+ * Constructs an InvalidParameterSpecException with no detail message. A
+ * detail message is a String that describes this particular
+ * exception.
+ */
+ public InvalidParameterSpecException() {
+ super();
+ }
+
+ /**
+ * Constructs an InvalidParameterSpecException with the specified detail
+ * message. A detail message is a String that describes this
+ * particular exception.
+ *
+ * @param msg the detail message.
+ */
+ public InvalidParameterSpecException(String msg) {
+ super(msg);
+ }
+}
diff --git a/java/security/spec/KeySpec.java b/java/security/spec/KeySpec.java
new file mode 100644
index 0000000..34fec5d
--- /dev/null
+++ b/java/security/spec/KeySpec.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+/**
+ * A (transparent) specification of the key material
+ * that constitutes a cryptographic key.
+ *
+ * <p>If the key is stored on a hardware device, its
+ * specification may contain information that helps identify the key on the
+ * device.
+ *
+ * <P> A key may be specified in an algorithm-specific way, or in an
+ * algorithm-independent encoding format (such as ASN.1).
+ * For example, a DSA private key may be specified by its components
+ * {@code x}, {@code p}, {@code q}, and {@code g}
+ * (see {@link DSAPrivateKeySpec}), or it may be
+ * specified using its DER encoding
+ * (see {@link PKCS8EncodedKeySpec}).
+ *
+ * <P> This interface contains no methods or constants. Its only purpose
+ * is to group (and provide type safety for) all key specifications.
+ * All key specifications must implement this interface.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see EncodedKeySpec
+ * @see X509EncodedKeySpec
+ * @see PKCS8EncodedKeySpec
+ * @see DSAPrivateKeySpec
+ * @see DSAPublicKeySpec
+ *
+ * @since 1.2
+ */
+
+public interface KeySpec { }
diff --git a/java/security/spec/MGF1ParameterSpec.java b/java/security/spec/MGF1ParameterSpec.java
new file mode 100644
index 0000000..1be267f
--- /dev/null
+++ b/java/security/spec/MGF1ParameterSpec.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the set of parameters used with mask generation
+ * function MGF1 in OAEP Padding and RSA-PSS signature scheme, as
+ * defined in the
+ * <a href="http://www.ietf.org/rfc/rfc3447.txt">PKCS #1 v2.1</a>
+ * standard.
+ *
+ * <p>Its ASN.1 definition in PKCS#1 standard is described below:
+ * <pre>
+ * MGF1Parameters ::= OAEP-PSSDigestAlgorthms
+ * </pre>
+ * where
+ * <pre>
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha224 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ * </pre>
+ * @see PSSParameterSpec
+ * @see javax.crypto.spec.OAEPParameterSpec
+ *
+ * @author Valerie Peng
+ *
+ * @since 1.5
+ */
+public class MGF1ParameterSpec implements AlgorithmParameterSpec {
+
+ /**
+ * The MGF1ParameterSpec which uses "SHA-1" message digest.
+ */
+ public static final MGF1ParameterSpec SHA1 =
+ new MGF1ParameterSpec("SHA-1");
+ /**
+ * The MGF1ParameterSpec which uses "SHA-224" message digest.
+ */
+ public static final MGF1ParameterSpec SHA224 =
+ new MGF1ParameterSpec("SHA-224");
+ /**
+ * The MGF1ParameterSpec which uses "SHA-256" message digest.
+ */
+ public static final MGF1ParameterSpec SHA256 =
+ new MGF1ParameterSpec("SHA-256");
+ /**
+ * The MGF1ParameterSpec which uses "SHA-384" message digest.
+ */
+ public static final MGF1ParameterSpec SHA384 =
+ new MGF1ParameterSpec("SHA-384");
+ /**
+ * The MGF1ParameterSpec which uses SHA-512 message digest.
+ */
+ public static final MGF1ParameterSpec SHA512 =
+ new MGF1ParameterSpec("SHA-512");
+
+ private String mdName;
+
+ /**
+ * Constructs a parameter set for mask generation function MGF1
+ * as defined in the PKCS #1 standard.
+ *
+ * @param mdName the algorithm name for the message digest
+ * used in this mask generation function MGF1.
+ * @exception NullPointerException if {@code mdName} is null.
+ */
+ public MGF1ParameterSpec(String mdName) {
+ if (mdName == null) {
+ throw new NullPointerException("digest algorithm is null");
+ }
+ this.mdName = mdName;
+ }
+
+ /**
+ * Returns the algorithm name of the message digest used by the mask
+ * generation function.
+ *
+ * @return the algorithm name of the message digest.
+ */
+ public String getDigestAlgorithm() {
+ return mdName;
+ }
+}
diff --git a/java/security/spec/PKCS8EncodedKeySpec.java b/java/security/spec/PKCS8EncodedKeySpec.java
new file mode 100644
index 0000000..060f266
--- /dev/null
+++ b/java/security/spec/PKCS8EncodedKeySpec.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+/**
+ * This class represents the ASN.1 encoding of a private key,
+ * encoded according to the ASN.1 type {@code PrivateKeyInfo}.
+ * The {@code PrivateKeyInfo} syntax is defined in the PKCS#8 standard
+ * as follows:
+ *
+ * <pre>
+ * PrivateKeyInfo ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL }
+ *
+ * Version ::= INTEGER
+ *
+ * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * PrivateKey ::= OCTET STRING
+ *
+ * Attributes ::= SET OF Attribute
+ * </pre>
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see EncodedKeySpec
+ * @see X509EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public class PKCS8EncodedKeySpec extends EncodedKeySpec {
+
+ /**
+ * Creates a new PKCS8EncodedKeySpec with the given encoded key.
+ *
+ * @param encodedKey the key, which is assumed to be
+ * encoded according to the PKCS #8 standard. The contents of
+ * the array are copied to protect against subsequent modification.
+ * @exception NullPointerException if {@code encodedKey}
+ * is null.
+ */
+ public PKCS8EncodedKeySpec(byte[] encodedKey) {
+ super(encodedKey);
+ }
+
+ /**
+ * Returns the key bytes, encoded according to the PKCS #8 standard.
+ *
+ * @return the PKCS #8 encoding of the key. Returns a new array
+ * each time this method is called.
+ */
+ public byte[] getEncoded() {
+ return super.getEncoded();
+ }
+
+ /**
+ * Returns the name of the encoding format associated with this
+ * key specification.
+ *
+ * @return the string {@code "PKCS#8"}.
+ */
+ public final String getFormat() {
+ return "PKCS#8";
+ }
+}
diff --git a/java/security/spec/PSSParameterSpec.java b/java/security/spec/PSSParameterSpec.java
new file mode 100644
index 0000000..a9b82d8
--- /dev/null
+++ b/java/security/spec/PSSParameterSpec.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.security.spec.MGF1ParameterSpec;
+
+/**
+ * This class specifies a parameter spec for RSA-PSS signature scheme,
+ * as defined in the
+ * <a href="http://www.ietf.org/rfc/rfc3447.txt">PKCS#1 v2.1</a>
+ * standard.
+ *
+ * <p>Its ASN.1 definition in PKCS#1 standard is described below:
+ * <pre>
+ * RSASSA-PSS-params ::= SEQUENCE {
+ * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1,
+ * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1,
+ * saltLength [2] INTEGER DEFAULT 20,
+ * trailerField [3] INTEGER DEFAULT 1
+ * }
+ * </pre>
+ * where
+ * <pre>
+ * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-sha1 PARAMETERS NULL }|
+ * { OID id-sha224 PARAMETERS NULL }|
+ * { OID id-sha256 PARAMETERS NULL }|
+ * { OID id-sha384 PARAMETERS NULL }|
+ * { OID id-sha512 PARAMETERS NULL },
+ * ... -- Allows for future expansion --
+ * }
+ *
+ * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= {
+ * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+ * ... -- Allows for future expansion --
+ * }
+ * </pre>
+ * <p>Note: the PSSParameterSpec.DEFAULT uses the following:
+ * message digest -- "SHA-1"
+ * mask generation function (mgf) -- "MGF1"
+ * parameters for mgf -- MGF1ParameterSpec.SHA1
+ * SaltLength -- 20
+ * TrailerField -- 1
+ *
+ * @see MGF1ParameterSpec
+ * @see AlgorithmParameterSpec
+ * @see java.security.Signature
+ *
+ * @author Valerie Peng
+ *
+ *
+ * @since 1.4
+ */
+
+public class PSSParameterSpec implements AlgorithmParameterSpec {
+
+ private String mdName = "SHA-1";
+ private String mgfName = "MGF1";
+ private AlgorithmParameterSpec mgfSpec = MGF1ParameterSpec.SHA1;
+ private int saltLen = 20;
+ private int trailerField = 1;
+
+ /**
+ * The PSS parameter set with all default values.
+ * @since 1.5
+ */
+ public static final PSSParameterSpec DEFAULT = new PSSParameterSpec();
+
+ /**
+ * Constructs a new {@code PSSParameterSpec} as defined in
+ * the PKCS #1 standard using the default values.
+ */
+ private PSSParameterSpec() {
+ }
+
+ /**
+ * Creates a new {@code PSSParameterSpec} as defined in
+ * the PKCS #1 standard using the specified message digest,
+ * mask generation function, parameters for mask generation
+ * function, salt length, and trailer field values.
+ *
+ * @param mdName the algorithm name of the hash function.
+ * @param mgfName the algorithm name of the mask generation
+ * function.
+ * @param mgfSpec the parameters for the mask generation
+ * function. If null is specified, null will be returned by
+ * getMGFParameters().
+ * @param saltLen the length of salt.
+ * @param trailerField the value of the trailer field.
+ * @exception NullPointerException if {@code mdName},
+ * or {@code mgfName} is null.
+ * @exception IllegalArgumentException if {@code saltLen}
+ * or {@code trailerField} is less than 0.
+ * @since 1.5
+ */
+ public PSSParameterSpec(String mdName, String mgfName,
+ AlgorithmParameterSpec mgfSpec,
+ int saltLen, int trailerField) {
+ if (mdName == null) {
+ throw new NullPointerException("digest algorithm is null");
+ }
+ if (mgfName == null) {
+ throw new NullPointerException("mask generation function " +
+ "algorithm is null");
+ }
+ if (saltLen < 0) {
+ throw new IllegalArgumentException("negative saltLen value: " +
+ saltLen);
+ }
+ if (trailerField < 0) {
+ throw new IllegalArgumentException("negative trailerField: " +
+ trailerField);
+ }
+ this.mdName = mdName;
+ this.mgfName = mgfName;
+ this.mgfSpec = mgfSpec;
+ this.saltLen = saltLen;
+ this.trailerField = trailerField;
+ }
+
+ /**
+ * Creates a new {@code PSSParameterSpec}
+ * using the specified salt length and other default values as
+ * defined in PKCS#1.
+ *
+ * @param saltLen the length of salt in bits to be used in PKCS#1
+ * PSS encoding.
+ * @exception IllegalArgumentException if {@code saltLen} is
+ * less than 0.
+ */
+ public PSSParameterSpec(int saltLen) {
+ if (saltLen < 0) {
+ throw new IllegalArgumentException("negative saltLen value: " +
+ saltLen);
+ }
+ this.saltLen = saltLen;
+ }
+
+ /**
+ * Returns the message digest algorithm name.
+ *
+ * @return the message digest algorithm name.
+ * @since 1.5
+ */
+ public String getDigestAlgorithm() {
+ return mdName;
+ }
+
+ /**
+ * Returns the mask generation function algorithm name.
+ *
+ * @return the mask generation function algorithm name.
+ *
+ * @since 1.5
+ */
+ public String getMGFAlgorithm() {
+ return mgfName;
+ }
+
+ /**
+ * Returns the parameters for the mask generation function.
+ *
+ * @return the parameters for the mask generation function.
+ * @since 1.5
+ */
+ public AlgorithmParameterSpec getMGFParameters() {
+ return mgfSpec;
+ }
+
+ /**
+ * Returns the salt length in bits.
+ *
+ * @return the salt length.
+ */
+ public int getSaltLength() {
+ return saltLen;
+ }
+
+ /**
+ * Returns the value for the trailer field, i.e. bc in PKCS#1 v2.1.
+ *
+ * @return the value for the trailer field, i.e. bc in PKCS#1 v2.1.
+ * @since 1.5
+ */
+ public int getTrailerField() {
+ return trailerField;
+ }
+}
diff --git a/java/security/spec/RSAKeyGenParameterSpec.java b/java/security/spec/RSAKeyGenParameterSpec.java
new file mode 100644
index 0000000..a73c6cd
--- /dev/null
+++ b/java/security/spec/RSAKeyGenParameterSpec.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * This class specifies the set of parameters used to generate an RSA
+ * key pair.
+ *
+ * @author Jan Luehe
+ *
+ * @see java.security.KeyPairGenerator#initialize(java.security.spec.AlgorithmParameterSpec)
+ *
+ * @since 1.3
+ */
+
+public class RSAKeyGenParameterSpec implements AlgorithmParameterSpec {
+
+ private int keysize;
+ private BigInteger publicExponent;
+
+ /**
+ * The public-exponent value F0 = 3.
+ */
+ public static final BigInteger F0 = BigInteger.valueOf(3);
+
+ /**
+ * The public exponent-value F4 = 65537.
+ */
+ public static final BigInteger F4 = BigInteger.valueOf(65537);
+
+ /**
+ * Constructs a new {@code RSAParameterSpec} object from the
+ * given keysize and public-exponent value.
+ *
+ * @param keysize the modulus size (specified in number of bits)
+ * @param publicExponent the public exponent
+ */
+ public RSAKeyGenParameterSpec(int keysize, BigInteger publicExponent) {
+ this.keysize = keysize;
+ this.publicExponent = publicExponent;
+ }
+
+ /**
+ * Returns the keysize.
+ *
+ * @return the keysize.
+ */
+ public int getKeysize() {
+ return keysize;
+ }
+
+ /**
+ * Returns the public-exponent value.
+ *
+ * @return the public-exponent value.
+ */
+ public BigInteger getPublicExponent() {
+ return publicExponent;
+ }
+}
diff --git a/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java b/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
new file mode 100644
index 0000000..a198e43
--- /dev/null
+++ b/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies an RSA multi-prime private key, as defined in the
+ * PKCS#1 v2.1, using the Chinese Remainder Theorem (CRT) information
+ * values for efficiency.
+ *
+ * @author Valerie Peng
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see PKCS8EncodedKeySpec
+ * @see RSAPrivateKeySpec
+ * @see RSAPublicKeySpec
+ * @see RSAOtherPrimeInfo
+ *
+ * @since 1.4
+ */
+
+public class RSAMultiPrimePrivateCrtKeySpec extends RSAPrivateKeySpec {
+
+ private final BigInteger publicExponent;
+ private final BigInteger primeP;
+ private final BigInteger primeQ;
+ private final BigInteger primeExponentP;
+ private final BigInteger primeExponentQ;
+ private final BigInteger crtCoefficient;
+ private final RSAOtherPrimeInfo otherPrimeInfo[];
+
+ /**
+ * Creates a new {@code RSAMultiPrimePrivateCrtKeySpec}
+ * given the modulus, publicExponent, privateExponent,
+ * primeP, primeQ, primeExponentP, primeExponentQ,
+ * crtCoefficient, and otherPrimeInfo as defined in PKCS#1 v2.1.
+ *
+ * <p>Note that the contents of {@code otherPrimeInfo}
+ * are copied to protect against subsequent modification when
+ * constructing this object.
+ *
+ * @param modulus the modulus n.
+ * @param publicExponent the public exponent e.
+ * @param privateExponent the private exponent d.
+ * @param primeP the prime factor p of n.
+ * @param primeQ the prime factor q of n.
+ * @param primeExponentP this is d mod (p-1).
+ * @param primeExponentQ this is d mod (q-1).
+ * @param crtCoefficient the Chinese Remainder Theorem
+ * coefficient q-1 mod p.
+ * @param otherPrimeInfo triplets of the rest of primes, null can be
+ * specified if there are only two prime factors (p and q).
+ * @exception NullPointerException if any of the parameters, i.e.
+ * {@code modulus},
+ * {@code publicExponent}, {@code privateExponent},
+ * {@code primeP}, {@code primeQ},
+ * {@code primeExponentP}, {@code primeExponentQ},
+ * {@code crtCoefficient}, is null.
+ * @exception IllegalArgumentException if an empty, i.e. 0-length,
+ * {@code otherPrimeInfo} is specified.
+ */
+ public RSAMultiPrimePrivateCrtKeySpec(BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger primeP,
+ BigInteger primeQ,
+ BigInteger primeExponentP,
+ BigInteger primeExponentQ,
+ BigInteger crtCoefficient,
+ RSAOtherPrimeInfo[] otherPrimeInfo) {
+ super(modulus, privateExponent);
+ if (modulus == null) {
+ throw new NullPointerException("the modulus parameter must be " +
+ "non-null");
+ }
+ if (publicExponent == null) {
+ throw new NullPointerException("the publicExponent parameter " +
+ "must be non-null");
+ }
+ if (privateExponent == null) {
+ throw new NullPointerException("the privateExponent parameter " +
+ "must be non-null");
+ }
+ if (primeP == null) {
+ throw new NullPointerException("the primeP parameter " +
+ "must be non-null");
+ }
+ if (primeQ == null) {
+ throw new NullPointerException("the primeQ parameter " +
+ "must be non-null");
+ }
+ if (primeExponentP == null) {
+ throw new NullPointerException("the primeExponentP parameter " +
+ "must be non-null");
+ }
+ if (primeExponentQ == null) {
+ throw new NullPointerException("the primeExponentQ parameter " +
+ "must be non-null");
+ }
+ if (crtCoefficient == null) {
+ throw new NullPointerException("the crtCoefficient parameter " +
+ "must be non-null");
+ }
+ this.publicExponent = publicExponent;
+ this.primeP = primeP;
+ this.primeQ = primeQ;
+ this.primeExponentP = primeExponentP;
+ this.primeExponentQ = primeExponentQ;
+ this.crtCoefficient = crtCoefficient;
+ if (otherPrimeInfo == null) {
+ this.otherPrimeInfo = null;
+ } else if (otherPrimeInfo.length == 0) {
+ throw new IllegalArgumentException("the otherPrimeInfo " +
+ "parameter must not be empty");
+ } else {
+ this.otherPrimeInfo = otherPrimeInfo.clone();
+ }
+ }
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent.
+ */
+ public BigInteger getPublicExponent() {
+ return this.publicExponent;
+ }
+
+ /**
+ * Returns the primeP.
+ *
+ * @return the primeP.
+ */
+ public BigInteger getPrimeP() {
+ return this.primeP;
+ }
+
+ /**
+ * Returns the primeQ.
+ *
+ * @return the primeQ.
+ */
+ public BigInteger getPrimeQ() {
+ return this.primeQ;
+ }
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @return the primeExponentP.
+ */
+ public BigInteger getPrimeExponentP() {
+ return this.primeExponentP;
+ }
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @return the primeExponentQ.
+ */
+ public BigInteger getPrimeExponentQ() {
+ return this.primeExponentQ;
+ }
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @return the crtCoefficient.
+ */
+ public BigInteger getCrtCoefficient() {
+ return this.crtCoefficient;
+ }
+
+ /**
+ * Returns a copy of the otherPrimeInfo or null if there are
+ * only two prime factors (p and q).
+ *
+ * @return the otherPrimeInfo. Returns a new array each
+ * time this method is called.
+ */
+ public RSAOtherPrimeInfo[] getOtherPrimeInfo() {
+ if (otherPrimeInfo == null) return null;
+ return otherPrimeInfo.clone();
+ }
+}
diff --git a/java/security/spec/RSAOtherPrimeInfo.java b/java/security/spec/RSAOtherPrimeInfo.java
new file mode 100644
index 0000000..10d8471
--- /dev/null
+++ b/java/security/spec/RSAOtherPrimeInfo.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class represents the triplet (prime, exponent, and coefficient)
+ * inside RSA's OtherPrimeInfo structure, as defined in the PKCS#1 v2.1.
+ * The ASN.1 syntax of RSA's OtherPrimeInfo is as follows:
+ *
+ * <pre>
+ * OtherPrimeInfo ::= SEQUENCE {
+ * prime INTEGER,
+ * exponent INTEGER,
+ * coefficient INTEGER
+ * }
+ *
+ * </pre>
+ *
+ * @author Valerie Peng
+ *
+ *
+ * @see RSAPrivateCrtKeySpec
+ * @see java.security.interfaces.RSAMultiPrimePrivateCrtKey
+ *
+ * @since 1.4
+ */
+
+public class RSAOtherPrimeInfo {
+
+ private BigInteger prime;
+ private BigInteger primeExponent;
+ private BigInteger crtCoefficient;
+
+
+ /**
+ * Creates a new {@code RSAOtherPrimeInfo}
+ * given the prime, primeExponent, and
+ * crtCoefficient as defined in PKCS#1.
+ *
+ * @param prime the prime factor of n.
+ * @param primeExponent the exponent.
+ * @param crtCoefficient the Chinese Remainder Theorem
+ * coefficient.
+ * @exception NullPointerException if any of the parameters, i.e.
+ * {@code prime}, {@code primeExponent},
+ * {@code crtCoefficient}, is null.
+ *
+ */
+ public RSAOtherPrimeInfo(BigInteger prime,
+ BigInteger primeExponent,
+ BigInteger crtCoefficient) {
+ if (prime == null) {
+ throw new NullPointerException("the prime parameter must be " +
+ "non-null");
+ }
+ if (primeExponent == null) {
+ throw new NullPointerException("the primeExponent parameter " +
+ "must be non-null");
+ }
+ if (crtCoefficient == null) {
+ throw new NullPointerException("the crtCoefficient parameter " +
+ "must be non-null");
+ }
+ this.prime = prime;
+ this.primeExponent = primeExponent;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ /**
+ * Returns the prime.
+ *
+ * @return the prime.
+ */
+ public final BigInteger getPrime() {
+ return this.prime;
+ }
+
+ /**
+ * Returns the prime's exponent.
+ *
+ * @return the primeExponent.
+ */
+ public final BigInteger getExponent() {
+ return this.primeExponent;
+ }
+
+ /**
+ * Returns the prime's crtCoefficient.
+ *
+ * @return the crtCoefficient.
+ */
+ public final BigInteger getCrtCoefficient() {
+ return this.crtCoefficient;
+ }
+}
diff --git a/java/security/spec/RSAPrivateCrtKeySpec.java b/java/security/spec/RSAPrivateCrtKeySpec.java
new file mode 100644
index 0000000..d0ba70b
--- /dev/null
+++ b/java/security/spec/RSAPrivateCrtKeySpec.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies an RSA private key, as defined in the PKCS#1
+ * standard, using the Chinese Remainder Theorem (CRT) information values for
+ * efficiency.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see PKCS8EncodedKeySpec
+ * @see RSAPrivateKeySpec
+ * @see RSAPublicKeySpec
+ */
+
+public class RSAPrivateCrtKeySpec extends RSAPrivateKeySpec {
+
+ private final BigInteger publicExponent;
+ private final BigInteger primeP;
+ private final BigInteger primeQ;
+ private final BigInteger primeExponentP;
+ private final BigInteger primeExponentQ;
+ private final BigInteger crtCoefficient;
+
+
+
+ /**
+ * Creates a new {@code RSAPrivateCrtKeySpec}
+ * given the modulus, publicExponent, privateExponent,
+ * primeP, primeQ, primeExponentP, primeExponentQ, and
+ * crtCoefficient as defined in PKCS#1.
+ *
+ * @param modulus the modulus n
+ * @param publicExponent the public exponent e
+ * @param privateExponent the private exponent d
+ * @param primeP the prime factor p of n
+ * @param primeQ the prime factor q of n
+ * @param primeExponentP this is d mod (p-1)
+ * @param primeExponentQ this is d mod (q-1)
+ * @param crtCoefficient the Chinese Remainder Theorem
+ * coefficient q-1 mod p
+ */
+ public RSAPrivateCrtKeySpec(BigInteger modulus,
+ BigInteger publicExponent,
+ BigInteger privateExponent,
+ BigInteger primeP,
+ BigInteger primeQ,
+ BigInteger primeExponentP,
+ BigInteger primeExponentQ,
+ BigInteger crtCoefficient) {
+ super(modulus, privateExponent);
+ this.publicExponent = publicExponent;
+ this.primeP = primeP;
+ this.primeQ = primeQ;
+ this.primeExponentP = primeExponentP;
+ this.primeExponentQ = primeExponentQ;
+ this.crtCoefficient = crtCoefficient;
+ }
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent
+ */
+ public BigInteger getPublicExponent() {
+ return this.publicExponent;
+ }
+
+ /**
+ * Returns the primeP.
+
+ * @return the primeP
+ */
+ public BigInteger getPrimeP() {
+ return this.primeP;
+ }
+
+ /**
+ * Returns the primeQ.
+ *
+ * @return the primeQ
+ */
+ public BigInteger getPrimeQ() {
+ return this.primeQ;
+ }
+
+ /**
+ * Returns the primeExponentP.
+ *
+ * @return the primeExponentP
+ */
+ public BigInteger getPrimeExponentP() {
+ return this.primeExponentP;
+ }
+
+ /**
+ * Returns the primeExponentQ.
+ *
+ * @return the primeExponentQ
+ */
+ public BigInteger getPrimeExponentQ() {
+ return this.primeExponentQ;
+ }
+
+ /**
+ * Returns the crtCoefficient.
+ *
+ * @return the crtCoefficient
+ */
+ public BigInteger getCrtCoefficient() {
+ return this.crtCoefficient;
+ }
+}
diff --git a/java/security/spec/RSAPrivateKeySpec.java b/java/security/spec/RSAPrivateKeySpec.java
new file mode 100644
index 0000000..e749146
--- /dev/null
+++ b/java/security/spec/RSAPrivateKeySpec.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1998, 2001, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies an RSA private key.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see PKCS8EncodedKeySpec
+ * @see RSAPublicKeySpec
+ * @see RSAPrivateCrtKeySpec
+ */
+
+public class RSAPrivateKeySpec implements KeySpec {
+
+ private BigInteger modulus;
+ private BigInteger privateExponent;
+
+ /**
+ * Creates a new RSAPrivateKeySpec.
+ *
+ * @param modulus the modulus
+ * @param privateExponent the private exponent
+ */
+ public RSAPrivateKeySpec(BigInteger modulus, BigInteger privateExponent) {
+ this.modulus = modulus;
+ this.privateExponent = privateExponent;
+ }
+
+ /**
+ * Returns the modulus.
+ *
+ * @return the modulus
+ */
+ public BigInteger getModulus() {
+ return this.modulus;
+ }
+
+ /**
+ * Returns the private exponent.
+ *
+ * @return the private exponent
+ */
+ public BigInteger getPrivateExponent() {
+ return this.privateExponent;
+ }
+}
diff --git a/java/security/spec/RSAPublicKeySpec.java b/java/security/spec/RSAPublicKeySpec.java
new file mode 100644
index 0000000..9a944f9
--- /dev/null
+++ b/java/security/spec/RSAPublicKeySpec.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1998, 2001, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+
+/**
+ * This class specifies an RSA public key.
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see X509EncodedKeySpec
+ * @see RSAPrivateKeySpec
+ * @see RSAPrivateCrtKeySpec
+ */
+
+public class RSAPublicKeySpec implements KeySpec {
+
+ private BigInteger modulus;
+ private BigInteger publicExponent;
+
+ /**
+ * Creates a new RSAPublicKeySpec.
+ *
+ * @param modulus the modulus
+ * @param publicExponent the public exponent
+ */
+ public RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent) {
+ this.modulus = modulus;
+ this.publicExponent = publicExponent;
+ }
+
+ /**
+ * Returns the modulus.
+ *
+ * @return the modulus
+ */
+ public BigInteger getModulus() {
+ return this.modulus;
+ }
+
+ /**
+ * Returns the public exponent.
+ *
+ * @return the public exponent
+ */
+ public BigInteger getPublicExponent() {
+ return this.publicExponent;
+ }
+}
diff --git a/java/security/spec/X509EncodedKeySpec.java b/java/security/spec/X509EncodedKeySpec.java
new file mode 100644
index 0000000..b9984de
--- /dev/null
+++ b/java/security/spec/X509EncodedKeySpec.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+/**
+ * This class represents the ASN.1 encoding of a public key,
+ * encoded according to the ASN.1 type {@code SubjectPublicKeyInfo}.
+ * The {@code SubjectPublicKeyInfo} syntax is defined in the X.509
+ * standard as follows:
+ *
+ * <pre>
+ * SubjectPublicKeyInfo ::= SEQUENCE {
+ * algorithm AlgorithmIdentifier,
+ * subjectPublicKey BIT STRING }
+ * </pre>
+ *
+ * @author Jan Luehe
+ *
+ *
+ * @see java.security.Key
+ * @see java.security.KeyFactory
+ * @see KeySpec
+ * @see EncodedKeySpec
+ * @see PKCS8EncodedKeySpec
+ *
+ * @since 1.2
+ */
+
+public class X509EncodedKeySpec extends EncodedKeySpec {
+
+ /**
+ * Creates a new X509EncodedKeySpec with the given encoded key.
+ *
+ * @param encodedKey the key, which is assumed to be
+ * encoded according to the X.509 standard. The contents of the
+ * array are copied to protect against subsequent modification.
+ * @exception NullPointerException if {@code encodedKey}
+ * is null.
+ */
+ public X509EncodedKeySpec(byte[] encodedKey) {
+ super(encodedKey);
+ }
+
+ /**
+ * Returns the key bytes, encoded according to the X.509 standard.
+ *
+ * @return the X.509 encoding of the key. Returns a new array
+ * each time this method is called.
+ */
+ public byte[] getEncoded() {
+ return super.getEncoded();
+ }
+
+ /**
+ * Returns the name of the encoding format associated with this
+ * key specification.
+ *
+ * @return the string {@code "X.509"}.
+ */
+ public final String getFormat() {
+ return "X.509";
+ }
+}
diff --git a/java/security/spec/package-info.java b/java/security/spec/package-info.java
new file mode 100644
index 0000000..92f30be
--- /dev/null
+++ b/java/security/spec/package-info.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides classes and interfaces for key specifications and algorithm
+ * parameter specifications.
+ *
+ * <p>A key specification is a transparent representation of the key material
+ * that constitutes a key. A key may be specified in an algorithm-specific
+ * way, or in an algorithm-independent encoding format (such as ASN.1).
+ * This package contains key specifications for DSA public and private keys,
+ * RSA public and private keys, PKCS #8 private keys in DER-encoded format,
+ * and X.509 public and private keys in DER-encoded format.
+ *
+ * <p>An algorithm parameter specification is a transparent representation
+ * of the sets of parameters used with an algorithm. This package contains
+ * an algorithm parameter specification for parameters used with the
+ * DSA algorithm.
+ *
+ * <h2>Package Specification</h2>
+ *
+ * <ul>
+ * <li>PKCS #1: RSA Encryption Standard, Version 1.5, November 1993</li>
+ * <li>PKCS #8: Private-Key Information Syntax Standard,
+ * Version 1.2, November 1993</li>
+ * <li>Federal Information Processing Standards Publication (FIPS PUB) 186:
+ * Digital Signature Standard (DSS)</li>
+ * </ul>
+ *
+ * <h2>Related Documentation</h2>
+ *
+ * For documentation that includes information about algorithm parameter
+ * and key specifications, please see:
+ * <ul>
+ * <li>
+ * <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/CryptoSpec.html">
+ * <b>Java™
+ * Cryptography Architecture API Specification and Reference
+ * </b></a></li>
+ * <li>
+ * <a href=
+ * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/crypto/HowToImplAProvider.html">
+ * <b>How to Implement a Provider for the
+ * Java™ Cryptography Architecture
+ * </b></a></li>
+ * </ul>
+ *
+ * @since 1.2
+ */
+package java.security.spec;