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 &amp; 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 &quot;wrapping&quot;
+     * 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 &amp; 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 &amp; 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 &amp; 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 &amp;
+         * 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 &amp;
+         * 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&trade; 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&trade; 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 &quot;Crypto&quot; 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 &amp; 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 &amp; 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&trade;
+ *     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&trade;
+ *     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&trade;
+ *     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&trade; 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&trade;
+ *       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&trade;
+ *     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&trade;
+ *     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&trade;
+ *     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&trade; 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&trade; 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&trade; 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} &gt; {@code k} &gt;= 1) or a
+     * pentanomial (X^{@code m} + X^{@code k3}
+     * + X^{@code k2} + X^{@code k1} + 1 with
+     * {@code m} &gt; {@code k3} &gt; {@code k2}
+     * &gt; {@code k1} &gt;= 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} &gt; {@code k} &gt;= 1) or a
+     * pentanomial (X^{@code m} + X^{@code k3}
+     * + X^{@code k2} + X^{@code k1} + 1 with
+     * {@code m} &gt; {@code k3} &gt; {@code k2}
+     * &gt; {@code k1} &gt;= 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&trade;
+ *       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&trade; Cryptography Architecture
+ *       </b></a></li>
+ * </ul>
+ *
+ * @since 1.2
+ */
+package java.security.spec;