diff options
Diffstat (limited to 'libraries/spongycastle/core/src/main/jdk1.1/java/security/cert')
43 files changed, 8721 insertions, 0 deletions
diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java new file mode 100644 index 000000000..2eb219e07 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRL.java @@ -0,0 +1,20 @@ + +package java.security.cert; + +public abstract class CRL +{ + private String type; + + protected CRL(String type) + { + this.type = type; + } + + public final String getType() + { + return type; + } + + public abstract boolean isRevoked(Certificate cert); + public abstract String toString(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java new file mode 100644 index 000000000..f079b8beb --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLException.java @@ -0,0 +1,16 @@ + +package java.security.cert; + +import java.security.GeneralSecurityException; + +public class CRLException extends GeneralSecurityException +{ + public CRLException() + { + } + + public CRLException(String msg) + { + super(msg); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java new file mode 100644 index 000000000..2e4ff616a --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CRLSelector.java @@ -0,0 +1,39 @@ +package java.security.cert; + +/** + * A selector that defines a set of criteria for selecting <code>CRL</code>s. + * Classes that implement this interface are often used to specify + * which <code>CRL</code>s should be retrieved from a <code>CertStore</code>.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public interface CRLSelector extends Cloneable +{ + /** + * Decides whether a <code>CRL</code> should be selected. + * + * @param crl the <code>CRL</code> to be checked + * + * @return <code>true</code> if the <code>CRL</code> should be selected, + * <code>false</code> otherwise + */ + public boolean match(CRL crl); + + /** + * Makes a copy of this <code>CRLSelector</code>. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this <code>CRLSelector</code> + */ + public Object clone(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java new file mode 100644 index 000000000..ceb5cd189 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPath.java @@ -0,0 +1,283 @@ +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; +import java.util.ListIterator; + +/** + * An immutable sequence of certificates (a certification path).<br /> + * <br /> + * This is an abstract class that defines the methods common to all + * CertPaths. Subclasses can handle different kinds of certificates + * (X.509, PGP, etc.).<br /> + * <br /> + * All CertPath objects have a type, a list of Certificates, and one + * or more supported encodings. Because the CertPath class is + * immutable, a 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.<br /> + * <br /> + * The type is a String that identifies the type of Certificates in + * the certification path. For each certificate cert in a + * certification path certPath, + * cert.getType().equals(certPath.getType()) must be true.<br /> + * <br /> + * The list of Certificates is an ordered List of zero or more + * Certificates. This List and all of the Certificates contained in it + * must be immutable.<br /> + * <br /> + * Each 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 CertPath is considered the default encoding. This + * encoding is used if no encoding is explicitly requested (for the + * {@link #getEncoded()} method, for instance).<br /> + * <br /> + * All CertPath objects are also Serializable. CertPath objects are + * resolved into an alternate {@link CertPathRep} object during + * serialization. This allows a CertPath object to be serialized into + * an equivalent representation regardless of its underlying + * implementation.<br /> + * <br /> + * CertPath objects can be created with a CertificateFactory or they + * can be returned by other classes, such as a CertPathBuilder.<br /> + * <br /> + * By convention, X.509 CertPaths (consisting of X509Certificates), + * 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 CertPaths may not follow + * these conventions. PKIX CertPathValidators will detect any + * departure from these conventions that cause the certification path + * to be invalid and throw a CertPathValidatorException.<br /> + * <br /> + * <strong>Concurrent Access</strong><br /> + * <br /> + * All CertPath objects must be thread-safe. That is, multiple threads + * may concurrently invoke the methods defined in this class on a + * single CertPath object (or more than one) with no ill effects. This + * is also true for the List returned by CertPath.getCertificates.<br /> + * <br /> + * Requiring 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 CertPath and List objects in + * question are immutable. + * + * @see CertificateFactory + * @see CertPathBuilder + */ +public abstract class CertPath extends Object implements Serializable +{ + private String type; + + /** + * Alternate <code>CertPath</code> class for serialization. + **/ + protected static class CertPathRep + implements Serializable + { + private String type; + private byte[] data; + + /** + * Creates a <code>CertPathRep</code> with the specified + * type and encoded form of a certification path. + * + * @param type the standard name of a CertPath + * @param typedata the encoded form of the certification + * path + **/ + protected CertPathRep(String type, byte[] data) + { + this.type = type; + this.data = data; + } + + /** + * Returns a CertPath constructed from the type and data. + * + * @return the resolved CertPath object + * @exception ObjectStreamException if a CertPath could not be constructed + **/ + protected Object readResolve() + throws ObjectStreamException + { + try { + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + CertificateFactory cf = CertificateFactory.getInstance(type); + return cf.generateCertPath(inStream); + } catch ( CertificateException ce ) { + throw new NotSerializableException(" java.security.cert.CertPath: " + type); + } + } + } + + /** + * Creates a CertPath of the specified type. + * This constructor is protected because most users should use + * a CertificateFactory to create CertPaths. + * @param type the standard name of the type of Certificatesin this path + **/ + protected CertPath(String type) + { + this.type = type; + } + + /** + * Returns the type of Certificates in this certification + * path. This is the same string that would be returned by + * {@link Certificate#getType() cert.getType()} for all + * Certificates in the certification path. + * + * @return the type of Certificates 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 Iterator via its + * remove method result in an UnsupportedOperationException. + * + * @return an Iterator over the names of the supported encodings (as Strings) + **/ + public abstract Iterator getEncodings(); + + /** + * Compares this certification path for equality with the + * specified object. Two CertPaths are equal if and only if + * their types are equal and their certificate Lists (and by + * implication the Certificates in those Lists) are equal. A + * CertPath is never equal to an object that is not a + * CertPath.<br /> + * <br /> + * 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 + * + * @see Object#hashCode() Object.hashCode() + **/ + public boolean equals(Object other) + { + if (!( other instanceof CertPath ) ) + return false; + + CertPath otherCertPath = (CertPath)other; + if ( ! getType().equals(otherCertPath.getType()) ) + return false; + return getCertificates().equals(otherCertPath.getCertificates()); + } + + /** + * 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> + * hashCode = path.getType().hashCode(); + * hashCode = 31 * hashCode + path.getCertificates().hashCode(); + * </pre> + * This ensures that path1.equals(path2) implies that + * path1.hashCode()==path2.hashCode() for any two + * certification paths, path1 and path2, as required by the + * general contract of Object.hashCode. + * + * @return The hashcode value for this certification path + * + * @see #equals(Object) + **/ + public int hashCode() + { + return getType().hashCode() * 31 + getCertificates().hashCode(); + } + + /** + * Returns a string representation of this certification + * path. This calls the toString method on each of the + * Certificates in the path. + * + * @return a string representation of this certification path + **/ + public String toString() + { + StringBuffer s = new StringBuffer(); + List certs = getCertificates(); + ListIterator iter = certs.listIterator(); + s.append('\n').append(getType()).append(" Cert Path: length = ").append(certs.size()).append("\n[\n"); + while ( iter.hasNext() ) { + s.append("=========================================================Certificate ").append(iter.nextIndex()).append('\n'); + s.append(iter.next()).append('\n'); + s.append("========================================================Certificate end\n\n\n"); + } + s.append("\n]"); + return s.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 List returned must be immutable and thread-safe. + * + * @return an immutable List of Certificates (may be empty, but not null) + **/ + public abstract List getCertificates(); + + /** + * Replaces the CertPath to be serialized with a CertPathRep + * object. + * + * @return the CertPathRep to be serialized + * + * @exception ObjectStreamException if a CertPathRep object + * representing this certification path could not be created + **/ + protected Object writeReplace() + throws ObjectStreamException + { + try { + return new CertPathRep( getType(), getEncoded() ); + } catch ( CertificateException ce ) { + throw new NotSerializableException( " java.security.cert.CertPath: " + getType() ); + } + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java new file mode 100644 index 000000000..b3adbf15f --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilder.java @@ -0,0 +1,243 @@ +package java.security.cert; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; + +/** + * A class for building certification paths (also known as certificate + * chains).<br /> + * <br /> + * This class uses a provider-based architecture, as described in the + * Java Cryptography Architecture. To create a + * <code>CertPathBuilder</code>, call one of the static + * <code>getInstance</code> methods, passing in the algorithm name of + * the CertPathBuilder desired and optionally the name of the provider + * desired.<br /> + * <br /> + * Once a <code>CertPathBuilder</code> 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 CertPath + * that was built) is returned in an object that implements the + * <code>CertPathBuilderResult</code> interface.<br /> + * <br /> + * <strong>Concurrent Access</strong><br /> + * <br /> + * 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.<br /> + * <br /> + * 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</code> + * instance concurrently should synchronize amongst themselves and + * provide the necessary locking. Multiple threads each manipulating a + * different <code>CertPathBuilder</code> instance need not + * synchronize.<br /> + * <br /> + * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes. + * + * @see CertUtil + **/ +public class CertPathBuilder extends Object +{ + private CertPathBuilderSpi builderSpi; + private Provider provider; + private String algorithm; + + /** + * Creates a 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 CertPathBuilder object that implements the + * specified algorithm.<br /> + * <br /> + * If the default provider package provides an implementation + * of the specified CertPathBuilder algorithm, an instance of + * CertPathBuilder containing that implementation is + * returned. If the requested algorithm is not available in + * the default package, other packages are searched.<br /> + * <br /> + * @param algorithm the name of the requested CertPathBuilder algorithm + * + * @return a CertPathBuilder object that implements the + * specified algorithm + * + * @exception NoSuchAlgorithmException if the requested + * algorithm is not available in the default provider package + * or any of the other provider packages that were searched + **/ + public static CertPathBuilder getInstance(String algorithm) + throws NoSuchAlgorithmException + { + try { + CertUtil.Implementation imp = + CertUtil.getImplementation("CertPathBuilder", algorithm, (String)null); + if (imp != null) + { + return new CertPathBuilder((CertPathBuilderSpi)imp.getEngine(), + imp.getProvider(), algorithm); + } + } catch ( NoSuchProviderException ex ) {} + throw new NoSuchAlgorithmException("can't find type " + algorithm); + } + + /** + * Returns a CertPathBuilder object that implements the + * specified algorithm, as supplied by the specified provider. + * + * @param algorithm the name of the requested CertPathBuilder + * algorithm + * @param provider the name of the provider + * + * @return a CertPathBuilder object that implements the + * specified algorithm, as supplied by the specified provider + * + * @exception NoSuchAlgorithmException if the requested algorithm + * is not available from the specified provider + * @exception NoSuchProviderException if the provider has not + * been configured + * @exception IllegalArgumentException if the provider is null + **/ + public static CertPathBuilder getInstance(String algorithm, + String provider) + throws NoSuchAlgorithmException, + NoSuchProviderException + { + if ( provider == null ) + throw new IllegalArgumentException("provider must be non-null"); + CertUtil.Implementation imp = + CertUtil.getImplementation("CertPathBuilder", algorithm, provider); + + if (imp != null) + { + return new CertPathBuilder((CertPathBuilderSpi)imp.getEngine(), + imp.getProvider(), algorithm); + } + throw new NoSuchAlgorithmException("can't find type " + algorithm); + } + + /** + * Returns a CertPathBuilder object that implements the + * specified algorithm, as supplied by the specified + * provider. Note: the provider doesn't have to be registered. + * + * @param algorithm the name of the requested CertPathBuilder + * algorithm + * @param provider the provider + * @return a CertPathBuilder object that implements the + * specified algorithm, as supplied by the specified provider + * + * @exception NoSuchAlgorithmException if the requested algorithm + * is not available from the specified provider + * @exception IllegalArgumentException if the provider is null. + **/ + public static CertPathBuilder getInstance(String algorithm, + Provider provider) + throws NoSuchAlgorithmException + { + if ( provider == null ) + throw new IllegalArgumentException("provider must be non-null"); + CertUtil.Implementation imp = + CertUtil.getImplementation("CertPathBuilder", algorithm, provider); + + if (imp != null) + { + return new CertPathBuilder((CertPathBuilderSpi)imp.getEngine(), + provider, algorithm); + } + throw new NoSuchAlgorithmException("can't find type " + algorithm); + } + + /** + * Returns the provider of this <code>CertPathBuilder</code>. + * + * @return the provider of this <code>CertPathBuilder</code> + **/ + public final Provider getProvider() + { + return provider; + } + + /** + * Returns the name of the algorithm of this + * <code>CertPathBuilder</code>. + * + * @return the name of the algorithm of this <code>CertPathBuilder</code> + **/ + public final String getAlgorithm() + { + return 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 + * + * @exception CertPathBuilderException if the builder is unable to construct + * a certification path that satisfies the specified parameters + * @exception InvalidAlgorithmParameterException if the specified parameters * are inappropriate for this <code>CertPathBuilder</code> + */ + public final CertPathBuilderResult build(CertPathParameters params) + throws CertPathBuilderException, + InvalidAlgorithmParameterException + { + return builderSpi.engineBuild(params); + } + + + /** + * Returns the default <code>CertPathBuilder</code> type as specified in + * the Java security properties file, or the string "PKIX" + * if no such property exists. The Java security properties file is + * located in the file named <JAVA_HOME>/lib/security/java.security, + * where <JAVA_HOME> refers to the directory where the SDK was + * installed.<br /> + * <br /> + * The default <code>CertPathBuilder</code> type can be used by + * applications that do not want to use a hard-coded type when calling one + * of the <code>getInstance</code> methods, and want to provide a default + * type in case a user does not specify its own.<br /> + * <br /> + * The default <code>CertPathBuilder</code> type can be changed by + * setting the value of the "certpathbuilder.type" security property + * (in the Java security properties file) to the desired type. + * + * @return the default <code>CertPathBuilder</code> type as specified + * in the Java security properties file, or the string "PKIX" + * if no such property exists. + */ + public static final String getDefaultType() + { + String defaulttype = null; + defaulttype = Security.getProperty("certpathbuilder.type"); + + if ( defaulttype == null || defaulttype.length() <= 0 ) + return "PKIX"; + else + return defaulttype; + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java new file mode 100644 index 000000000..13b60891e --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderException.java @@ -0,0 +1,182 @@ +package java.security.cert; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.security.GeneralSecurityException; + +/** + * An exception indicating one of a variety of problems encountered + * when building a certification path with a + * <code>CertPathBuilder</code>.<br /> + * <br /> + * A <code>CertPathBuilderException</code> provides support for + * wrapping exceptions. The {@link #getCause() getCause} method + * returns the throwable, if any, that caused this exception to be + * thrown.<br /> + * <br /> + * <strong>Concurrent Access</strong><br /> + * <br /> + * 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 + **/ +public class CertPathBuilderException extends GeneralSecurityException +{ + private Throwable cause; + + /** + * Creates a <code>CertPathBuilderException</code> with <code>null</code> + * as its detail message. + */ + public CertPathBuilderException() + { + } + + /** + * Creates a <code>CertPathBuilderException</code> with the given detail + * message. The detail message is a <code>String</code> that describes + * this particular exception in more detail. + * + * @param msg + * the detail message + */ + public CertPathBuilderException(String message) + { + super(message); + } + + /** + * Creates a <code>CertPathBuilderException</code> that wraps the + * specified throwable. This allows any exception to be converted into a + * <code>CertPathBuilderException</code>, 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())</code> (which typically + * contains the class and detail message of cause). + * + * @param cause + * the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is permitted, and + * indicates that the cause is nonexistent or unknown.) + */ + public CertPathBuilderException(String message, Throwable cause) + { + super(message); + this.cause = cause; + } + + /** + * Creates a <code>CertPathBuilderException</code> 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()} method). (A null value is permitted, and + * indicates that the cause is nonexistent or unknown.) + */ + public CertPathBuilderException(Throwable cause) + { + this.cause = cause; + } + + /** + * Returns the internal (wrapped) cause, or null if the cause is nonexistent + * or unknown. + * + * @return the cause of this throwable or <code>null</code> if the cause + * is nonexistent or unknown. + */ + public Throwable getCause() + { + return cause; + } + + /** + * Returns the detail message for this CertPathBuilderException. + * + * @return the detail message, or <code>null</code> if neither the message + * nor internal cause were specified + */ + public String getMessage() + { + String message = super.getMessage(); + + if (message == null && cause == null) + { + return null; + } + + if (cause != null) + { + return cause.getMessage(); + } + + return message; + } + + /** + * Returns a string describing this exception, including a description of + * the internal (wrapped) cause if there is one. + * + * @return a string representation of this + * <code>CertPathBuilderException</code> + */ + public String toString() + { + String message = getMessage(); + if (message == null) + { + return ""; + } + + return message; + } + + /** + * Prints a stack trace to <code>System.err</code>, including the + * backtrace of the cause, if any. + */ + public void printStackTrace() + { + printStackTrace(System.err); + } + + /** + * Prints a stack trace to a <code>PrintStream</code>, including the + * backtrace of the cause, if any. + * + * @param ps + * the <code>PrintStream</code> to use for output + */ + public void printStackTrace(PrintStream ps) + { + super.printStackTrace(ps); + if (getCause() != null) + { + getCause().printStackTrace(ps); + } + } + + /** + * Prints a stack trace to a <code>PrintWriter</code>, including the + * backtrace of the cause, if any. + * + * @param ps + * the <code>PrintWriter</code> to use for output + */ + public void printStackTrace(PrintWriter pw) + { + super.printStackTrace(pw); + if (getCause() != null) + { + getCause().printStackTrace(pw); + } + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java new file mode 100644 index 000000000..c0482bc4e --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderResult.java @@ -0,0 +1,38 @@ +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.<br /> + * <br /> + * At a minimum, a CertPathBuilderResult contains the CertPath built by the + * 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.<br /> + * <br /> + * <strong>Concurrent Access</strong><br /> + * <br /> + * 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. + **/ +public interface CertPathBuilderResult extends Cloneable +{ + /** + * Returns the built certification path. + * + * @return the certification path (never <code>null</code>) + */ + public CertPath getCertPath(); + + /** + * Makes a copy of this <code>CertPathBuilderResult</code>. + * Changes to the copy will not affect the original and vice + * versa. + * + * @return a copy of this CertPathBuilderResult + */ + public Object clone(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java new file mode 100644 index 000000000..be044fa30 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathBuilderSpi.java @@ -0,0 +1,50 @@ +package java.security.cert; + +import java.security.InvalidAlgorithmParameterException; + +/** + * The Service Provider Interface (SPI) for the CertPathBuilder + * class. All CertPathBuilder implementations must include a class + * (the SPI class) that extends this class (CertPathBuilderSpi) and + * implements all of its methods. In general, instances of this class + * should only be accessed through the CertPathBuilder class. For + * details, see the Java Cryptography Architecture.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * Instances of this class need not be protected against concurrent + * access from multiple threads. Threads that need to access a single + * CertPathBuilderSpi instance concurrently should synchronize amongst + * themselves and provide the necessary locking before calling the + * wrapping CertPathBuilder object.<br /> + * <br /> + * However, implementations of CertPathBuilderSpi may still encounter + * concurrency issues, since multiple threads each manipulating a + * different CertPathBuilderSpi instance need not synchronize. + **/ +public abstract class CertPathBuilderSpi + extends Object +{ + /** + * 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 + * + * @exception CertPathBuilderException if the builder is unable + * to construct a certification path that satisfies the + * specified + * @exception parametersInvalidAlgorithmParameterException if the + * specified parameters are inappropriate for this CertPathBuilder + */ + public abstract CertPathBuilderResult engineBuild( CertPathParameters params ) + throws CertPathBuilderException, + InvalidAlgorithmParameterException; +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java new file mode 100644 index 000000000..caff291a8 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathParameters.java @@ -0,0 +1,18 @@ +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 CertPath + * parameter specifications. All <code>CertPath</code> parameter specifications must + * implement this interface. + **/ +public interface CertPathParameters extends Cloneable +{ + /** + * Makes a copy of this <code>CertPathParameters</code>. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this <code>CertPathParameters</code> + **/ + public Object clone(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java new file mode 100644 index 000000000..aaddbf0e5 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidator.java @@ -0,0 +1,250 @@ +package java.security.cert; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; + +/** + * A class for validating certification paths (also known as certificate + * chains).<br /> + * <br /> + * This class uses a provider-based architecture, as described in the Java + * Cryptography Architecture. To create a <code>CertPathValidator</code>, + * call one of the static <code>getInstance</code> methods, passing in the + * algorithm name of the <code>CertPathValidator</code> desired and + * optionally the name of the provider desired. <br /> + * <br /> + * Once a <code>CertPathValidator</code> 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</code> to be validated + * and an algorithm-specific set of parameters. If successful, the result is + * returned in an object that implements the + * <code>CertPathValidatorResult</code> interface.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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.<br /> + * <br /> + * 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</code> instance concurrently should + * synchronize amongst themselves and provide the necessary locking. Multiple + * threads each manipulating a different <code>CertPathValidator</code> + * instance need not synchronize.<br /> + * <br /> + * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes. + * + * @see CertPath + * @see CertUtil + **/ +public class CertPathValidator extends Object +{ + private CertPathValidatorSpi validatorSpi; + private Provider provider; + private String algorithm; + + /** + * Creates a <code>CertPathValidator</code> 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</code> object that implements the + * specified algorithm.<br /> + * <br /> + * If the default provider package provides an implementation of the + * specified <code>CertPathValidator</code> algorithm, an instance of + * <code>CertPathValidator</code> containing that implementation is + * returned. If the requested algorithm is not available in the default + * package, other packages are searched. + * + * @param algorithm the name of the requested <code>CertPathValidator</code> + * algorithm + * + * @return a <code>CertPathValidator</code> object that implements the + * specified algorithm + * + * @exception NoSuchAlgorithmException if the requested algorithm + * is not available in the default provider package or any of the other + * provider packages that were searched + */ + public static CertPathValidator getInstance(String algorithm) + throws NoSuchAlgorithmException + { + try { + CertUtil.Implementation imp = + CertUtil.getImplementation("CertPathValidator", algorithm, (String)null ); + if (imp != null) + { + return new CertPathValidator((CertPathValidatorSpi)imp.getEngine(), imp.getProvider(), algorithm); + } + } catch (NoSuchProviderException ex ) {} + throw new NoSuchAlgorithmException("can't find algorithm " + algorithm); + } + + /** + * Returns a <code>CertPathValidator</code> object that implements the + * specified algorithm, as supplied by the specified provider. + * + * @param algorithm the name of the requested <code>CertPathValidator</code> + * algorithm + * @param provider the name of the provider + * + * @return a <code>CertPathValidator</code> object that implements the + * specified algorithm, as supplied by the specified provider + * + * @exception NoSuchAlgorithmException if the requested algorithm + * is not available from the specified provider + * @exception NoSuchProviderException if the provider has not been + * configured + * @exception IllegalArgumentException if the <code>provider</code> is + * null + */ + public static CertPathValidator getInstance(String algorithm, + String provider) + throws NoSuchAlgorithmException, + NoSuchProviderException + { + if ( provider == null ) + throw new IllegalArgumentException("provider must be non-null"); + + CertUtil.Implementation imp = CertUtil.getImplementation("CertPathValidator", algorithm, provider ); + if (imp != null) + { + return new CertPathValidator((CertPathValidatorSpi)imp.getEngine(), imp.getProvider(), algorithm); + } + throw new NoSuchAlgorithmException("can't find algorithm " + algorithm); + } + + /** + * Returns a <code>CertPathValidator</code> object that implements the + * specified algorithm, as supplied by the specified provider. + * Note: the <code>provider</code> doesn't have to be registered. + * + * @param algorithm the name of the requested + * <code>CertPathValidator</code> algorithm + * @param provider the provider + * + * @return a <code>CertPathValidator</code> object that implements the + * specified algorithm, as supplied by the specified provider + * + * @exception NoSuchAlgorithmException if the requested algorithm + * is not available from the specified provider + * @exception IllegalArgumentException if the <code>provider</code> is + * null + */ + public static CertPathValidator getInstance(String algorithm, + Provider provider) + throws NoSuchAlgorithmException + { + if ( provider == null ) + throw new IllegalArgumentException("provider must be non-null"); + + CertUtil.Implementation imp = CertUtil.getImplementation("CertPathValidator", algorithm, provider ); + if (imp != null) + { + return new CertPathValidator((CertPathValidatorSpi)imp.getEngine(), provider, algorithm); + } + throw new NoSuchAlgorithmException("can't find algorithm " + algorithm); + } + + /** + * Returns the <code>Provider</code> of this + * <code>CertPathValidator</code>. + * + * @return the <code>Provider</code> of this <code>CertPathValidator</code> + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Returns the algorithm name of this <code>CertPathValidator</code>. + * + * @return the algorithm name of this <code>CertPathValidator</code> + */ + public final String getAlgorithm() + { + return algorithm; + } + + /** + * Validates the specified certification path using the specified + * algorithm parameter set.<br /> + * <br /> + * The <code>CertPath</code> specified must be of a type that is + * supported by the validation algorithm, otherwise an + * <code>InvalidAlgorithmParameterException</code> will be thrown. For + * example, a <code>CertPathValidator</code> that implements the PKIX + * algorithm validates <code>CertPath</code> objects of type X.509. + * + * @param certPath the <code>CertPath</code> to be validated + * @param params the algorithm parameters + * + * @return the result of the validation algorithm + * + * @exception CertPathValidatorException if the <code>CertPath</code> + * does not validate + * @exception InvalidAlgorithmParameterException if the specified + * parameters or the type of the specified <code>CertPath</code> are + * inappropriate for this <code>CertPathValidator</code> + */ + public final CertPathValidatorResult validate( CertPath certPath, + CertPathParameters params) + throws CertPathValidatorException, + InvalidAlgorithmParameterException + { + return validatorSpi.engineValidate( certPath, params ); + } + + + /** + * Returns the default <code>CertPathValidator</code> type as specified in + * the Java security properties file, or the string "PKIX" + * if no such property exists. The Java security properties file is + * located in the file named <JAVA_HOME>/lib/security/java.security, + * where <JAVA_HOME> refers to the directory where the SDK was + * installed.<br /> + * <br /> + * The default <code>CertPathValidator</code> type can be used by + * applications that do not want to use a hard-coded type when calling one + * of the <code>getInstance</code> methods, and want to provide a default + * type in case a user does not specify its own.<br /> + * <br /> + * The default <code>CertPathValidator</code> type can be changed by + * setting the value of the "certpathvalidator.type" security property + * (in the Java security properties file) to the desired type. + * + * @return the default <code>CertPathValidator</code> type as specified + * in the Java security properties file, or the string "PKIX" + * if no such property exists. + */ + public static final String getDefaultType() + { + String defaulttype = null; + defaulttype = Security.getProperty("certpathvalidator.type"); + + if ( defaulttype == null || defaulttype.length() <= 0 ) + return "PKIX"; + else + return defaulttype; + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java new file mode 100644 index 000000000..2088ab1a4 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorException.java @@ -0,0 +1,248 @@ +package java.security.cert; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.security.GeneralSecurityException; + +/** + * An exception indicating one of a variety of problems encountered when + * validating a certification path. <br /> + * <br /> + * A <code>CertPathValidatorException</code> provides support for wrapping + * exceptions. The {@link #getCause getCause} method returns the throwable, + * if any, that caused this exception to be thrown. <br /> + * <br /> + * A <code>CertPathValidatorException</code> may also include the + * certification path that was being validated when the exception was thrown + * and the index of the certificate in the certification path that caused the + * exception to be thrown. Use the {@link #getCertPath getCertPath} and + * {@link #getIndex getIndex} methods to retrieve this information.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public class CertPathValidatorException extends GeneralSecurityException +{ + private Throwable cause; + private CertPath certPath; + private int index = -1; + + /** + * Creates a <code>CertPathValidatorException</code> with + * no detail message. + */ + public CertPathValidatorException() + { + super(); + } + + /** + * Creates a <code>CertPathValidatorException</code> with the given + * detail message. A detail message is a <code>String</code> that + * describes this particular exception. + * + * @param messag the detail message + */ + public CertPathValidatorException(String message) + { + super(message); + } + + /** + * Creates a <code>CertPathValidatorException</code> 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</code> value is + * permitted, and indicates that the cause is nonexistent or unknown.) + */ + public CertPathValidatorException(String message, Throwable cause) + { + super(message); + this.cause = cause; + } + + /** + * Creates a <code>CertPathValidatorException</code> with the specified + * detail message, cause, certification path, and index. + * + * @param msg the detail message (or <code>null</code> if none) + * @param cause the cause (or <code>null</code> 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</code> is zero based. + * + * @exception IndexOutOfBoundsException if the index is out of range + * <code>(index < -1 || (certPath != null && index >= + * certPath.getCertificates().size())</code> + * @exception IllegalArgumentException if <code>certPath</code> is + * <code>null</code> and <code>index</code> is not -1 + */ + public CertPathValidatorException(String message, Throwable cause, CertPath certPath, int index) + { + super( message ); + + if ( certPath == null && index != -1 ) + throw new IllegalArgumentException( "certPath = null and index != -1" ); + if ( index < -1 || ( certPath != null && index >= certPath.getCertificates().size() ) ) + throw new IndexOutOfBoundsException( " index < -1 or out of bound of certPath.getCertificates()" ); + + this.cause = cause; + this.certPath = certPath; + this.index = index; + } + + /** + * Creates a <code>CertPathValidatorException</code> that wraps the + * specified throwable. This allows any exception to be converted into a + * <code>CertPathValidatorException</code>, 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() + * </code>) (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</code> value is + * permitted, and indicates that the cause is nonexistent or unknown.) + */ + public CertPathValidatorException(Throwable cause) + { + this.cause = cause; + } + + /** + * Returns the detail message for this + * <code>CertPathValidatorException</code>. + * + * @return the detail message, or <code>null</code> if neither the message + * nor cause were specified + */ + public String getMessage() + { + String message = super.getMessage(); + + if ( message == null && cause == null ) + return null; + + StringBuffer s = new StringBuffer(); + if ( message != null ) + { + s.append(message).append('\n'); + } + if ( cause != null ) + { + s.append("Cause:\n").append(cause.getMessage()).append('\n'); + } + return s.toString(); + } + + /** + * Returns the certification path that was being validated when + * the exception was thrown. + * + * @return the <code>CertPath</code> that was being validated when + * the exception was thrown (or <code>null</code> if not specified) + */ + public CertPath getCertPath() + { + return 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</code> 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 index; + } + + /** + * Returns the cause of this <code>CertPathValidatorException</code> or + * <code>null</code> if the cause is nonexistent or unknown. + * + * @return the cause of this throwable or <code>null</code> if the cause + * is nonexistent or unknown. + */ + public Throwable getCause() + { + return cause; + } + + /** + * Returns a string describing this exception, including a description + * of the internal (wrapped) cause if there is one. + * + * @return a string representation of this + * <code>CertPathValidatorException</code> + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + String s = getMessage(); + if ( s != null ) + { + sb.append( s ); + } + if ( getIndex() >= 0 ) + { + sb.append("index in certpath: ").append(getIndex()).append('\n'); + sb.append(getCertPath()); + } + return sb.toString(); + } + + /** + * Prints a stack trace to <code>System.err</code>, including the backtrace + * of the cause, if any. + */ + public void printStackTrace() + { + printStackTrace(System.err); + } + + /** + * Prints a stack trace to a <code>PrintStream</code>, including the + * backtrace of the cause, if any. + * + * @param ps the <code>PrintStream</code> to use for output + */ + public void printStackTrace(PrintStream ps) + { + super.printStackTrace(ps); + if ( getCause() != null ) + { + getCause().printStackTrace(ps); + } + } + + /** + * Prints a stack trace to a <code>PrintWriter</code>, including the + * backtrace of the cause, if any. + * + * @param pw the <code>PrintWriter</code> to use for output + */ + public void printStackTrace(PrintWriter pw) + { + super.printStackTrace(pw); + if ( getCause() != null ) + { + getCause().printStackTrace(pw); + } + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java new file mode 100644 index 000000000..ec09641d5 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorResult.java @@ -0,0 +1,22 @@ +package java.security.cert; + +/** + * A specification of the result of a certification path validator algorithm.<br /> + * <br /> + * 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 + **/ +public interface CertPathValidatorResult extends Cloneable +{ + /** + * Makes a copy of this <code>CertPathValidatorResult</code>. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this <code>CertPathValidatorResult</code> + */ + public Object clone(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java new file mode 100644 index 000000000..c70bc47fc --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertPathValidatorSpi.java @@ -0,0 +1,59 @@ +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</code> implementations must include a class (the + * SPI class) that extends this class (<code>CertPathValidatorSpi</code>) + * and implements all of its methods. In general, instances of this class + * should only be accessed through the <code>CertPathValidator</code> class. + * For details, see the Java Cryptography Architecture.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * Instances of this class need not be protected against concurrent + * access from multiple threads. Threads that need to access a single + * <code>CertPathValidatorSpi</code> instance concurrently should synchronize + * amongst themselves and provide the necessary locking before calling the + * wrapping <code>CertPathValidator</code> object.<br /> + * <br /> + * However, implementations of <code>CertPathValidatorSpi</code> may still + * encounter concurrency issues, since multiple threads each + * manipulating a different <code>CertPathValidatorSpi</code> instance need not + * synchronize. + **/ +public abstract class CertPathValidatorSpi extends Object +{ + /** + * The default constructor. + */ + public CertPathValidatorSpi() {} + + /** + * Validates the specified certification path using the specified + * algorithm parameter set.<br /> + * <br /> + * The <code>CertPath</code> specified must be of a type that is + * supported by the validation algorithm, otherwise an + * <code>InvalidAlgorithmParameterException</code> will be thrown. For + * example, a <code>CertPathValidator</code> that implements the PKIX + * algorithm validates <code>CertPath</code> objects of type X.509. + * + * @param certPath the <code>CertPath</code> to be validated + * @param params the algorithm parameters + * + * @return the result of the validation algorithm + * + * @exception CertPathValidatorException if the <code>CertPath</code> + * does not validate + * @exception InvalidAlgorithmParameterException if the specified + * parameters or the type of the specified <code>CertPath</code> are + * inappropriate for this <code>CertPathValidator</code> + */ + public abstract CertPathValidatorResult engineValidate(CertPath certPath, CertPathParameters params) + throws CertPathValidatorException, + InvalidAlgorithmParameterException; +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java new file mode 100644 index 000000000..31bf97448 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertSelector.java @@ -0,0 +1,39 @@ +package java.security.cert; + +/** + * A selector that defines a set of criteria for selecting + * <code>Certificate</code>s. Classes that implement this interface + * are often used to specify which <code>Certificate</code>s should + * be retrieved from a <code>CertStore</code>.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + */ +public interface CertSelector extends Cloneable +{ + /** + * Decides whether a <code>Certificate</code> should be selected. + * + * @param cert the <code>Certificate</code> to be checked + * @return <code>true</code> if the <code>Certificate</code> + * should be selected, <code>false</code> otherwise + */ + public boolean match(Certificate cert); + + /** + * Makes a copy of this <code>CertSelector</code>. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this <code>CertSelector</code> + */ + public Object clone(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java new file mode 100644 index 000000000..0e2c6d2f7 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStore.java @@ -0,0 +1,352 @@ +package java.security.cert; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; +import java.util.Collection; + +/** + * A class for retrieving <code>Certificate</code>s and <code>CRL</code>s + * from a repository.<br /> + * <br /> + * This class uses a provider-based architecture, as described in the + * Java Cryptography Architecture. + * To create a <code>CertStore</code>, call one of the static + * <code>getInstance</code> methods, passing in the type of + * <code>CertStore</code> desired, any applicable initialization parameters + * and optionally the name of the provider desired. <br /> + * <br /> + * Once the <code>CertStore</code> has been created, it can be used to + * retrieve <code>Certificate</code>s and <code>CRL</code>s by calling its + * {@link #getCertificates(CertSelector selector) getCertificates} and + * {@link #getCRLs(CRLSelector selector) getCRLs} methods.<br /> + * <br /> + * Unlike a {@link java.security.KeyStore KeyStore}, which provides access + * to a cache of private keys and trusted certificates, a + * <code>CertStore</code> is designed to provide access to a potentially + * vast repository of untrusted certificates and CRLs. For example, an LDAP + * implementation of <code>CertStore</code> 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. See Appendix A in the + * Java Certification Path API Programmer's Guide for more information about + * standard <code>CertStore</code> types.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * All public methods of <code>CertStore</code> objects must be thread-safe. + * That is, multiple threads may concurrently invoke these methods on a + * single <code>CertStore</code> object (or more than one) with no + * ill effects. This allows a <code>CertPathBuilder</code> to search for a + * CRL while simultaneously searching for further certificates, for instance.<br /> + * <br /> + * 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.<br /> + * <br /> + * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes. + * + * @see CertUtil + **/ +public class CertStore extends Object +{ + private CertStoreSpi storeSpi; + private Provider provider; + private String type; + private CertStoreParameters params; + + /** + * Creates a <code>CertStore</code> 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</code>) + */ + protected CertStore( CertStoreSpi storeSpi, + Provider provider, + String type, + CertStoreParameters params ) + { + this.storeSpi = storeSpi; + this.provider = provider; + this.type = type; + this.params = params; + } + + /** + * Returns a <code>Collection</code> of <code>Certificate</code>s that + * match the specified selector. If no <code>Certificate</code>s + * match the selector, an empty <code>Collection</code> will be returned.<br /> + * <br /> + * For some <code>CertStore</code> types, the resulting + * <code>Collection</code> may not contain <b>all</b> of the + * <code>Certificate</code>s that match the selector. For instance, + * an LDAP <code>CertStore</code> may not search all entries in the + * directory. Instead, it may just search entries that are likely to + * contain the <code>Certificate</code>s it is looking for.<br /> + * <br /> + * Some <code>CertStore</code> implementations (especially LDAP + * <code>CertStore</code>s) may throw a <code>CertStoreException</code> + * unless a non-null <code>CertSelector</code> 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</code> used to select which + * <code>Certificate</code>s should be returned. Specify <code>null</code> + * to return all <code>Certificate</code>s (if supported). + * + * @return A <code>Collection</code> of <code>Certificate</code>s that + * match the specified selector (never <code>null</code>) + * @exception CertStoreException if an exception occurs + */ + public final Collection getCertificates( CertSelector selector ) + throws CertStoreException + { + return storeSpi.engineGetCertificates( selector ); + } + + /** + * Returns a <code>Collection</code> of <code>CRL</code>s that + * match the specified selector. If no <code>CRL</code>s + * match the selector, an empty <code>Collection</code> will be returned.<br /> + * <br /> + * For some <code>CertStore</code> types, the resulting + * <code>Collection</code> may not contain <b>all</b> of the + * <code>CRL</code>s that match the selector. For instance, + * an LDAP <code>CertStore</code> may not search all entries in the + * directory. Instead, it may just search entries that are likely to + * contain the <code>CRL</code>s it is looking for.<br /> + * <br /> + * Some <code>CertStore</code> implementations (especially LDAP + * <code>CertStore</code>s) may throw a <code>CertStoreException</code> + * unless a non-null <code>CRLSelector</code> 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</code> used to select which + * <code>CRL</code>s should be returned. Specify <code>null</code> + * to return all <code>CRL</code>s (if supported). + * + * @return A <code>Collection</code> of <code>CRL</code>s that + * match the specified selector (never <code>null</code>) + * + * @exception CertStoreException if an exception occurs + */ + public final Collection getCRLs( CRLSelector selector ) + throws CertStoreException + { + return storeSpi.engineGetCRLs( selector ); + } + + /** + * Returns a <code>CertStore</code> object that implements the specified + * <code>CertStore</code> type and is initialized with the specified + * parameters.<br /> + * <br /> + * If the default provider package provides an implementation + * of the specified <code>CertStore</code> type, an instance of + * <code>CertStore</code> containing that implementation is returned. + * If the requested type is not available in the default package, other + * packages are searched.<br /> + * <br /> + * The <code>CertStore</code> that is returned is initialized with the + * specified <code>CertStoreParameters</code>. The type of parameters + * needed may vary between different types of <code>CertStore</code>s. + * Note that the specified <code>CertStoreParameters</code> object is + * cloned. + * + * @param type the name of the requested <code>CertStore</code> type + * @param params the initialization parameters (may be <code>null</code>) + * + * @return a <code>CertStore</code> object that implements the specified + * <code>CertStore</code> type + * + * @exception NoSuchAlgorithmException if the requested type is not + * available in the default provider package or any of the other provider + * packages that were searched + * @exception InvalidAlgorithmParameterException if the specified + * initialization parameters are inappropriate for this + * <code>CertStore</code> + */ + public static CertStore getInstance( String type, + CertStoreParameters params) + throws InvalidAlgorithmParameterException, + NoSuchAlgorithmException + { + try { + CertUtil.Implementation imp = + CertUtil.getImplementation( "CertStore", type, (String)null, + new Class[] { CertStoreParameters.class }, + new Object[] { params } ); + if (imp != null) + { + return new CertStore((CertStoreSpi)imp.getEngine(), imp.getProvider(), type, params ); + } + } catch ( NoSuchProviderException ex ) {} + throw new NoSuchAlgorithmException("can't find type " + type); + } + + /** + * Returns a <code>CertStore</code> object that implements the specified + * <code>CertStore</code> type, as supplied by the specified provider + * and initialized with the specified parameters.<br /> + * <br /> + * The <code>CertStore</code> that is returned is initialized with the + * specified <code>CertStoreParameters</code>. The type of parameters + * needed may vary between different types of <code>CertStore</code>s. + * Note that the specified <code>CertStoreParameters</code> object is + * cloned. + * + * @param type the requested <code>CertStore</code> type + * @param params the initialization parameters (may be <code>null</code>) + * @param provider the name of the provider + * + * @return a <code>CertStore</code> object that implements the + * specified type, as supplied by the specified provider + * + * @exception NoSuchAlgorithmException if the requested type is not + * available from the specified provider + * @exception InvalidAlgorithmParameterException if the specified + * initialization parameters are inappropriate for this + * <code>CertStore</code> + * @exception NoSuchProviderException if the provider has not been configured + * @exception IllegalArgumentException if the <code>provider</code> is + * null + */ + public static CertStore getInstance( String type, + CertStoreParameters params, + String provider) + throws InvalidAlgorithmParameterException, + NoSuchAlgorithmException, + NoSuchProviderException, + IllegalArgumentException + { + if ( provider == null ) + throw new IllegalArgumentException( "provider must be non-null" ); + + CertUtil.Implementation imp = + CertUtil.getImplementation( "CertStore", type, provider, + new Class[] { CertStoreParameters.class }, + new Object[] { params } ); + if (imp != null) + { + return new CertStore((CertStoreSpi)imp.getEngine(), imp.getProvider(), type, params ); + } + throw new NoSuchAlgorithmException("can't find type " + type); + } + + /** + * Returns a <code>CertStore</code> object that implements the specified + * <code>CertStore</code> type, as supplied by the specified provider and + * initialized with the specified parameters. + * Note: the <code>provider</code> doesn't have to be registered.<br /> + * <br /> + * The <code>CertStore</code> that is returned is initialized with the + * specified <code>CertStoreParameters</code>. The type of parameters + * needed may vary between different types of <code>CertStore</code>s. + * Note that the specified <code>CertStoreParameters</code> object is + * cloned. + * + * @param type the requested <code>CertStore</code> type + * @param params the initialization parameters (may be <code>null</code>) + * @param provider the provider + * + * @return a <code>CertStore</code> object that implements the + * specified type, as supplied by the specified provider + * + * @exception NoSuchAlgorithmException if the requested type is not + * available from the specified provider + * @exception InvalidAlgorithmParameterException if the specified + * initialization parameters are inappropriate for this + * <code>CertStore</code> + * @exception IllegalArgumentException if the <code>provider</code> is + * null + */ + public static CertStore getInstance( String type, + CertStoreParameters params, + Provider provider ) + throws NoSuchAlgorithmException, + InvalidAlgorithmParameterException, + IllegalArgumentException + { + if ( provider == null ) + throw new IllegalArgumentException( "provider must be non-null" ); + CertUtil.Implementation imp = + CertUtil.getImplementation( "CertStore", type, provider, + new Class[] { CertStoreParameters.class }, + new Object[] { params } ); + if (imp != null) + { + return new CertStore((CertStoreSpi)imp.getEngine(), provider, type, params ); + } + throw new NoSuchAlgorithmException("can't find type " + type); + } + + /** + * Returns the parameters used to initialize this <code>CertStore</code>. + * Note that the <code>CertStoreParameters</code> object is cloned before + * it is returned. + * + * @return the parameters used to initialize this <code>CertStore</code> + * (may be <code>null</code>) + */ + public final CertStoreParameters getCertStoreParameters() + { + return params; + } + + /** + * Returns the type of this <code>CertStore</code>. + * + * @return the type of this <code>CertStore</code> + */ + public final String getType() + { + return type; + } + + /** + * Returns the provider of this <code>CertStore</code>. + * + * @return the provider of this <code>CertStore</code> + */ + public final Provider getProvider() + { + return provider; + } + + /** + * Returns the default <code>CertStore</code> type as specified in the + * Java security properties file, or the string "LDAP" if no + * such property exists. The Java security properties file is located in + * the file named <JAVA_HOME>/lib/security/java.security, where + * <JAVA_HOME> refers to the directory where the SDK was installed.<br /> + * <br /> + * The default <code>CertStore</code> type can be used by applications + * that do not want to use a hard-coded type when calling one of the + * <code>getInstance</code> methods, and want to provide a default + * <code>CertStore</code> type in case a user does not specify its own.<br /> + * <br /> + * The default <code>CertStore</code> type can be changed by setting + * the value of the "certstore.type" security property (in the Java + * security properties file) to the desired type. + * + * @return the default <code>CertStore</code> type as specified in the + * Java security properties file, or the string "LDAP" + * if no such property exists. + */ + public static final String getDefaultType() + { + String defaulttype = null; + defaulttype = Security.getProperty("certstore.type"); + + if ( defaulttype == null || defaulttype.length() <= 0 ) + return "LDAP"; + else + return defaulttype; + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java new file mode 100644 index 000000000..a15bc3df6 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreException.java @@ -0,0 +1,172 @@ +package java.security.cert; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.security.GeneralSecurityException; + +/** + * An exception indicating one of a variety of problems retrieving + * certificates and CRLs from a <code>CertStore</code>.<br /> + * <br /> + * A <code>CertStoreException</code> provides support for wrapping + * exceptions. The {@link #getCause getCause} method returns the throwable, + * if any, that caused this exception to be thrown.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public class CertStoreException extends GeneralSecurityException +{ + private Throwable cause; + + /** + * Creates a <code>CertStoreException</code> with <code>null</code> as + * its detail message. + */ + public CertStoreException() + { + super(); + } + + /** + * Creates a <code>CertStoreException</code> with the given detail + * message. A detail message is a <code>String</code> that describes this + * particular exception. + * + * @param messag the detail message + */ + public CertStoreException(String message) + { + super(message); + } + + /** + * Creates a <code>CertStoreException</code> with the specified detail + * message and cause. + * + * @param messag the detail message + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause getCause()} method). (A <code>null</code> value is + * permitted, and indicates that the cause is nonexistent or unknown.) + */ + public CertStoreException(String message, Throwable cause) + { + super(message); + this.cause = cause; + } + + /** + * Creates a <code>CertStoreException</code> that wraps the specified + * throwable. This allows any exception to be converted into a + * <code>CertStoreException</code>, while retaining information about the + * cause, which may be useful for debugging. The detail message is + * set to (<code>cause==null ? null : cause.toString()</code>) (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</code> value is + * permitted, and indicates that the cause is nonexistent or unknown.) + */ + public CertStoreException(Throwable cause) + { + this.cause = cause; + } + + /** + * Returns the detail message for this <code>CertStoreException</code>. + * + * @return the detail message, or <code>null</code> if neither the message + * nor cause were specified + */ + public String getMessage() + { + String message = super.getMessage(); + + if ( message == null && cause == null ) + return null; + + StringBuffer s = new StringBuffer(); + if ( message != null ) + { + s.append(message).append('\n'); + } + if ( cause != null ) + { + s.append("Cause:\n").append(cause.getMessage()); + } + return s.toString(); + } + + /** + * Returns the cause of this <code>CertStoreException</code> or + * <code>null</code> if the cause is nonexistent or unknown. + * + * @return the cause of this throwable or <code>null</code> if the cause + * is nonexistent or unknown. + */ + public Throwable getCause() + { + return cause; + } + + /** + * Returns a string describing this exception, including a description + * of the internal (wrapped) cause if there is one. + * + * @return a string representation of this + * <code>CertStoreException</code> + */ + public String toString() + { + String message = getMessage(); + if ( message == null ) + return ""; + + return message; + } + + /** + * Prints a stack trace to <code>System.err</code>, including the backtrace + * of the cause, if any. + */ + public void printStackTrace() { + printStackTrace(System.err); + } + + /** + * Prints a stack trace to a <code>PrintStream</code>, including the + * backtrace of the cause, if any. + * + * @param ps the <code>PrintStream</code> to use for output + */ + public void printStackTrace(PrintStream ps) { + super.printStackTrace(ps); + if ( cause != null ) { + cause.printStackTrace(ps); + } + } + + /** + * Prints a stack trace to a <code>PrintWriter</code>, including the + * backtrace of the cause, if any. + * + * @param pw the <code>PrintWriter</code> to use for output + */ + public void printStackTrace(PrintWriter pw) { + if ( cause != null ) { + cause.printStackTrace(pw); + } + super.printStackTrace(pw); + if ( cause != null ) { + cause.printStackTrace(pw); + } + } +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java new file mode 100644 index 000000000..58a70b372 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreParameters.java @@ -0,0 +1,52 @@ +package java.security.cert; + +/** + * A specification of <code>CertStore</code> parameters.<br /> + * <br /> + * The purpose of this interface is to group (and provide type safety for) + * all <code>CertStore</code> parameter specifications. All + * <code>CertStore</code> parameter specifications must implement this + * interface. <br /> + * <br /> + * Typically, a <code>CertStoreParameters</code> object is passed as a parameter + * to one of the {@link CertStore#getInstance CertStore.getInstance} methods. + * The <code>getInstance</code> method returns a <code>CertStore</code> that + * is used for retrieving <code>Certificate</code>s and <code>CRL</code>s. The + * <code>CertStore</code> that is returned is initialized with the specified + * parameters. The type of parameters needed may vary between different types + * of <code>CertStore</code>s. + * + * @see CertStore#getInstance + **/ +public interface CertStoreParameters extends Cloneable +{ + /** + * Makes a copy of this <code>CertStoreParameters</code>.<br /> + * <br /> + * The precise meaning of "copy" may depend on the class of + * the <code>CertStoreParameters</code> 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.<br /> + * <br /> + * Note that the <code>CertStore.getInstance</code> methods make a copy + * of the specified <code>CertStoreParameters</code>. A deep copy + * implementation of <code>clone</code> is safer and more robust, as it + * prevents the caller from corrupting a shared <code>CertStore</code> by + * subsequently modifying the contents of its initialization parameters. + * However, a shallow copy implementation of <code>clone</code> is more + * appropriate for applications that need to hold a reference to a + * parameter contained in the <code>CertStoreParameters</code>. For example, + * a shallow copy clone allows an application to release the resources of + * a particular <code>CertStore</code> initialization parameter immediately, + * rather than waiting for the garbage collection mechanism. This should + * be done with the utmost care, since the <code>CertStore</code> may still + * be in use by other threads.<br /> + * <br /> + * 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</code> + */ + public Object clone(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java new file mode 100644 index 000000000..b92cf4aa5 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertStoreSpi.java @@ -0,0 +1,104 @@ +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</code> + * implementations must include a class (the SPI class) that extends + * this class (<code>CertStoreSpi</code>), provides a constructor with + * a single argument of type <code>CertStoreParameters</code>, and implements + * all of its methods. In general, instances of this class should only be + * accessed through the <code>CertStore</code> class. + * For details, see the Java Cryptography Architecture.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * The public methods of all <code>CertStoreSpi</code> objects must be + * thread-safe. That is, multiple threads may concurrently invoke these + * methods on a single <code>CertStoreSpi</code> object (or more than one) + * with no ill effects. This allows a <code>CertPathBuilder</code> to search + * for a CRL while simultaneously searching for further certificates, for + * instance.<br /> + * <br /> + * Simple <code>CertStoreSpi</code> implementations will probably ensure + * thread safety by adding a <code>synchronized</code> keyword to their + * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods. + * More sophisticated ones may allow truly concurrent access. + **/ +public abstract class CertStoreSpi + extends Object +{ + + /** + * The sole constructor. + * + * @param params the initialization parameters (may be <code>null</code>) + * @exception InvalidAlgorithmParameterException if the initialization + * parameters are inappropriate for this <code>CertStoreSpi</code> + */ + public CertStoreSpi( CertStoreParameters params ) + throws InvalidAlgorithmParameterException {} + + /** + * Returns a <code>Collection</code> of <code>Certificate</code>s that + * match the specified selector. If no <code>Certificate</code>s + * match the selector, an empty <code>Collection</code> will be returned.<br /> + * <br /> + * For some <code>CertStore</code> types, the resulting + * <code>Collection</code> may not contain <b>all</b> of the + * <code>Certificate</code>s that match the selector. For instance, + * an LDAP <code>CertStore</code> may not search all entries in the + * directory. Instead, it may just search entries that are likely to + * contain the <code>Certificate</code>s it is looking for.<br /> + * <br /> + * Some <code>CertStore</code> implementations (especially LDAP + * <code>CertStore</code>s) may throw a <code>CertStoreException</code> + * unless a non-null <code>CertSelector</code> 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</code> used to select which + * <code>Certificate</code>s should be returned. Specify <code>null</code> + * to return all <code>Certificate</code>s (if supported). + * + * @return A <code>Collection</code> of <code>Certificate</code>s that + * match the specified selector (never <code>null</code>) + * + * @exception CertStoreException if an exception occurs + */ + public abstract Collection engineGetCertificates( CertSelector selector ) + throws CertStoreException; + + /** + * Returns a <code>Collection</code> of <code>CRL</code>s that + * match the specified selector. If no <code>CRL</code>s + * match the selector, an empty <code>Collection</code> will be returned.<br /> + * <br /> + * For some <code>CertStore</code> types, the resulting + * <code>Collection</code> may not contain <b>all</b> of the + * <code>CRL</code>s that match the selector. For instance, + * an LDAP <code>CertStore</code> may not search all entries in the + * directory. Instead, it may just search entries that are likely to + * contain the <code>CRL</code>s it is looking for. <br /> + * <br /> + * Some <code>CertStore</code> implementations (especially LDAP + * <code>CertStore</code>s) may throw a <code>CertStoreException</code> + * unless a non-null <code>CRLSelector</code> 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</code> used to select which + * <code>CRL</code>s should be returned. Specify <code>null</code> + * to return all <code>CRL</code>s (if supported). + * + * @return A <code>Collection</code> of <code>CRL</code>s that + * match the specified selector (never <code>null</code>) + * + * @exception CertStoreException if an exception occurs + */ + public abstract Collection engineGetCRLs( CRLSelector selector ) + throws CertStoreException; +} + diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java new file mode 100644 index 000000000..216a8d8e4 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertUtil.java @@ -0,0 +1,556 @@ +package java.security.cert; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; + +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.DERIA5String; +import org.spongycastle.asn1.DEROutputStream; +import org.spongycastle.asn1.OIDTokenizer; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.util.Strings; + +class CertUtil +{ + static class Implementation + { + Object engine; + Provider provider; + + Implementation( + Object engine, + Provider provider) + { + this.engine = engine; + this.provider = provider; + } + + Object getEngine() + { + return engine; + } + + Provider getProvider() + { + return provider; + } + } + + /** + * see if we can find an algorithm (or its alias and what it represents) in + * the property table for the given provider. + * + * @return null if no algorithm found, an Implementation if it is. + */ + static Implementation getImplementation( + String baseName, + String algorithm, + Provider prov) + { + if (prov == null) + { + Provider[] provider = Security.getProviders(); + + // + // search every provider looking for the algorithm we want. + // + for (int i = 0; i != provider.length; i++) + { + Implementation imp = getImplementation(baseName, algorithm, provider[i]); + if (imp != null) + { + return imp; + } + } + + return null; + } + + String alias; + + while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + algorithm)) != null) + { + algorithm = alias; + } + + String className = prov.getProperty(baseName + "." + algorithm); + + if (className != null) + { + try + { + return new Implementation(Class.forName(className).newInstance(), prov); + } + catch (ClassNotFoundException e) + { + throw new IllegalStateException( + "algorithm " + algorithm + " in provider " + prov.getName() + " but no class found!"); + } + catch (Exception e) + { + throw new IllegalStateException( + "algorithm " + algorithm + " in provider " + prov.getName() + " but class inaccessible: " + e.toString()); + } + } + + return null; + } + + /** + * return an implementation for a given algorithm/provider. + * If the provider is null, we grab the first avalaible who has the required algorithm. + * + * @return null if no algorithm found, an Implementation if it is. + * @exception NoSuchProviderException if a provider is specified and not found. + */ + static Implementation getImplementation( + String baseName, + String algorithm, + String provider) + throws NoSuchProviderException + { + if (provider == null) + { + Provider[] prov = Security.getProviders(); + + // + // search every provider looking for the algorithm we want. + // + for (int i = 0; i != prov.length; i++) + { + Implementation imp = getImplementation(baseName, algorithm, prov[i]); + if (imp != null) + { + return imp; + } + } + } + else + { + Provider prov = Security.getProvider(provider); + + if (prov == null) + { + throw new NoSuchProviderException("Provider " + provider + " not found"); + } + + return getImplementation(baseName, algorithm, prov); + } + + return null; + } + + /** + * see if we can find an algorithm (or its alias and what it represents) in + * the property table for the given provider. + * + * @return null if no algorithm found, an Implementation if it is. + */ + static Implementation getImplementation(String baseName, String algorithm, + Provider prov, Class[] ctorparamtype, Object[] ctorparam) + throws InvalidAlgorithmParameterException + { + String alias; + + while ((alias = prov.getProperty("Alg.Alias." + baseName + "." + + algorithm)) != null) + { + algorithm = alias; + } + + String className = prov.getProperty(baseName + "." + algorithm); + + if (className != null) + { + try + { + return new Implementation(Class.forName(className) + .getConstructor(ctorparamtype).newInstance(ctorparam), + prov); + } + catch (ClassNotFoundException e) + { + throw new IllegalStateException("algorithm " + algorithm + + " in provider " + prov.getName() + + " but no class found!"); + } + catch (Exception e) + { + if (e instanceof InvalidAlgorithmParameterException) + { + throw (InvalidAlgorithmParameterException)e; + } + + throw new IllegalStateException("algorithm " + algorithm + + " in provider " + prov.getName() + + " but class inaccessible!"); + } + } + + return null; + } + + /** + * return an implementation for a given algorithm/provider. If the provider + * is null, we grab the first avalaible who has the required algorithm. + * + * @return null if no algorithm found, an Implementation if it is. + * + * @exception NoSuchProviderException + * if a provider is specified and not found. + */ + static Implementation getImplementation(String baseName, String algorithm, + String provider, Class[] ctorparamtype, Object[] ctorparam) + throws NoSuchProviderException, InvalidAlgorithmParameterException + { + if (provider == null) + { + Provider[] prov = Security.getProviders(); + + // + // search every provider looking for the algorithm we want. + // + for (int i = 0; i != prov.length; i++) + { + Implementation imp = getImplementation(baseName, algorithm, + prov[i], ctorparamtype, ctorparam); + if (imp != null) + { + return imp; + } + } + } + else + { + Provider prov = Security.getProvider(provider); + + if (prov == null) + { + throw new NoSuchProviderException("Provider " + provider + + " not found"); + } + + return getImplementation(baseName, algorithm, prov, ctorparamtype, + ctorparam); + } + + return null; + } + + static byte[] parseGeneralName(int type, String data) throws IOException + { + byte[] encoded = null; + + switch (type) + { + case 0: + throw new IOException( + "unable to parse OtherName String representation"); + case 1: + encoded = parseRfc822(data.trim()); + break; + case 2: + encoded = parseDNSName(data.trim()); + break; + case 3: + throw new IOException( + "unable to parse ORAddress String representation"); + case 4: + encoded = parseX509Name(data.trim()); + break; + case 5: + throw new IOException( + "unable to parse EDIPartyName String representation"); + case 6: + encoded = parseURI(data.trim()); + break; + case 7: + encoded = parseIP(data.trim()); + break; + case 8: + encoded = parseOID(data.trim()); + break; + default: + throw new IOException( + "unable to parse unkown type String representation"); + } + return encoded; + } + + /** + * Check the format of an OID.<br /> + * Throw an IOException if the first component is not 0, 1 or 2 or the + * second component is greater than 39.<br /> + * <br /> + * User {@link org.spongycastle.asn1.OIDTokenizer OIDTokenizer} + * + * @param the + * OID to be checked. + * + * @exception IOException + * if the first component is not 0, 1 or 2 or the second + * component is greater than 39. + */ + static byte[] parseOID(String oid) throws IOException + { + OIDTokenizer tokenizer = new OIDTokenizer(oid); + String token; + if (!tokenizer.hasMoreTokens()) + { + throw new IOException("OID contains no tokens"); + } + token = tokenizer.nextToken(); + if (token == null) + { + throw new IOException("OID contains no tokens"); + } + try + { + int test = (Integer.valueOf(token)).intValue(); + if (test < 0 || test > 2) + { + throw new IOException("first token is not >= 0 and <=2"); + } + if (!tokenizer.hasMoreTokens()) + { + throw new IOException("OID contains only one token"); + } + token = tokenizer.nextToken(); + if (token == null) + { + throw new IOException("OID contains only one token"); + } + test = (Integer.valueOf(token)).intValue(); + if (test < 0 || test > 39) + { + throw new IOException("secon token is not >= 0 and <=39"); + } + } + catch (NumberFormatException ex) + { + throw new IOException("token: " + token + ": " + ex.toString()); + } + ASN1Object derData = new ASN1ObjectIdentifier(oid); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + derOutStream.writeObject(derData); + derOutStream.close(); + return outStream.toByteArray(); + } + + /** + * Parse the given IPv4 or IPv6 into DER encoded byte array representation. + * + * @param the + * IP in well known String format + * + * @return the IP as byte array + * + * @exception IOException + * if the String could not be parsed + */ + private static byte[] parseIP(String data) throws IOException + { + byte[] encoded = parseIPv4(data); + + if (encoded == null) + { + encoded = parseIPv6(data); + } + + if (encoded == null) + { + throw new IOException( + "unable to parse IP to DER encoded byte array"); + } + + return encoded; + } + + /** + * Parse the given IPv4 into DER encoded byte array representation. + * + * @param the + * IP in well known String format + * + * @return the IP as byte array or <code>null</code> if not parseable + */ + private static byte[] parseIPv4(String data) + { + if (data.length() == 0) + { + return null; + } + + int octet; + int octets = 0; + byte[] dst = new byte[4]; + + int pos = 0; + int start = 0; + while (start < data.length() + && (pos = data.indexOf('.', start)) > start && pos - start > 3) + { + try + { + octet = (Integer.valueOf(data.substring(start, pos - start))) + .intValue(); + } + catch (NumberFormatException ex) + { + return null; + } + if (octet < 0 || octet > 255) + { + return null; + } + dst[octets++] = (byte)(octet & 0xff); + + start = pos + 1; + } + + if (octets < 4) + { + return null; + } + + return dst; + } + + /** + * Parse the given IPv6 into DER encoded byte array representation.<br /> + * <br /> + * <b>TODO: implement this</b> + * + * @param the + * IP in well known String format + * + * @return the IP as byte array or <code>null</code> if not parseable + */ + private static byte[] parseIPv6(String data) + { + return null; + } + + /** + * Parse the given URI into DER encoded byte array representation. + * + * @param the + * URI in well known String format + * + * @return the URI as byte array + * + * @exception IOException + * if the String could not be parsed + */ + private static byte[] parseURI(String data) throws IOException + { + // TODO do parsing test + ASN1Object derData = new DERIA5String(data); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + derOutStream.writeObject(derData); + derOutStream.close(); + return outStream.toByteArray(); + } + + /** + * Parse the given rfc822 addr-spec into DER encoded byte array + * representation. + * + * @param the + * rfc822 addr-spec in well known String format + * + * @return the rfc822 addr-spec as byte array + * + * @exception IOException + * if the String could not be parsed + */ + private static byte[] parseRfc822(String data) throws IOException + { + int tmpInt = data.indexOf('@'); + if (tmpInt < 0 || tmpInt >= data.length() - 1) + { + throw new IOException("wrong format of rfc822Name:" + data); + } + // TODO more test for illegal charateers + ASN1Object derData = new DERIA5String(data); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + derOutStream.writeObject(derData); + derOutStream.close(); + return outStream.toByteArray(); + } + + /** + * Parse the given DNS name into DER encoded byte array representation. The + * String must be in den preffered name syntax as defined in RFC 1034. + * + * @param the + * DNS name in well known String format + * + * @return the DNS name as byte array + * + * @exception IOException + * if the String could not be parsed + */ + private static byte[] parseDNSName(String data) throws IOException + { + // TODO more test for illegal charateers + ASN1Object derData = new DERIA5String(data); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + derOutStream.writeObject(derData); + derOutStream.close(); + return outStream.toByteArray(); + } + + /** + * Parse the given X.509 name into DER encoded byte array representation. + * + * @param the + * X.509 name in well known String format + * + * @return the X.509 name as byte array + * + * @exception IOException + * if the String could not be parsed + */ + private static byte[] parseX509Name(String data) throws IOException + { + // TODO more test for illegal charateers + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + derOutStream.writeObject(new X509Name(trimX509Name(data))); + derOutStream.close(); + return outStream.toByteArray(); + } + + /** + * Returns the given name converted to upper case and all multi spaces squezed + * to one space. + **/ + static String trimX509Name(String name) + { + String data = Strings.toUpperCase(name.trim()); + int pos; + while ((pos = data.indexOf(" ")) >= 0) + { + data = data.substring(0, pos) + data.substring(pos + 1); + } + while ((pos = data.indexOf(" =")) >= 0) + { + data = data.substring(0, pos) + data.substring(pos + 1); + } + while ((pos = data.indexOf("= ")) >= 0) + { + data = data.substring(0, pos + 1) + data.substring(pos + 2); + } + return data; + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java new file mode 100644 index 000000000..201e209a3 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/Certificate.java @@ -0,0 +1,80 @@ + +package java.security.cert; + +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PublicKey; +import java.security.SignatureException; + +public abstract class Certificate extends Object +{ + private String type; + + protected Certificate(String type) + { + this.type = type; + } + + public boolean equals(Object other) + { + if ( !(other instanceof Certificate) ) + return false; + + if ( other == this ) + return true; + + try + { + byte[] enc1 = getEncoded(); + byte[] enc2 = ((Certificate)other).getEncoded(); + + return MessageDigest.isEqual(enc1, enc2); + } + catch (CertificateEncodingException e) + { + return false; + } + } + + public final String getType() + { + return type; + } + + // XXX + public int hashCode() + { + try + { + byte[] enc1 = getEncoded(); + int hc = 0; + for (int i = 0; i < enc1.length; i++) + { + hc += enc1[i]; + } + + return hc; + } + catch (CertificateEncodingException e) + { + return 0; + } + } + + public abstract byte[] getEncoded() + throws CertificateEncodingException; + + public abstract PublicKey getPublicKey(); + + public abstract String toString(); + + public abstract void verify(PublicKey key) + throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException; + + public abstract void verify(PublicKey key, String sigProvider) + throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException; +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java new file mode 100644 index 000000000..47545a5c0 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateEncodingException.java @@ -0,0 +1,14 @@ + +package java.security.cert; + +public class CertificateEncodingException extends CertificateException +{ + public CertificateEncodingException() + { + } + + public CertificateEncodingException(String msg) + { + super(msg); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java new file mode 100644 index 000000000..644c6249f --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateException.java @@ -0,0 +1,16 @@ + +package java.security.cert; + +import java.security.GeneralSecurityException; + +public class CertificateException extends GeneralSecurityException +{ + public CertificateException() + { + } + + public CertificateException(String msg) + { + super(msg); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java new file mode 100644 index 000000000..1a9062aa2 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateExpiredException.java @@ -0,0 +1,14 @@ + +package java.security.cert; + +public class CertificateExpiredException extends CertificateException +{ + public CertificateExpiredException() + { + } + + public CertificateExpiredException(String msg) + { + super(msg); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java new file mode 100644 index 000000000..e86cd3a03 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactory.java @@ -0,0 +1,183 @@ + +package java.security.cert; + +import java.io.InputStream; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +/** + * Uses {@link CertUtil CertUtil} to actualiy load the SPI classes. + * + * @see CertUtil + **/ +public class CertificateFactory +{ + private CertificateFactorySpi certFacSpi; + private Provider provider; + private String type; + + protected CertificateFactory( + CertificateFactorySpi certFacSpi, + Provider provider, + String type) + { + this.certFacSpi = certFacSpi; + this.provider = provider; + this.type = type; + } + + public final CRL generateCRL(InputStream inStream) + throws CRLException + { + return certFacSpi.engineGenerateCRL(inStream); + } + + public final Collection generateCRLs(InputStream inStream) + throws CRLException + { + return certFacSpi.engineGenerateCRLs(inStream); + } + + public final Certificate generateCertificate(InputStream inStream) + throws CertificateException + { + return certFacSpi.engineGenerateCertificate(inStream); + } + + public final /*Sk13 Vector*/ Collection generateCertificates(InputStream inStream) + throws CertificateException + { + return certFacSpi.engineGenerateCertificates(inStream); + } + + /** + * Returns an iteration of the <code>CertPath</code> encodings supported + * by this certificate factory, with the default encoding first. See + * Appendix A in the + * Java Certification Path API Programmer's Guide for information about + * standard encoding names and their formats.<br /> + * <br /> + * Attempts to modify the returned <code>Iterator</code> via its + * <code>remove</code> method result in an + * <code>UnsupportedOperationException</code>. + * + * @return an <code>Iterator</code> over the names of the supported + * <code>CertPath</code> encodings (as <code>String</code>s) + */ + public final Iterator getCertPathEncodings() + { + return certFacSpi.engineGetCertPathEncodings(); + } + + /** + * Generates a <code>CertPath</code> object and initializes it with + * the data read from the <code>InputStream</code> 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</code> returned by + * the {@link #getCertPathEncodings getCertPathEncodings} method. + * + * @param inStream an <code>InputStream</code> containing the data + * + * @return a <code>CertPath</code> initialized with the data from the + * <code>InputStream</code> + * + * @exception CertificateException if an exception occurs while decoding + */ + public final CertPath generateCertPath(InputStream inStream) + throws CertificateException + { + return certFacSpi.engineGenerateCertPath(inStream); + } + + /** + * Generates a <code>CertPath</code> object and initializes it with + * the data read from the <code>InputStream</code> inStream. The data + * is assumed to be in the specified encoding. See Appendix A in the + * <a href="../../../../guide/security/certpath/CertPathProgGuide.html#AppA"> + * Java Certification Path API Programmer's Guide</a> + * for information about standard encoding names and their formats. + * + * @param inStream an <code>InputStream</code> containing the data + * @param encoding the encoding used for the data + * + * @return a <code>CertPath</code> initialized with the data from the + * <code>InputStream</code> + * + * @exception CertificateException if an exception occurs while decoding or + * the encoding requested is not supported + */ + public final CertPath generateCertPath(InputStream inStream, String encoding) + throws CertificateException + { + return certFacSpi.engineGenerateCertPath(inStream, encoding); + } + + /** + * Generates a <code>CertPath</code> object and initializes it with + * a <code>List</code> of <code>Certificate</code>s.<br /> + * <br /> + * The certificates supplied must be of a type supported by the + * <code>CertificateFactory</code>. They will be copied out of the supplied + * <code>List</code> object. + * + * @param certificates a <code>List</code> of <code>Certificate</code>s + * + * @return a <code>CertPath</code> initialized with the supplied list of + * certificates + * + * @exception CertificateException if an exception occurs + */ + public final CertPath generateCertPath(List certificates) + throws CertificateException + { + return certFacSpi.engineGenerateCertPath( certificates ); + } + + public static final CertificateFactory getInstance(String type) + throws CertificateException + { + try + { + CertUtil.Implementation imp = CertUtil.getImplementation("CertificateFactory", type, (String)null); + + if (imp != null) + { + return new CertificateFactory((CertificateFactorySpi)imp.getEngine(), imp.getProvider(), type); + } + + throw new CertificateException("can't find type " + type); + } + catch (NoSuchProviderException e) + { + throw new CertificateException(type + " not found"); + } + } + + public static final CertificateFactory getInstance( + String type, + String provider) + throws CertificateException, NoSuchProviderException + { + CertUtil.Implementation imp = CertUtil.getImplementation("CertificateFactory", type, provider); + + if (imp != null) + { + return new CertificateFactory((CertificateFactorySpi)imp.getEngine(), imp.getProvider(), type); + } + + throw new CertificateException("can't find type " + type); + } + + public final Provider getProvider() + { + return provider; + } + + public final String getType() + { + return type; + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java new file mode 100644 index 000000000..8cc06fc2e --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateFactorySpi.java @@ -0,0 +1,111 @@ + +package java.security.cert; + +import java.io.InputStream; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +public abstract class CertificateFactorySpi +{ + public CertificateFactorySpi() + { + } + + public abstract CRL engineGenerateCRL(InputStream inStream) + throws CRLException; + + public abstract Collection engineGenerateCRLs(InputStream inStream) + throws CRLException; + + public abstract Certificate engineGenerateCertificate(InputStream inStream) + throws CertificateException; + + public abstract /*SK13 Vector*/ Collection engineGenerateCertificates(InputStream inStream) + throws CertificateException; + + /** + * Returns an iteration of the <code>CertPath</code> encodings supported + * by this certificate factory, with the default encoding first. See + * Appendix A in the + * Java Certification Path API Programmer's Guide + * for information about standard encoding names.<br /> + * <br /> + * Attempts to modify the returned <code>Iterator</code> via its + * <code>remove</code> method result in an + * <code>UnsupportedOperationException</code>.<br /> + * <br /> + * 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</code> + * and by default throws an <code>UnsupportedOperationException</code>. + * + * @return an <code>Iterator</code> over the names of the supported + * <code>CertPath</code> encodings (as <code>String</code>s) + * + * @exception UnsupportedOperationException if the method is not supported + */ + public abstract Iterator engineGetCertPathEncodings(); + + /** + * Generates a <code>CertPath</code> object and initializes it with + * the data read from the <code>InputStream</code> inStream. The data + * is assumed to be in the default encoding. + * + * @param inStream an <code>InputStream</code> containing the data + * + * @return a <code>CertPath</code> initialized with the data from the + * <code>InputStream</code> + * + * @exception CertificateException if an exception occurs while decoding + */ + public abstract CertPath engineGenerateCertPath(InputStream inStream) + throws CertificateException; + + /** + * Generates a <code>CertPath</code> object and initializes it with + * the data read from the <code>InputStream</code> inStream. The data + * is assumed to be in the specified encoding.<br /> + * <br /> + * 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</code> + * and by default throws an <code>UnsupportedOperationException</code>. + * + * @param inStream an <code>InputStream</code> containing the data + * @param encoding the encoding used for the data + * + * @return a <code>CertPath</code> initialized with the data from the + * <code>InputStream</code> + * + * @exception CertificateException if an exception occurs while decoding or + * the encoding requested is not supported + * @exception UnsupportedOperationException if the method is not supported + */ + public abstract CertPath engineGenerateCertPath(InputStream inStream, String encoding) + throws CertificateException; + + /** + * Generates a <code>CertPath</code> object and initializes it with + * a <code>List</code> of <code>Certificate</code>s.<br /> + * <br /> + * The certificates supplied must be of a type supported by the + * <code>CertificateFactory</code>. They will be copied out of the supplied + * <code>List</code> object.<br /> + * <br /> + * 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</code> + * and by default throws an <code>UnsupportedOperationException</code>. + * + * @param certificates a <code>List</code> of <code>Certificate</code>s + * + * @return a <code>CertPath</code> initialized with the supplied list of + * certificates + * + * @exception CertificateException if an exception occurs + * @exception UnsupportedOperationException if the method is not supported + */ + public abstract CertPath engineGenerateCertPath(List certificates) + throws CertificateException; +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java new file mode 100644 index 000000000..ec8d46a3e --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateNotYetValidException.java @@ -0,0 +1,14 @@ + +package java.security.cert; + +public class CertificateNotYetValidException extends CertificateException +{ + public CertificateNotYetValidException() + { + } + + public CertificateNotYetValidException(String msg) + { + super(msg); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java new file mode 100644 index 000000000..a9f18aae0 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CertificateParsingException.java @@ -0,0 +1,14 @@ + +package java.security.cert; + +public class CertificateParsingException extends CertificateException +{ + public CertificateParsingException() + { + } + + public CertificateParsingException(String msg) + { + super(msg); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java new file mode 100644 index 000000000..7c31e7b51 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/CollectionCertStoreParameters.java @@ -0,0 +1,117 @@ +package java.security.cert; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Parameters used as input for the Collection <code>CertStore</code> + * algorithm.<br /> + * <br /> + * This class is used to provide necessary configuration parameters + * to implementations of the Collection <code>CertStore</code> + * algorithm. The only parameter included in this class is the + * <code>Collection</code> from which the <code>CertStore</code> will + * retrieve certificates and CRLs.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 java.util.Collection + * @see CertStore + **/ +public class CollectionCertStoreParameters implements CertStoreParameters +{ + private Collection collection; + + /** + * Creates an instance of <code>CollectionCertStoreParameters</code> + * which will allow certificates and CRLs to be retrieved from the + * specified <code>Collection</code>. If the specified + * <code>Collection</code> contains an object that is not a + * <code>Certificate</code> or <code>CRL</code>, that object will be + * ignored by the Collection <code>CertStore</code>.<br /> + * <br /> + * The <code>Collection</code> is <b>not</b> copied. Instead, a + * reference is used. This allows the caller to subsequently add or + * remove <code>Certificates</code> or <code>CRL</code>s from the + * <code>Collection</code>, thus changing the set of + * <code>Certificates</code> or <code>CRL</code>s available to the + * Collection <code>CertStore</code>. The Collection <code>CertStore</code> + * will not modify the contents of the <code>Collection</code>.<br /> + * <br /> + * If the <code>Collection</code> will be modified by one thread while + * another thread is calling a method of a Collection <code>CertStore</code> + * that has been initialized with this <code>Collection</code>, the + * <code>Collection</code> must have fail-fast iterators. + * + * @param collection a <code>Collection</code> of + * <code>Certificate</code>s and <code>CRL</code>s + * + * @exception NullPointerException if <code>collection</code> is + * <code>null</code> + */ + public CollectionCertStoreParameters(Collection collection) + { + if ( collection == null ) + throw new NullPointerException("collection must be non-null"); + this.collection = collection; + } + + /** + * Creates an instance of <code>CollectionCertStoreParameters</code> with + * the an empty Collection. + */ + public CollectionCertStoreParameters() + { + collection = new ArrayList(); + } + + /** + * Returns the <code>Collection</code> from which <code>Certificate</code>s + * and <code>CRL</code>s are retrieved. This is <b>not</b> a copy of the + * <code>Collection</code>, it is a reference. This allows the caller to + * subsequently add or remove <code>Certificates</code> or + * <code>CRL</code>s from the <code>Collection</code>. + * + * @return the <code>Collection</code> (never null) + */ + public Collection getCollection() + { + return collection; + } + + /** + * Returns a copy of this object. Note that only a reference to the + * <code>Collection</code> 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()); + } + } + + /** + * Returns a formatted string describing the parameters. + * + * @return a formatted string describing the parameters + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append("CollectionCertStoreParameters: [\n collections:\n"); + s.append( getCollection()); + s.append("\n]" ); + return s.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java new file mode 100644 index 000000000..2e4669975 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/LDAPCertStoreParameters.java @@ -0,0 +1,130 @@ +package java.security.cert; + +/** + * Parameters used as input for the LDAP <code>CertStore</code> algorithm.<br /> + * <br /> + * This class is used to provide necessary configuration parameters (server + * name and port number) to implementations of the LDAP <code>CertStore</code> + * algorithm.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public class LDAPCertStoreParameters implements CertStoreParameters +{ + private static final int LDAP_DEFAULT_PORT = 389; + + /** + * the port number of the LDAP server + */ + private String serverName; + + /** + * the DNS name of the LDAP server + */ + private int port; + + /** + * Creates an instance of <code>LDAPCertStoreParameters</code> with the + * default parameter values (server name "localhost", port 389). + */ + public LDAPCertStoreParameters() + { + this("localhost", LDAP_DEFAULT_PORT); + } + + /** + * Creates an instance of <code>LDAPCertStoreParameters</code> 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</code> is + * <code>null</code> + */ + public LDAPCertStoreParameters(String serverName) + { + this(serverName, LDAP_DEFAULT_PORT); + } + + /** + * Creates an instance of <code>LDAPCertStoreParameters</code> 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</code> is + * <code>null</code> + */ + public LDAPCertStoreParameters(String serverName, int port) + { + if (serverName == null) + throw new NullPointerException("serverName must be non-null"); + this.serverName = serverName; + this.port = port; + } + + /** + * Returns the DNS name of the LDAP server. + * + * @return the name (not <code>null</code>) + */ + 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.<br /> + * <br /> + * Note: this method currently performs a shallow copy of the object + * (simply calls <code>Object.clone()</code>). 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()); + } + } + + /** + * 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: ").append(serverName).append('\n'); + sb.append(" port: ").append(port).append('\n'); + sb.append(']'); + return sb.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java new file mode 100644 index 000000000..b4f7aceb9 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXBuilderParameters.java @@ -0,0 +1,179 @@ +package java.security.cert; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.util.Set; + +/** + * Parameters used as input for the PKIX <code>CertPathBuilder</code> + * algorithm.<br /> + * <br /> + * A PKIX <code>CertPathBuilder</code> uses these parameters to {@link + * CertPathBuilder#build build} a <code>CertPath</code> which has been + * validated according to the PKIX certification path validation algorithm.<br /> + * <br /> + * To instantiate a <code>PKIXBuilderParameters</code> 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</code> of <code>TrustAnchor</code> 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</code> instance containing trusted certificate entries, each + * of which will be considered as a most-trusted CA.<br /> + * <br /> + * In addition, an application must specify constraints on the target + * certificate that the <code>CertPathBuilder</code> will attempt + * to build a path to. The constraints are specified as a + * <code>CertSelector</code> object. These constraints should provide the + * <code>CertPathBuilder</code> with enough search criteria to find the target + * certificate. Minimal criteria for an <code>X509Certificate</code> usually + * include the subject name and/or one or more subject alternative names. + * If enough criteria is not specified, the <code>CertPathBuilder</code> + * may throw a <code>CertPathBuilderException</code>.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public class PKIXBuilderParameters extends PKIXParameters +{ + private int maxPathLength = 5; + + /** + * Creates an instance of <code>PKIXBuilderParameters</code> with + * the specified <code>Set</code> of most-trusted CAs. + * Each element of the set is a {@link TrustAnchor TrustAnchor}.<br /> + * <br /> + * Note that the <code>Set</code> is copied to protect against + * subsequent modifications. + * + * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s + * @param targetConstraints a <code>CertSelector</code> specifying the + * constraints on the target certificate + * + * @exception InvalidAlgorithmParameterException if <code>trustAnchors</code> + * is empty <code>(trustAnchors.isEmpty() == true)</code> + * @exception NullPointerException if <code>trustAnchors</code> is + * <code>null</code> + * @exception ClassCastException if any of the elements of + * <code>trustAnchors</code> are not of type + * <code>java.security.cert.TrustAnchor</code> + */ + public PKIXBuilderParameters( + Set trustAnchors, + CertSelector targetConstraints) + throws InvalidAlgorithmParameterException + { + super( trustAnchors ); + setTargetCertConstraints( targetConstraints ); + } + + /** + * Creates an instance of <code>PKIXBuilderParameters</code> that + * populates the set of most-trusted CAs from the trusted + * certificate entries contained in the specified <code>KeyStore</code>. + * Only keystore entries that contain trusted <code>X509Certificate</code>s + * are considered; all other certificate types are ignored. + * + * @param keystore a <code>KeyStore</code> from which the set of + * most-trusted CAs will be populated + * @param targetConstraints a <code>CertSelector</code> specifying the + * constraints on the target certificate + * + * @exception KeyStoreException if <code>keystore</code> has not been + * initialized + * @exception InvalidAlgorithmParameterException if <code>keystore</code> does + * not contain at least one trusted certificate entry + * @exception NullPointerException if <code>keystore</code> is + * <code>null</code> + */ + 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</code> instance must not build + * paths longer than the length specified.<br /> + * <br /> + * 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.<br /> + * <br /> + * If any of the CA certificates contain the + * <code>BasicConstraintsExtension</code>, the value of the + * <code>pathLenConstraint</code> 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 + * + * @exception InvalidParameterException if <code>maxPathLength</code> 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 s = new StringBuffer(); + s.append( "PKIXBuilderParameters [\n" ); + s.append( super.toString() ); + s.append( " Maximum Path Length: " ); + s.append( getMaxPathLength() ); + s.append( "\n]\n" ); + return s.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java new file mode 100644 index 000000000..2ac791826 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathBuilderResult.java @@ -0,0 +1,93 @@ +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.<br /> + * <br /> + * Instances of <code>PKIXCertPathBuilderResult</code> are returned by + * the <code>build</code> method of <code>CertPathBuilder</code> + * objects implementing the PKIX algorithm.<br /> + * <br /> + * All <code>PKIXCertPathBuilderResult</code> 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</code> describing the certification + * authority (CA) that served as a trust anchor for the certification path.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + * + **/ +public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult + implements CertPathBuilderResult +{ + private CertPath certPath; + + /** + * Creates an instance of <code>PKIXCertPathBuilderResult</code> + * containing the specified parameters. + * + * @param certPath the validated <code>CertPath</code> + * @param trustAnchor a <code>TrustAnchor</code> describing the CA that + * served as a trust anchor for the certification path + * @param policyTree the immutable valid policy tree, or <code>null</code> + * if there are no valid policies + * @param subjectPublicKey the public key of the subject + * + * @exception NullPointerException if the <code>certPath</code>, + * <code>trustAnchor</code> or <code>subjectPublicKey</code> parameters + * are <code>null</code> + */ + 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</code> object does not include the trust anchor. + * Instead, use the {@link #getTrustAnchor() getTrustAnchor()} method to + * obtain the <code>TrustAnchor</code> that served as the trust anchor + * for the certification path. + * + * @return the built and validated <code>CertPath</code> (never + * <code>null</code>) + */ + public CertPath getCertPath() + { + return certPath; + } + + /** + * Return a printable representation of this + * <code>PKIXCertPathBuilderResult</code>. + * + * @return a <code>String</code> describing the contents of this + * <code>PKIXCertPathBuilderResult</code> + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append( "PKIXCertPathBuilderResult: [\n" ); + s.append( " Certification Path: ").append(getCertPath()).append('\n' ); + s.append( " Trust Anchor: ").append(getTrustAnchor()).append('\n' ); + s.append( " Policy Tree: ").append(getPolicyTree()).append('\n' ); + s.append( " Subject Public Key: ").append(getPublicKey()).append("\n]"); + return s.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java new file mode 100644 index 000000000..14dec8060 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathChecker.java @@ -0,0 +1,155 @@ +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</code>. <br /> + * <br /> + * A concrete implementation of the <code>PKIXCertPathChecker</code> 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.<br /> + * <br /> + * Instances of <code>PKIXCertPathChecker</code> are passed as parameters + * using the {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} + * or {@link PKIXParameters#addCertPathChecker addCertPathChecker} methods + * of the <code>PKIXParameters</code> and <code>PKIXBuilderParameters</code> + * class. Each of the <code>PKIXCertPathChecker</code>s {@link #check check} + * methods will be called, in turn, for each certificate processed by a PKIX + * <code>CertPathValidator</code> or <code>CertPathBuilder</code> + * implementation.<br /> + * <br /> + * A <code>PKIXCertPathChecker</code> 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</code> to efficiently + * backtrack and try other paths. In these situations, the + * <code>CertPathBuilder</code> is able to restore prior path validation + * states by restoring the cloned <code>PKIXCertPathChecker</code>s.<br /> + * <br /> + * The order in which the certificates are presented to the + * <code>PKIXCertPathChecker</code> 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</code> 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.<br /> + * <br /> + * Additional input parameters required for executing the check may be + * specified through constructors of concrete implementations of this class.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public abstract class PKIXCertPathChecker implements Cloneable +{ + + /** + * Default constructor. + */ + protected PKIXCertPathChecker() {} + + /** + * Initializes the internal state of this <code>PKIXCertPathChecker</code>. + * <p> + * The <code>forward</code> flag specifies the order that + * certificates will be passed to the {@link #check check} method + * (forward or reverse). A <code>PKIXCertPathChecker</code> <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</code> method. If <code>true</code>, certificates + * are presented from target to most-trusted CA (forward); if + * <code>false</code>, from most-trusted CA to target (reverse). + * @exception CertPathValidatorException if this + * <code>PKIXCertPathChecker</code> 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 + */ + public abstract void init(boolean forward) + throws CertPathValidatorException; + + /** + * Indicates if forward checking is supported. Forward checking refers + * to the ability of the <code>PKIXCertPathChecker</code> to perform + * its checks when certificates are presented to the <code>check</code> + * method in the forward direction (from target to most-trusted CA). + * + * @return <code>true</code> if forward checking is supported, + * <code>false</code> otherwise + */ + public abstract boolean isForwardCheckingSupported(); + + /** + * Returns an immutable <code>Set</code> of X.509 certificate extensions + * that this <code>PKIXCertPathChecker</code> supports (i.e. recognizes, is + * able to process), or <code>null</code> if no extensions are supported. + * <p> + * Each element of the set is a <code>String</code> 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</code> + * might possibly be able to process should be included in the set. + * + * @return an immutable <code>Set</code> of X.509 extension OIDs (in + * <code>String</code> format) supported by this + * <code>PKIXCertPathChecker</code>, or <code>null</code> if no + * extensions are supported + */ + public abstract Set 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</code> method. + * + * @param cert the <code>Certificate</code> to be checked + * @param unresolvedCritExts a <code>Collection</code> 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 unresolvedCritExts) + throws CertPathValidatorException; + + /** + * Returns a clone of this object. Calls the <code>Object.clone()</code> + * method. + * All subclasses which maintain state must support and + * override this method, if necessary. + * + * @return a copy of this <code>PKIXCertPathChecker</code> + */ + public Object clone() + { + try { + return super.clone(); + } catch ( CloneNotSupportedException ex ) { + /* Cannot happen */ + throw new InternalError( ex.toString() ); + } + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java new file mode 100644 index 000000000..8ffa25555 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXCertPathValidatorResult.java @@ -0,0 +1,136 @@ +package java.security.cert; + +import java.security.PublicKey; + +/** + * This class represents the successful result of the PKIX certification + * path validation algorithm. <br /> + * <br /> + * Instances of <code>PKIXCertPathValidatorResult</code> are returned by the + * {@link CertPathValidator#validate validate} method of + * <code>CertPathValidator</code> objects implementing the PKIX algorithm.<br /> + * <br /> + * All <code>PKIXCertPathValidatorResult</code> objects contain the + * valid policy tree and subject public key resulting from the + * validation algorithm, as well as a <code>TrustAnchor</code> describing + * the certification authority (CA) that served as a trust anchor for the + * certification path.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public class PKIXCertPathValidatorResult implements CertPathValidatorResult +{ + private TrustAnchor trustAnchor; + private PolicyNode policyTree; + private PublicKey subjectPublicKey; + + /** + * Creates an instance of <code>PKIXCertPathValidatorResult</code> + * containing the specified parameters. + * + * @param trustAnchor a <code>TrustAnchor</code> describing the CA that + * served as a trust anchor for the certification path + * @param policyTree the immutable valid policy tree, or <code>null</code> + * if there are no valid policies + * @param subjectPublicKey the public key of the subject + * + * @exception NullPointerException if the <code>subjectPublicKey</code> or + * <code>trustAnchor</code> parameters are <code>null</code> + */ + 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</code> describing the CA that served + * as a trust anchor for the certification path. + * + * @return the <code>TrustAnchor</code> (never <code>null</code>) + */ + 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</code> object that is returned and any objects that + * it returns through public methods are immutable.<br /> + * <br /> + * 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</code>. 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</code> + * 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</code>) + */ + public PublicKey getPublicKey() + { + return subjectPublicKey; + } + + /** + * Returns a copy of this object. + * + * @return the copy + */ + public Object clone() + { + try { + return super.clone(); + } catch ( CloneNotSupportedException ex ) { + throw new InternalError( ex.toString() ); + } + } + + /** + * Return a printable representation of this + * <code>PKIXCertPathValidatorResult</code>. + * + * @return a <code>String</code> describing the contents of this + * <code>PKIXCertPathValidatorResult</code> + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append( "PKIXCertPathValidatorResult: [ \n" ); + s.append( " Trust Anchor: ").append(getTrustAnchor()).append('\n' ); + s.append( " Policy Tree: ").append(getPolicyTree()).append('\n' ); + s.append( " Subject Public Key: ").append(getPublicKey()).append("\n]" ); + return s.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java new file mode 100644 index 000000000..3c55d7e49 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PKIXParameters.java @@ -0,0 +1,770 @@ +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 CertPathValidator algorithm.<br /> + * <br /> + * A PKIX <code>CertPathValidator</code> uses these parameters to validate a + * <code>CertPath</code> according to the PKIX certification path validation + * algorithm.<br /> + * <br /> + * To instantiate a <code>PKIXParameters</code> 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)}, specifying a Set of <code>TrustAnchor</code> objects, each + * of which identify a most-trusted CA. Alternatively, an application + * can call {@link #PKIXParameters(KeyStore)}, specifying a <code>KeyStore</code> instance + * containing trusted certificate entries, each of which will be + * considered as a most-trusted CA.<br /> + * <br /> + * Once a <code>PKIXParameters</code> object has been created, other parameters can + * be specified (by calling {@link #setInitialPolicies} or {@link #setDate}, for + * instance) and then the <code>PKIXParameters</code> is passed along with the + * <code>CertPath</code> to be validated to {@link CertPathValidator#validate}.<br /> + * <br /> + * Any parameter that is not set (or is set to null) will be set to the + * default value for that parameter. The default value for the date + * parameter is null, which indicates the current time when the path is + * validated. The default for the remaining parameters is the least + * constrained.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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 + **/ +public class PKIXParameters implements CertPathParameters { + private Set trustAnchors; + private Set initialPolicies = new HashSet(); + private List certStores = new ArrayList(); + private CertSelector certSelector; + private List certPathCheckers = new ArrayList(); + private boolean revocationEnabled = true; + private boolean explicitPolicyRequired = false; + private boolean policyMappingInhibited = false; + private boolean anyPolicyInhibited = false; + private boolean policyQualifiersRejected = true; + private Date date; + private String sigProvider; + + /** + * Creates an instance of PKIXParameters with the specified + * Set of most-trusted CAs. Each element of the set is a + * TrustAnchor.<br /> + * <br /> + * Note that the Set is copied to protect against subsequent + * modifications. + * + * @param trustAnchors a Set of TrustAnchors + * + * @exception InvalidAlgorithmParameterException if the + * specified Set is empty <code>(trustAnchors.isEmpty() == true)</code> + * @exception NullPointerException if the specified Set is <code>null</code> + * @exception ClassCastException if any of the elements in the + * Set are not of type + * <code>java.security.cert.TrustAnchor</code> + **/ + public PKIXParameters(Set trustAnchors) + throws InvalidAlgorithmParameterException + { + setTrustAnchors( trustAnchors ); + } + + /** + * Creates an instance of PKIXParameters that populates the + * set of most-trusted CAs from the trusted certificate + * entries contained in the specified KeyStore. Only keystore + * entries that contain trusted X509Certificates are + * considered; all other certificate types are ignored. + * + * @param keystore a KeyStore from which the set of + * most-trusted CAs will be populated + * + * @exception KeyStoreException if the keystore has not been + * initialized + * @exception InvalidAlgorithmParameterException if the keystore + * does not contain at least one trusted certificate entry + * @exception NullPointerException if the keystore is null + **/ + public PKIXParameters(KeyStore keystore) + throws KeyStoreException, + InvalidAlgorithmParameterException + { + if ( keystore == null ) + throw new NullPointerException( "the keystore parameter must be non-null" ); + + Set trustAnchors = new HashSet(); + String alias; + Certificate cert; + Enumeration enum = keystore.aliases(); + while ( enum.hasMoreElements() ) { + alias = (String)enum.nextElement(); + if ( keystore.isCertificateEntry( alias ) ) { + cert = keystore.getCertificate( alias ); + if ( cert instanceof X509Certificate ) + trustAnchors.add( new TrustAnchor( (X509Certificate)cert, null ) ); + } + } + setTrustAnchors( trustAnchors ); + } + + /** + * Returns an immutable Set of the most-trusted CAs. + * + * @return an immutable <code>Set</code> of + * <code>TrustAnchors</code> (never <code>null</code>) + * + * @see #setTrustAnchors + **/ + public Set getTrustAnchors() + { + return Collections.unmodifiableSet(trustAnchors); + } + + /** + * Sets the Set of most-trusted CAs.<br /> + * <br /> + * Note that the Set is copied to protect against subsequent + * modifications.<br /> + * <br /> + * @param trustAnchors a Set of TrustAnchors + * + * @exception InvalidAlgorithmParameterException if the specified Set is empty <code>(trustAnchors.isEmpty() == true)</code> + * @exception NullPointerException if the specified Set is <code>null</code> + * @exception ClassCastException if any of the elements in + * the set are not of type java.security.cert.TrustAnchor + * + * @see #getTrustAnchors + **/ + public void setTrustAnchors(Set trustAnchors) + throws InvalidAlgorithmParameterException + { + if ( trustAnchors == null ) + throw new NullPointerException("the trustAnchors parameter must be non-null"); + if ( trustAnchors.isEmpty() ) + throw new InvalidAlgorithmParameterException("the trustAnchors parameter must be non-empty"); + + Iterator iter = trustAnchors.iterator(); + TrustAnchor obj; + this.trustAnchors = new HashSet(); + while( iter.hasNext() ) { + obj = (TrustAnchor)iter.next(); + if ( obj != null ) { + this .trustAnchors.add( obj ); + } + } + } + + /** + * Returns an immutable 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</code>, which is interpreted as meaning that any + * policy would be acceptable. + * + * @return an immutable <code>Set</code> of initial policy + * OIDs in String format, or an empty <code>Set</code> (implying any policy + * is acceptable). Never returns <code>null</code>. + * + * @see #setInitialPolicies(java.util.Set) + **/ + public Set getInitialPolicies() + { + Set returnSet = initialPolicies; + if ( initialPolicies == null ) + returnSet = new HashSet(); + + return Collections.unmodifiableSet( returnSet ); + } + + /** + * Sets the <code>Set</code> 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</code> (or <code>null</code>).<br /> + * <br /> + * Note that the Set is copied to protect against subsequent + * modifications.<br /> + * <br /> + * @param initialPolicies a Set of initial policy OIDs in String format (or <code>null</code>) + * + * @exception ClassCastException if any of the elements in the + * set are not of type String + * + * @see #getInitialPolicies() + **/ + public void setInitialPolicies(Set initialPolicies) + { + if ( initialPolicies == null || initialPolicies.isEmpty() ) + { + this.initialPolicies = null; + } + else + { + Iterator iter = initialPolicies.iterator(); + this.initialPolicies = new HashSet(); + String obj; + while ( iter.hasNext() ) + { + obj = (String)iter.next(); + if ( obj != null ) { + this.initialPolicies.add( obj ); + } + } + } + } + + /** + * Sets the list of CertStores to be used in finding + * certificates and CRLs. May be null, in which case no + * CertStores will be used. The first CertStores in the list + * may be preferred to those that appear later.<br /> + * <br /> + * Note that the List is copied to protect against subsequent + * modifications.<br /> + * <br /> + * @param stores a List of CertStores (or <code>null</code>) + * + * @exception ClassCastException if any of the elements in the + * list are not of type <code>java.security.cert.CertStore</code> + * + * @see #getCertStores() + **/ + public void setCertStores(List stores) + { + certStores = new ArrayList(); + if ( stores != null && ! stores.isEmpty() ) + { + Iterator iter = stores.iterator(); + CertStore obj; + while ( iter.hasNext() ) + { + obj = (CertStore)iter.next(); + if ( obj != null ) + { + certStores.add( obj ); + } + } + } + } + + /** + * Adds a CertStore to the end of the list of CertStores used + * in finding certificates and CRLs. + * + * @param store the <code>CertStore</code> to add. If + * <code>null</code<, the store is ignored (not added to + * list). + **/ + public void addCertStore(CertStore store) + { + if ( store != null ) + certStores.add( store ); + } + + /** + * Returns an immutable List of CertStores that are used to + * find certificates and CRLs. + * + * @return an immutable List of CertStores (may be empty, but never <code>null</code>) + * + * @see #setCertStores(java.util.List) + **/ + public List getCertStores() + { + return Collections.unmodifiableList(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).<br /> + * <br /> + * When a <code>PKIXParameters</code> 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 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 true if explicit policy is to be required, 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 true if explicit policy is required, 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 true if policy mapping is to be inhibited, 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()} + * returns false). + * + * @return val - <code>true</code> if the any policy OID is to be inhibited, <code>false</code> 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</code> if the any policy OID is inhibited, <code>false</code> 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.<br /> + * <br /> + * When a <code>PKIXParameters</code> 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.<br /> + * <br /> + * 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.<br /> + * <br /> + * When a 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(boolean) + **/ + public boolean getPolicyQualifiersRejected() + { + return policyQualifiersRejected; + } + + /** + * Returns the time for which the validity of the + * certification path should be determined. If null, the + * current time is used.<br /> + * <br /> + * Note that the Date returned is copied to protect against + * subsequent modifications. + * + * @return the Date, or <code>null</code> if not set + * + * @see #setDate(java.util.Date) + **/ + public Date getDate() + { + if ( date == null ) + return null; + + return new Date( date.getTime() ); + } + + /** + * Sets the time for which the validity of the certification + * path should be determined. If null, the current time is + * used.<br /> + * <br /> + * Note that the Date supplied here is copied to protect + * against subsequent modifications. + * + * @param date the Date, or <code>null</code> for the current time + * + * @see #getDate() + **/ + public void setDate(Date date) + { + if ( date == null ) + this.date = null; + else + this.date = new Date( date.getTime() ); + } + + /** + * Sets a <code>List</code> of additional certification path checkers. If + * the specified List contains an object that is not a + * PKIXCertPathChecker, it is ignored.<br /> + * <br /> + * Each <code>PKIXCertPathChecker</code> specified implements additional + * checks on a certificate. Typically, these are checks to + * process and verify private extensions contained in + * certificates. Each <code>PKIXCertPathChecker</code> should be + * instantiated with any initialization parameters needed to + * execute the check.<br /> + * <br /> + * This method allows sophisticated applications to extend a + * PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code>. Each of the + * specified PKIXCertPathCheckers will be called, in turn, by + * a PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code> for each + * certificate processed or validated.<br /> + * <br /> + * Regardless of whether these additional PKIXCertPathCheckers + * are set, a PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code> 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(boolean) setRevocationEnabled} method).<br /> + * <br /> + * Note that the List supplied here is copied and each + * PKIXCertPathChecker in the list is cloned to protect against + * subsequent modifications. + * + * @param checkers a List of PKIXCertPathCheckers. May be + * null, in which case no additional checkers will be used. + * @exception ClassCastException if any of the elements in the + * list are not of type + * <code>java.security.cert.PKIXCertPathChecker</code> + * @see #getCertPathCheckers() + **/ + public void setCertPathCheckers(List checkers) + { + certPathCheckers = new ArrayList(); + if ( checkers == null ) + return; + Iterator iter = checkers.iterator(); + while ( iter.hasNext() ) + certPathCheckers.add( (PKIXCertPathChecker)((PKIXCertPathChecker)iter.next()).clone() ); + } + + /** + * Returns the List of certification path checkers. The + * returned List is immutable, and each PKIXCertPathChecker in + * the List is cloned to protect against subsequent + * modifications. + * + * @return an immutable List of PKIXCertPathCheckers (may be empty, but not <code>null</code>) + * + * @see #setCertPathCheckers(java.util.List) + **/ + public List getCertPathCheckers() + { + List checkers = new ArrayList(); + Iterator iter = certPathCheckers.iterator(); + while ( iter.hasNext() ) + { + checkers.add( (PKIXCertPathChecker)((PKIXCertPathChecker)iter.next()).clone() ); + } + return Collections.unmodifiableList(checkers); + } + + /** + * Adds a PKIXCertPathChecker to the list of certification + * path checkers. See the {@link #setCertPathCheckers} method for more + * details.<br /> + * <br /> + * Note that the <code>PKIXCertPathChecker</code> is cloned to protect + * against subsequent modifications. + * + * @param checker a <code>PKIXCertPathChecker</code> to add + * to the list of checks. If <code>null</code>, the checker is + * ignored (not added to list). + **/ + public void addCertPathChecker( PKIXCertPathChecker checker ) + { + if ( checker != null ) + { + certPathCheckers.add( checker.clone() ); + } + } + + /** + * Returns the signature provider's name, or <code>null</code> if not set. + * + * @return the signature provider's name (or <code>null</code>) + * + * @see #setSigProvider(java.lang.String) + **/ + public String getSigProvider() + { + return sigProvider; + } + + /** + * Sets the signature provider's name. The specified provider + * will be preferred when creating Signature objects. If null + * or not set, the first provider found supporting the + * algorithm will be used. + * + * @param sigProvider the signature provider's name (or <code>null</code>) + * + * @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 + * CertSelector. If <code>null</code>, no constraints are defined.<br /> + * <br /> + * Note that the CertSelector returned is cloned to protect + * against subsequent modifications. + * + * @return a CertSelector specifying the constraints on the target certificate (or <code>null</code>) + * + * @see #setTargetCertConstraints(java.security.cert.CertSelector) + **/ + public CertSelector getTargetCertConstraints() + { + if ( certSelector == null ) + return null; + + return (CertSelector)certSelector.clone(); + } + + /** + * Sets the required constraints on the target + * certificate. The constraints are specified as an instance + * of CertSelector. If null, no constraints are defined.<br /> + * <br /> + * Note that the CertSelector specified is cloned to protect + * against subsequent modifications. + * + * @param selector a CertSelector specifying the constraints + * on the target certificate (or <code>null</code>) + * + * @see #getTargetCertConstraints() + **/ + public void setTargetCertConstraints(CertSelector selector) + { + if ( selector == null ) + certSelector = null; + else + certSelector = (CertSelector)selector.clone(); + } + + /** + * Makes a copy of this PKIXParameters object. Changes to the + * copy will not affect the original and vice versa. + * + * @return a copy of this <code>PKIXParameters</code> object + **/ + public Object clone() + { + try { + PKIXParameters obj = (PKIXParameters)super.clone(); + obj.certStores = new ArrayList( certStores ); + Iterator iter = certPathCheckers.iterator(); + obj.certPathCheckers = new ArrayList(); + while ( iter.hasNext() ) + { + obj.certPathCheckers.add( ((PKIXCertPathChecker)iter.next()).clone() ); + } + if ( initialPolicies != null ) + { + obj.initialPolicies = new HashSet( initialPolicies ); + } + if ( trustAnchors != null ) + { + obj.trustAnchors = new HashSet( trustAnchors ); + } + if ( certSelector != null ) + { + obj.certSelector = (CertSelector)certSelector.clone(); + } + return obj; + } catch ( CloneNotSupportedException ex ) { + throw new InternalError(); + } + } + + /** + * Returns a formatted string describing the parameters. + * + * @return a formatted string describing the parameters. + **/ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append("[\n"); + if ( trustAnchors != null ) + { + s.append(" Trust Anchors: ").append(trustAnchors).append('\n'); + } + if ( initialPolicies != null ) + { + if ( initialPolicies.isEmpty() ) + { + s.append(" Initial Policy OIDs: any\n" ); + } + else + { + s.append(" Initial Policy OIDs: [").append(initialPolicies).append("]\n"); + } + } + s.append(" Validity Date: "); + if ( date != null ) + s.append(date); + else + s.append("null"); + s.append('\n'); + + s.append(" Signature Provider: "); + if ( sigProvider != null ) + s.append(sigProvider); + else + s.append("null"); + s.append('\n'); + + s.append(" Default Revocation Enabled: "); + s.append(revocationEnabled); + s.append('\n' ); + + s.append(" Explicit Policy Required: "); + s.append(explicitPolicyRequired); + s.append('\n'); + + s.append(" Policy Mapping Inhibited: "); + s.append(policyMappingInhibited); + s.append('\n'); + + s.append(" Any Policy Inhibited: "); + s.append(anyPolicyInhibited); + s.append('\n'); + + s.append(" Policy Qualifiers Rejected: "); + s.append(policyQualifiersRejected); + s.append('\n'); + + s.append(" Target Cert Constraints: "); + s.append(certSelector); + s.append('\n'); + + s.append(" Certification Path Checkers: ["); + s.append(certPathCheckers); + s.append( "}\n"); + + s.append(" CertStores: ["); + s.append(certStores); + s.append("}\n"); + + s.append("]\n"); + + return s.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java new file mode 100644 index 000000000..cdae45205 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyNode.java @@ -0,0 +1,107 @@ +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.<br /> + * <br /> + * 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.<br /> + * <br /> + * 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</code>. However, + * the valid policy tree is available for more sophisticated applications, + * especially those that process policy qualifiers.<br /> + * <br /> + * {@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</code>.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * All <code>PolicyNode</code> objects must be immutable and + * thread-safe. Multiple threads may concurrently invoke the methods defined + * in this class on a single <code>PolicyNode</code> 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. + **/ +public interface PolicyNode +{ + + /** + * Returns the parent of this node, or <code>null</code> if this is the + * root node. + * + * @return the parent of this node, or <code>null</code> if this is the + * root node + */ + public PolicyNode getParent(); + + /** + * Returns an iterator over the children of this node. Any attempts to + * modify the children of this node through the + * <code>Iterator</code>'s remove method must throw an + * <code>UnsupportedOperationException</code>. + * + * @return an iterator over the children of this node + */ + public Iterator 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) + */ + public int getDepth(); + + /** + * Returns the valid policy represented by this node. + * + * @return the <code>String</code> OID of the valid policy + * represented by this node, or the special value "any-policy". For + * the root node, this method always returns the special value "any-policy". + */ + public String getValidPolicy(); + + /** + * Returns the set of policy qualifiers associated with the + * valid policy represented by this node. + * + * @return an immutable <code>Set</code> of + * <code>PolicyQualifierInfo</code>s. For the root node, this + * is always an empty <code>Set</code>. + */ + public Set 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</code> of expected policy + * <code>String</code> OIDs, or an immutable <code>Set</code> with + * the single special value "any-policy". For the root node, this method + * always returns a <code>Set</code> with the single value "any-policy". + */ + public Set getExpectedPolicies(); + + /** + * Returns the criticality indicator of the certificate policy extension + * in the most recently processed certificate. + * + * @return <code>true</code> if extension marked critical, + * <code>false</code> otherwise. For the root node, <code>false</code> + * is always returned. + */ + public boolean isCritical(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java new file mode 100644 index 000000000..a17f49bf4 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/PolicyQualifierInfo.java @@ -0,0 +1,196 @@ +package java.security.cert; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DEROutputStream; +import org.spongycastle.asn1.util.ASN1Dump; + +/** + * An immutable policy qualifier represented by the ASN.1 PolicyQualifierInfo + * structure.<br /> + * <br /> + * The ASN.1 definition is as follows:<br /> + * <br /> + * + * <pre> + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * </pre> + * + * <br /> + * <br /> + * 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.<br /> + * <br /> + * A <code>Set</code> of <code>PolicyQualifierInfo</code> 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</code> + * flag to false (by calling the + * {@link PKIXParameters#setPolicyQualifiersRejected + * PKIXParameters.setPolicyQualifiersRejected} method) before validating a + * certification path.<br /> + * <br /> + * 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</code> 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.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * All <code>PolicyQualifierInfo</code> 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</code> object + * (or more than one) with no ill effects. Requiring + * <code>PolicyQualifierInfo</code> objects to be immutable and thread-safe + * allows them to be passed around to various pieces of code without worrying + * about coordinating access.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier}, + * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object} + */ +public final class PolicyQualifierInfo +{ + private String id; + + private byte[] encoded; + + private byte[] qualifier; + + /** + * Creates an instance of <code>PolicyQualifierInfo</code> from the + * encoded bytes. The encoded byte array is copied on construction.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier} and + * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream} + * + * @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 + { + this.encoded = (byte[])encoded.clone(); + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + this.encoded); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Sequence obj = (ASN1Sequence)derInStream.readObject(); + id = ((ASN1ObjectIdentifier)obj.getObjectAt(0)).getId(); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + + derOutStream.writeObject(obj.getObjectAt(1)); + derOutStream.close(); + + qualifier = outStream.toByteArray(); + } + catch (Exception ex) + { + throw new IOException("parsing exception : " + ex.toString()); + } + } + + /** + * Returns the <code>policyQualifierId</code> field of this + * <code>PolicyQualifierInfo</code>. The <code>policyQualifierId</code> + * is an Object Identifier (OID) represented by a set of nonnegative + * integers separated by periods. + * + * @return the OID (never <code>null</code>) + */ + public String getPolicyQualifierId() + { + return id; + } + + /** + * Returns the ASN.1 DER encoded form of this + * <code>PolicyQualifierInfo</code>. + * + * @return the ASN.1 DER encoded bytes (never <code>null</code>). Note + * that a copy is returned, so the data is cloned each time this + * method is called. + */ + public byte[] getEncoded() + { + return (byte[])encoded.clone(); + } + + /** + * Returns the ASN.1 DER encoded form of the <code>qualifier</code> field + * of this <code>PolicyQualifierInfo</code>. + * + * @return the ASN.1 DER encoded bytes of the <code>qualifier</code> + * field. Note that a copy is returned, so the data is cloned each + * time this method is called. + */ + public byte[] getPolicyQualifier() + { + if (qualifier == null) + { + return null; + } + + return (byte[])qualifier.clone(); + } + + /** + * Return a printable representation of this + * <code>PolicyQualifierInfo</code>.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object} + * + * @return a <code>String</code> describing the contents of this + * <code>PolicyQualifierInfo</code> + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append("PolicyQualifierInfo: [\n"); + s.append("qualifierID: ").append(id).append('\n'); + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream(qualifier); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object derObject = derInStream.readObject(); + s + .append(" qualifier:\n").append(ASN1Dump.dumpAsString(derObject)) + .append('\n'); + } + catch (IOException ex) + { + s.append(ex.getMessage()); + } + s.append("qualifier: ").append(id).append('\n'); + s.append(']'); + return s.toString(); + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java new file mode 100644 index 000000000..f139a742c --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/TrustAnchor.java @@ -0,0 +1,293 @@ +package java.security.cert; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.PublicKey; +import java.security.cert.X509Certificate; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1Sequence; + +/** + * A trust anchor or most-trusted Certification Authority (CA). <br /> + * <br /> + * 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 X509Certificate or as individual + * parameters. <br /> + * <br /> + * <strong>Concurrent Access</strong><br /> + * <br /> + * All TrustAnchor objects must be immutable and thread-safe. That is, multiple + * threads may concurrently invoke the methods defined in this class on a + * single TrustAnchor object (or more than one) with no ill effects. Requiring + * 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.<br /> + * <br /> + * <b>TODO: implement better nameConstraints testing.</b> + **/ +public class TrustAnchor +{ + private X509Certificate trustCert = null; + + private PublicKey trustPublicKey = null; + + private String trustName = null; + + private byte[] nameConstraints = null; + + /** + * Creates an instance of TrustAnchor with the specified X509Certificate and + * optional name constraints, which are intended to be used as additional + * constraints when validating an X.509 certification path.<br /> + * <br /> + * 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 2459 and + * X.509. The ASN.1 definition of this structure appears below.<br /> + * <br /> + * + * <pre> + * 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> + * + * <br /> + * <br /> + * Note that the name constraints byte array supplied is cloned to protect + * against subsequent modifications. + * + * @param trustedCert + * a trusted 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 null to omit the + * parameter. + * + * @exception IllegalArgumentException + * if the name constraints cannot be decoded + * @exception NullPointerException + * if the specified X509Certificate is null + */ + public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) + { + if (trustedCert == null) + { + throw new NullPointerException("trustedCert must be non-null"); + } + + this.trustCert = trustedCert; + if (nameConstraints != null) + { + this.nameConstraints = (byte[])nameConstraints.clone(); + checkNameConstraints(this.nameConstraints); + } + } + + /** + * Creates an instance of <code>TrustAnchor</code> 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. + * + * 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 2459 and X.509. + * The ASN.1 notation for this structure is supplied in the documentation + * for {@link #TrustAnchor(X509Certificate trustedCert, byte[] + * nameConstraints) TrustAnchor(X509Certificate trustedCert, byte[] + * nameConstraints) }. + * + * 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 RFC + * 2253 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 null to omit the + * parameter. + * + * @exception IllegalArgumentException + * if the specified caName parameter is empty (<code>caName.length() == 0</code>) + * or incorrectly formatted or the name constraints cannot be + * decoded + * @exception NullPointerException + * if the specified caName or pubKey parameter is null + */ + public TrustAnchor(String caName, PublicKey pubKey, byte[] nameConstraints) + { + if (caName == null) + { + throw new NullPointerException("caName must be non-null"); + } + if (pubKey == null) + { + throw new NullPointerException("pubKey must be non-null"); + } + if (caName.length() == 0) + { + throw new IllegalArgumentException( + "caName can not be an empty string"); + } + + this.trustName = caName; + this.trustPublicKey = pubKey; + if (nameConstraints != null) + { + this.nameConstraints = (byte[])nameConstraints.clone(); + checkNameConstraints(this.nameConstraints); + } + } + + /** + * Returns the most-trusted CA certificate. + * + * @return a trusted <code>X509Certificate</code> or <code>null</code> + * if the trust anchor was not specified as a trusted certificate + */ + public final X509Certificate getTrustedCert() + { + return trustCert; + } + + /** + * Returns the name of the most-trusted CA in RFC 2253 String format. + * + * @return the X.500 distinguished name of the most-trusted CA, or + * <code>null</code> if the trust anchor was not specified as a + * trusted public key and name pair + */ + public final String getCAName() + { + return trustName; + } + + /** + * Returns the public key of the most-trusted CA. + * + * @return the public key of the most-trusted CA, or null if the trust + * anchor was not specified as a trusted public key and name pair + */ + public final PublicKey getCAPublicKey() + { + return trustPublicKey; + } + + /** + * 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.<br /> + * <br /> + * 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 2459 and X.509. + * The ASN.1 notation for this structure is supplied in the documentation + * for <code>TrustAnchor(X509Certificate trustedCert, byte[] + * nameConstraints)</code>.<br /> + * <br /> + * 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</code> if not set. + */ + public final byte[] getNameConstraints() + { + return (byte[])nameConstraints.clone(); + } + + /** + * Returns a formatted string describing the <code>TrustAnchor</code>. + * + * @return a formatted string describing the <code>TrustAnchor</code> + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("[\n"); + if (getCAPublicKey() != null) + { + sb.append(" Trusted CA Public Key: ").append(getCAPublicKey()).append('\n'); + sb.append(" Trusted CA Issuer Name: ").append(getCAName()).append('\n'); + } + else + { + sb.append(" Trusted CA cert: ").append(getTrustedCert()).append('\n'); + } + if (nameConstraints != null) + { + sb.append(" Name Constraints: ").append(nameConstraints).append('\n'); + } + return sb.toString(); + } + + /** + * Check given DER encoded nameConstraints for correct decoding. Currently + * only basic DER decoding test.<br /> + * <br /> + * <b>TODO: implement more testing.</b> + * + * @param data + * the DER encoded nameConstrains to be checked or + * <code>null</code> + * @exception IllegalArgumentException + * if the check failed. + */ + private void checkNameConstraints(byte[] data) + { + if (data != null) + { + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object derObject = derInStream.readObject(); + if (!(derObject instanceof ASN1Sequence)) + { + throw new IllegalArgumentException( + "nameConstraints parameter decoding error"); + } + } + catch (IOException ex) + { + throw new IllegalArgumentException( + "nameConstraints parameter decoding error: " + ex); + } + } + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java new file mode 100644 index 000000000..cf65ed0b6 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRL.java @@ -0,0 +1,77 @@ + +package java.security.cert; + +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Principal; +import java.security.PublicKey; +import java.security.SignatureException; +import java.util.Date; +import java.util.Set; + +public abstract class X509CRL extends CRL implements X509Extension +{ + protected X509CRL() + { + super("X.509"); + } + + public boolean equals(Object other) + { + if ( this == other ) + return true; + + if ( !(other instanceof X509CRL) ) + return false; + + try + { + byte[] enc1 = getEncoded(); + byte[] enc2 = ((X509CRL)other).getEncoded(); + + return MessageDigest.isEqual(enc1, enc2); + } + catch (CRLException e) + { + return false; + } + } + + public int hashCode() + { + int hashcode = 0; + + try + { + byte[] encoded = getEncoded(); + for (int i = 1; i < encoded.length; i++) + { + hashcode += encoded[i] * i; + } + } + catch (CRLException ce) + { + return(hashcode); + } + + return(hashcode); + } + + public abstract byte[] getEncoded() throws CRLException; + public abstract Principal getIssuerDN(); + public abstract Date getNextUpdate(); + public abstract X509CRLEntry getRevokedCertificate(BigInteger serialNumber); + public abstract Set getRevokedCertificates(); + public abstract String getSigAlgName(); + public abstract String getSigAlgOID(); + public abstract byte[] getSigAlgParams(); + public abstract byte[] getSignature(); + public abstract byte[] getTBSCertList() throws CRLException; + public abstract Date getThisUpdate(); + public abstract int getVersion(); + public abstract void verify(PublicKey key) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException; + public abstract void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException; +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java new file mode 100644 index 000000000..bb0d78074 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLEntry.java @@ -0,0 +1,56 @@ + +package java.security.cert; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.Date; + +public abstract class X509CRLEntry implements X509Extension +{ + public boolean equals(Object other) + { + if ( this == other ) + return true; + + if ( !(other instanceof X509CRLEntry) ) + return false; + + try + { + byte[] enc1 = getEncoded(); + byte[] enc2 = ((X509CRLEntry)other).getEncoded(); + + return MessageDigest.isEqual(enc1, enc2); + } + catch (CRLException e) + { + return false; + } + } + + public int hashCode() + { + int hashcode = 0; + + try + { + byte[] encoded = getEncoded(); + for (int i = 1; i < encoded.length; i++) + { + hashcode += encoded[i] * i; + } + } + catch (CRLException ce) + { + return(hashcode); + } + + return(hashcode); + } + + public abstract byte[] getEncoded() throws CRLException; + public abstract Date getRevocationDate(); + public abstract BigInteger getSerialNumber(); + public abstract boolean hasExtensions(); + public abstract String toString(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java new file mode 100644 index 000000000..7971e7b61 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CRLSelector.java @@ -0,0 +1,717 @@ +package java.security.cert; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRL; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.jce.PrincipalUtil; + +/** + * A <code>CRLSelector</code> that selects <code>X509CRLs</code> that match + * all specified criteria. This class is particularly useful when selecting CRLs + * from a <code>CertStore</code> to check revocation status of a particular + * certificate.<br /> + * <br /> + * When first constructed, an <code>X509CRLSelector</code> has no criteria + * enabled and each of the <code>get</code> methods return a default value (<code>null</code>). + * Therefore, the {@link #match match} method would return <code>true</code> + * for any <code>X509CRL</code>. Typically, several criteria are enabled (by + * calling {@link #setIssuerNames setIssuerNames} or + * {@link #setDateAndTime setDateAndTime}, for instance) and then the + * <code>X509CRLSelector</code> is passed to + * {@link CertStore#getCRLs CertStore.getCRLs} or some similar method.<br /> + * <br /> + * Please refer to RFC 2459 for definitions of the X.509 CRL fields and + * extensions mentioned below.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier}, + * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name} + * + * @see CRLSelector + * @see X509CRL + */ +public class X509CRLSelector implements CRLSelector +{ + private Set issuerNames = null; + + private Set issuerNamesX509 = null; + + private BigInteger minCRL = null; + + private BigInteger maxCRL = null; + + private Date dateAndTime = null; + + private X509Certificate certChecking = null; + + /** + * Creates an <code>X509CRLSelector</code>. Initially, no criteria are + * set so any <code>X509CRL</code> will match. + */ + public X509CRLSelector() + { + } + + /** + * Sets the issuerNames criterion. The issuer distinguished name in the + * <code>X509CRL</code> must match at least one of the specified + * distinguished names. If <code>null</code>, any issuer distinguished + * name will do.<br /> + * <br /> + * This method allows the caller to specify, with a single method call, the + * complete set of issuer names which <code>X509CRLs</code> may contain. + * The specified value replaces the previous value for the issuerNames + * criterion.<br /> + * <br /> + * The <code>names</code> parameter (if not <code>null</code>) is a + * <code>Collection</code> of names. Each name is a <code>String</code> + * or a byte array representing a distinguished name (in RFC 2253 or ASN.1 + * DER encoded form, respectively). If <code>null</code> is supplied as + * the value for this argument, no issuerNames check will be performed.<br /> + * <br /> + * Note that the <code>names</code> parameter can contain duplicate + * distinguished names, but they may be removed from the + * <code>Collection</code> of names returned by the + * {@link #getIssuerNames getIssuerNames} method.<br /> + * <br /> + * 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 RDN + * + * RDN ::= + * 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)) } + * </code></pre> + * + * <br /> + * <br /> + * Note that a deep copy is performed on the <code>Collection</code> to + * protect against subsequent modifications. + * + * @param names + * a <code>Collection</code> of names (or <code>null</code>) + * + * @exception IOException + * if a parsing error occurs + * + * @see #getIssuerNames + */ + public void setIssuerNames(Collection names) throws IOException + { + if (names == null || names.isEmpty()) + { + issuerNames = null; + issuerNamesX509 = null; + } + else + { + Object item; + Iterator iter = names.iterator(); + while (iter.hasNext()) + { + item = iter.next(); + if (item instanceof String) + { + addIssuerName((String)item); + } + else if (item instanceof byte[]) + { + addIssuerName((byte[])item); + } + else + { + throw new IOException("name not byte[]or String: " + + item.toString()); + } + } + } + } + + /** + * Adds a name to the issuerNames criterion. The issuer distinguished name + * in the <code>X509CRL</code> must match at least one of the specified + * distinguished names.<br /> + * <br /> + * This method allows the caller to add a name to the set of issuer names + * which <code>X509CRLs</code> 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.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the + * name + * + * @param name + * the name in RFC 2253 form + * + * @exception IOException + * if a parsing error occurs + */ + public void addIssuerName(String name) throws IOException + { + if (issuerNames == null) + { + issuerNames = new HashSet(); + issuerNamesX509 = new HashSet(); + } + X509Name nameX509; + try + { + nameX509 = new X509Name(name); + } + catch (IllegalArgumentException ex) + { + throw new IOException(ex.getMessage()); + } + issuerNamesX509.add(nameX509); + issuerNames.add(name); + } + + /** + * Adds a name to the issuerNames criterion. The issuer distinguished name + * in the <code>X509CRL</code> must match at least one of the specified + * distinguished names.<br /> + * <br /> + * This method allows the caller to add a name to the set of issuer names + * which <code>X509CRLs</code> 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.<br /> + * <br /> + * 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)}.<br /> + * <br /> + * Note that the byte array supplied here is cloned to protect against + * subsequent modifications.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the + * name, {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object} and + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence} + * + * @param name + * a byte array containing the name in ASN.1 DER encoded form + * + * @exception IOException + * if a parsing error occurs + */ + public void addIssuerName(byte[] name) throws IOException + { + if (issuerNames == null) + { + issuerNames = new HashSet(); + issuerNamesX509 = new HashSet(); + } + + ByteArrayInputStream inStream = new ByteArrayInputStream(name); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object obj = derInStream.readObject(); + if (obj instanceof ASN1Sequence) + { + issuerNamesX509.add(new X509Name((ASN1Sequence)obj)); + } + else + { + throw new IOException("parsing error"); + } + issuerNames.add(name.clone()); + } + + /** + * Sets the minCRLNumber criterion. The <code>X509CRL</code> must have a + * CRL number extension whose value is greater than or equal to the + * specified value. If <code>null</code>, no minCRLNumber check will be + * done. + * + * @param minCRL + * the minimum CRL number accepted (or <code>null</code>) + */ + public void setMinCRLNumber(BigInteger minCRL) + { + this.minCRL = minCRL; + } + + /** + * Sets the maxCRLNumber criterion. The <code>X509CRL</code> must have a + * CRL number extension whose value is less than or equal to the specified + * value. If <code>null</code>, no maxCRLNumber check will be done. + * + * @param maxCRL + * the maximum CRL number accepted (or <code>null</code>) + */ + 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</code> and earlier than the value of the nextUpdate + * component. There is no match if the <code>X509CRL</code> does not + * contain a nextUpdate component. If <code>null</code>, no dateAndTime + * check will be done.<br /> + * <br /> + * Note that the <code>Date</code> supplied here is cloned to protect + * against subsequent modifications. + * + * @param dateAndTime + * the <code>Date</code> to match against (or <code>null</code>) + * + * @see #getDateAndTime + */ + public void setDateAndTime(Date dateAndTime) + { + if (dateAndTime == null) + { + this.dateAndTime = null; + } + else + { + this.dateAndTime = new Date(dateAndTime.getTime()); + } + } + + /** + * Sets the certificate being checked. This is not a criterion. Rather, it + * is optional information that may help a <code>CertStore</code> find + * CRLs that would be relevant when checking revocation for the specified + * certificate. If <code>null</code> is specified, then no such optional + * information is provided. + * + * @param cert + * the <code>X509Certificate</code> being checked (or + * <code>null</code>) + * + * @see #getCertificateChecking + */ + public void setCertificateChecking(X509Certificate cert) + { + certChecking = cert; + } + + /** + * Returns a copy of the issuerNames criterion. The issuer distinguished + * name in the <code>X509CRL</code> must match at least one of the + * specified distinguished names. If the value returned is <code>null</code>, + * any issuer distinguished name will do.<br /> + * <br /> + * If the value returned is not <code>null</code>, it is a + * <code>Collection</code> of names. Each name is a <code>String</code> + * or a byte array representing a distinguished name (in RFC 2253 or ASN.1 + * DER encoded form, respectively). Note that the <code>Collection</code> + * returned may contain duplicate names.<br /> + * <br /> + * 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)}.<br /> + * <br /> + * Note that a deep copy is performed on the <code>Collection</code> to + * protect against subsequent modifications. + * + * @return a <code>Collection</code> of names (or <code>null</code>) + * @see #setIssuerNames + */ + public Collection getIssuerNames() + { + if (issuerNames == null) + { + return null; + } + + Collection set = new HashSet(); + Iterator iter = issuerNames.iterator(); + Object item; + while (iter.hasNext()) + { + item = iter.next(); + if (item instanceof String) + { + set.add(new String((String)item)); + } + else if (item instanceof byte[]) + { + set.add(((byte[])item).clone()); + } + } + return set; + } + + /** + * Returns the minCRLNumber criterion. The <code>X509CRL</code> must have + * a CRL number extension whose value is greater than or equal to the + * specified value. If <code>null</code>, no minCRLNumber check will be + * done. + * + * @return the minimum CRL number accepted (or <code>null</code>) + */ + public BigInteger getMinCRL() + { + return minCRL; + } + + /** + * Returns the maxCRLNumber criterion. The <code>X509CRL</code> must have + * a CRL number extension whose value is less than or equal to the specified + * value. If <code>null</code>, no maxCRLNumber check will be done. + * + * @return the maximum CRL number accepted (or <code>null</code>) + */ + 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</code> and earlier than the value of the nextUpdate + * component. There is no match if the <code>X509CRL</code> does not + * contain a nextUpdate component. If <code>null</code>, no dateAndTime + * check will be done.<br /> + * <br /> + * Note that the <code>Date</code> returned is cloned to protect against + * subsequent modifications. + * + * @return the <code>Date</code> to match against (or <code>null</code>) + * + * @see #setDateAndTime + */ + public Date getDateAndTime() + { + if (dateAndTime == null) + { + return null; + } + + return new Date(dateAndTime.getTime()); + } + + /** + * Returns the certificate being checked. This is not a criterion. Rather, + * it is optional information that may help a <code>CertStore</code> find + * CRLs that would be relevant when checking revocation for the specified + * certificate. If the value returned is <code>null</code>, then no such + * optional information is provided. + * + * @return the certificate being checked (or <code>null</code>) + * + * @see #setCertificateChecking + */ + public X509Certificate getCertificateChecking() + { + return certChecking; + } + + /** + * Returns a printable representation of the <code>X509CRLSelector</code>.<br /> + * <br /> + * Uses + * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to + * format the output + * + * @return a <code>String</code> describing the contents of the + * <code>X509CRLSelector</code>. + */ + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append("X509CRLSelector: [\n"); + if (issuerNamesX509 != null) + { + s.append(" IssuerNames:\n"); + Iterator iter = issuerNamesX509.iterator(); + while (iter.hasNext()) + { + s.append(" ").append(iter.next()).append('\n'); + } + } + if (minCRL != null) + { + s.append(" minCRLNumber: ").append(minCRL).append('\n'); + } + if (maxCRL != null) + { + s.append(" maxCRLNumber: ").append(maxCRL).append('\n'); + } + if (dateAndTime != null) + { + s.append(" dateAndTime: ").append(dateAndTime).append('\n'); + } + if (certChecking != null) + { + s.append(" Certificate being checked: ").append(certChecking).append('\n'); + } + s.append(']'); + return s.toString(); + } + + /** + * Decides whether a <code>CRL</code> should be selected.<br /> + * <br /> + * Uses + * {@link org.spongycastle.asn1.x509.X509Name#toString X509Name.toString} to + * parse and to compare the crl parameter issuer and + * {@link org.spongycastle.asn1.x509.X509Extensions#CRLNumber CRLNumber} to + * access the CRL number extension. + * + * @param crl + * the <code>CRL</code> to be checked + * + * @return <code>true</code> if the <code>CRL</code> should be selected, + * <code>false</code> otherwise + */ + public boolean match(CRL crl) + { + if (!(crl instanceof X509CRL)) + { + return false; + } + + X509CRL crlX509 = (X509CRL)crl; + boolean test; + + if (issuerNamesX509 != null) + { + Iterator iter = issuerNamesX509.iterator(); + test = false; + X509Name crlIssuer = null; + try + { + crlIssuer = PrincipalUtil.getIssuerX509Principal(crlX509); + } + catch (Exception ex) + { + + return false; + } + + while (iter.hasNext()) + { + if (crlIssuer.equals(iter.next(), true)) + { + test = true; + break; + } + } + if (!test) + { + return false; + } + } + + byte[] data = crlX509.getExtensionValue(X509Extensions.CRLNumber + .getId()); + if (data != null) + { + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + inStream = new ByteArrayInputStream( + ((ASN1OctetString)derInputStream.readObject()) + .getOctets()); + derInputStream = new ASN1InputStream(inStream); + BigInteger crlNumber = ((DERInteger)derInputStream.readObject()) + .getPositiveValue(); + if (minCRL != null && minCRL.compareTo(crlNumber) > 0) + { + return false; + } + if (maxCRL != null && maxCRL.compareTo(crlNumber) < 0) + { + return false; + } + } + catch (IOException ex) + { + return false; + } + } + else if (minCRL != null || maxCRL != null) + { + return false; + } + + if (dateAndTime != null) + { + Date check = crlX509.getThisUpdate(); + if (check == null) + { + return false; + } + else if (dateAndTime.before(check)) + { + return false; + } + + check = crlX509.getNextUpdate(); + if (check == null) + { + return false; + } + else if (!dateAndTime.before(check)) + { + 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(); + Iterator iter = issuerNames.iterator(); + Object obj; + while (iter.hasNext()) + { + obj = iter.next(); + if (obj instanceof byte[]) + { + copy.issuerNames.add(((byte[])obj).clone()); + } + else + { + copy.issuerNames.add(obj); + } + } + copy.issuerNamesX509 = new HashSet(issuerNamesX509); + } + return copy; + } + catch (CloneNotSupportedException e) + { + /* Cannot happen */ + throw new InternalError(e.toString()); + } + } + + /** + * Decides whether a <code>CRL</code> should be selected. + * + * @param crl + * the <code>CRL</code> to be checked + * + * @return <code>true</code> if the <code>CRL</code> should be selected, + * <code>false</code> otherwise + */ + public boolean equals(Object obj) + { + if (!(obj instanceof X509CRLSelector)) + { + return false; + } + + X509CRLSelector equalsCRL = (X509CRLSelector)obj; + + if (!equals(dateAndTime, equalsCRL.dateAndTime)) + { + return false; + } + + if (!equals(minCRL, equalsCRL.minCRL)) + { + return false; + } + + if (!equals(maxCRL, equalsCRL.maxCRL)) + { + return false; + } + + if (!equals(issuerNamesX509, equalsCRL.issuerNamesX509)) + { + return false; + } + + if (!equals(certChecking, equalsCRL.certChecking)) + { + return false; + } + + return true; + } + + /** + * Return <code>true</code> if two Objects are unequal. + * This means that one is <code>null</code> and the other is + * not or <code>obj1.equals(obj2)</code> returns + * <code>false</code>. + **/ + private boolean equals(Object obj1, Object obj2) + { + if (obj1 == null) + { + if (obj2 != null) + { + return true; + } + } + else if (!obj1.equals(obj2)) + { + return true; + } + return false; + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java new file mode 100644 index 000000000..89767cde5 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509CertSelector.java @@ -0,0 +1,2461 @@ +package java.security.cert; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.PublicKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Object; +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.ASN1OctetString; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.ASN1TaggedObject; +import org.spongycastle.asn1.DERGeneralizedTime; +import org.spongycastle.asn1.DEROutputStream; +import org.spongycastle.asn1.util.ASN1Dump; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.ExtendedKeyUsage; +import org.spongycastle.asn1.x509.KeyPurposeId; +import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.asn1.x509.X509Name; +import org.spongycastle.jce.PrincipalUtil; +import org.spongycastle.util.Integers; + +/** + * A <code>CertSelector</code> that selects + * <code>X509Certificates that match all + * specified criteria. This class is particularly useful when + * selecting certificates from a CertStore to build a PKIX-compliant + * certification path.<br /> + * <br /> + * When first constructed, an <code>X509CertSelector</code> has no criteria enabled + * and each of the get methods return a default value (<code>null</code>, or -1 for + * the {@link #getBasicConstraints} method). Therefore, the {@link #match} method would + * return true for any <code>X509Certificate</code>. Typically, several criteria + * are enabled (by calling {@link #setIssuer} or {@link #setKeyUsage}, for instance) and + * then the <code>X509CertSelector</code> is passed to {@link CertStore#getCertificates} or + * some similar method.<br /> + * <br /> + * Several criteria can be enabled (by calling {@link #setIssuer} and + * {@link #setSerialNumber}, for example) such that the match method usually + * uniquely matches a single <code>X509Certificate</code>. 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.<br /> + * <br /> + * Please refer to RFC 2459 for definitions of the X.509 certificate + * extensions mentioned below.<br /> + * <br /> + * <b>Concurrent Access</b><br /> + * <br /> + * 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.<br /> + * <br /> + * <b>TODO: implement name constraints</b> + * <b>TODO: implement match check for path to names</b><br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier}, + * {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.OIDTokenizer OIDTokenizer}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name}, + * {@link org.spongycastle.asn1.x509.X509Extensions X509Extensions}, + * {@link org.spongycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage}, + * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId}, + * {@link org.spongycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo}, + * {@link org.spongycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier} + */ +public class X509CertSelector implements CertSelector +{ + private static final Hashtable keyPurposeIdMap = new Hashtable(); + static + { + keyPurposeIdMap.put(KeyPurposeId.id_kp_serverAuth.getId(), + KeyPurposeId.id_kp_serverAuth); + keyPurposeIdMap.put(KeyPurposeId.id_kp_clientAuth.getId(), + KeyPurposeId.id_kp_clientAuth); + keyPurposeIdMap.put(KeyPurposeId.id_kp_codeSigning.getId(), + KeyPurposeId.id_kp_codeSigning); + keyPurposeIdMap.put(KeyPurposeId.id_kp_emailProtection.getId(), + KeyPurposeId.id_kp_emailProtection); + keyPurposeIdMap.put(KeyPurposeId.id_kp_ipsecEndSystem.getId(), + KeyPurposeId.id_kp_ipsecEndSystem); + keyPurposeIdMap.put(KeyPurposeId.id_kp_ipsecTunnel.getId(), + KeyPurposeId.id_kp_ipsecTunnel); + keyPurposeIdMap.put(KeyPurposeId.id_kp_ipsecUser.getId(), + KeyPurposeId.id_kp_ipsecUser); + keyPurposeIdMap.put(KeyPurposeId.id_kp_timeStamping.getId(), + KeyPurposeId.id_kp_timeStamping); + } + + private X509Certificate x509Cert = null; + + private BigInteger serialNumber = null; + + private Object issuerDN = null; + + private X509Name issuerDNX509 = null; + + private Object subjectDN = null; + + private X509Name subjectDNX509 = null; + + private byte[] subjectKeyID = null; + + private byte[] authorityKeyID = null; + + private Date certValid = null; + + private Date privateKeyValid = null; + + private ASN1ObjectIdentifier subjectKeyAlgID = null; + + private PublicKey subjectPublicKey = null; + + private byte[] subjectPublicKeyByte = null; + + private boolean[] keyUsage = null; + + private Set keyPurposeSet = null; + + private boolean matchAllSubjectAltNames = true; + + private Set subjectAltNames = null; + + private Set subjectAltNamesByte = null; + + private int minMaxPathLen = -1; + + private Set policy = null; + + private Set policyOID = null; + + private Set pathToNames = null; + + private Set pathToNamesByte = null; + + /** + * Creates an <code>X509CertSelector</code>. Initially, no criteria are + * set so any <code>X509Certificate</code> will match. + */ + public X509CertSelector() + { + } + + /** + * Sets the certificateEquals criterion. The specified + * <code>X509Certificate</code> must be equal to the + * <code>X509Certificate</code> passed to the match method. If + * <code>null</code>, then this check is not applied.<br /> + * <br /> + * 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 X509Certificate to match (or <code>null</code>) + * + * @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</code>. If + * <code>null</code>, any certificate serial number will do. + * + * @param serial + * the certificate serial number to match (or <code>null</code>) + * + * @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</code>. If + * <code>null</code>, any issuer distinguished name will do.<br /> + * <br /> + * If <code>issuerDN</code> is not <code>null</code>, it should contain + * a distinguished name, in RFC 2253 format.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the + * issuerDN. + * + * @param issuerDN + * a distinguished name in RFC 2253 format (or <code>null</code>) + * + * @exception IOException + * if a parsing error occurs (incorrect form for DN) + */ + public void setIssuer(String issuerDN) throws IOException + { + if (issuerDN == null) + { + this.issuerDN = null; + this.issuerDNX509 = null; + } + else + { + X509Name nameX509; + try + { + nameX509 = new X509Name(issuerDN); + } + catch (IllegalArgumentException ex) + { + throw new IOException(ex.getMessage()); + } + this.issuerDNX509 = nameX509; + this.issuerDN = issuerDN; + } + } + + /** + * Sets the issuer criterion. The specified distinguished name must match + * the issuer distinguished name in the <code>X509Certificate</code>. If + * null is specified, the issuer criterion is disabled and any issuer + * distinguished name will do.<br /> + * <br /> + * If <code>issuerDN</code> is not <code>null</code>, it should contain + * a single DER encoded distinguished name, as defined in X.501. The ASN.1 + * notation for this structure is as follows.<br /> + * <br /> + * + * <pre> + * Name ::= CHOICE { + * RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RDN + * + * RDN ::= + * 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> + * + * <br /> + * <br /> + * Note that the byte array specified here is cloned to protect against + * subsequent modifications.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name} + * + * @param issuerDN - + * a byte array containing the distinguished name in ASN.1 DER + * encoded form (or <code>null</code>) + * + * @exception IOException + * if an encoding error occurs (incorrect form for DN) + */ + public void setIssuer(byte[] issuerDN) throws IOException + { + if (issuerDN == null) + { + this.issuerDN = null; + this.issuerDNX509 = null; + } + else + { + ByteArrayInputStream inStream = new ByteArrayInputStream(issuerDN); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object obj = derInStream.readObject(); + if (obj instanceof ASN1Sequence) + { + this.issuerDNX509 = new X509Name((ASN1Sequence)obj); + } + else + { + throw new IOException("parsing error"); + } + this.issuerDN = (byte[])issuerDN.clone(); + } + } + + /** + * Sets the subject criterion. The specified distinguished name must match + * the subject distinguished name in the <code>X509Certificate</code>. If + * null, any subject distinguished name will do.<br /> + * <br /> + * If <code>subjectDN</code> is not <code>null</code>, it should + * contain a distinguished name, in RFC 2253 format.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for parsing the + * subjectDN. + * + * @param subjectDN + * a distinguished name in RFC 2253 format (or <code>null</code>) + * + * @exception IOException + * if a parsing error occurs (incorrect form for DN) + */ + public void setSubject(String subjectDN) throws IOException + { + if (subjectDN == null) + { + this.subjectDN = null; + this.subjectDNX509 = null; + } + else + { + X509Name nameX509; + try + { + nameX509 = new X509Name(subjectDN); + } + catch (IllegalArgumentException ex) + { + throw new IOException(ex.getMessage()); + } + + this.subjectDNX509 = nameX509; + this.subjectDN = subjectDN; + } + } + + /** + * Sets the subject criterion. The specified distinguished name must match + * the subject distinguished name in the <code>X509Certificate</code>. If + * null, any subject distinguished name will do.<br /> + * <br /> + * If <code>subjectDN</code> is not <code>null</code>, 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 []) setIssuer(byte [] issuerDN)}.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name} + * + * @param subjectDN + * a byte array containing the distinguished name in ASN.1 DER + * format (or <code>null</code>) + * + * @exception IOException + * if an encoding error occurs (incorrect form for DN) + */ + public void setSubject(byte[] subjectDN) throws IOException + { + if (subjectDN == null) + { + this.subjectDN = null; + this.subjectDNX509 = null; + } + else + { + ByteArrayInputStream inStream = new ByteArrayInputStream(subjectDN); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object obj = derInStream.readObject(); + + if (obj instanceof ASN1Sequence) + { + this.subjectDNX509 = new X509Name((ASN1Sequence)obj); + } + else + { + throw new IOException("parsing error"); + } + this.subjectDN = (byte[])subjectDN.clone(); + } + } + + /** + * Sets the subjectKeyIdentifier criterion. The <code>X509Certificate</code> + * must contain a SubjectKeyIdentifier extension for which the contents of + * the extension matches the specified criterion value. If the criterion + * value is null, no subjectKeyIdentifier check will be done.<br /> + * <br /> + * If <code>subjectKeyID</code> is not <code>null</code>, 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.<br /> + * <br /> + * + * <pre> + * SubjectKeyIdentifier ::= KeyIdentifier + * + * KeyIdentifier ::= OCTET STRING + * </pre> + * + * <br /> + * <br /> + * Since the format of subject key identifiers is not mandated by any + * standard, subject key identifiers are not parsed by the + * <code>X509CertSelector</code>. Instead, the values are compared using + * a byte-by-byte comparison.<br /> + * <br /> + * Note that the byte array supplied here is cloned to protect against + * subsequent modifications. + * + * @param subjectKeyID - + * the subject key identifier (or <code>null</code>) + * + * @see #getSubjectKeyIdentifier() + */ + public void setSubjectKeyIdentifier(byte[] subjectKeyID) + { + if (subjectKeyID == null) + { + this.subjectKeyID = null; + } + else + { + this.subjectKeyID = (byte[])subjectKeyID.clone(); + } + } + + /** + * Sets the authorityKeyIdentifier criterion. The + * <code>X509Certificate</code> 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</code>, + * no authorityKeyIdentifier check will be done.<br /> + * <br /> + * If <code>authorityKeyID</code> is not <code>null</code>, 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.<br /> + * <br /> + * + * <pre> + * AuthorityKeyIdentifier ::= SEQUENCE { + * keyIdentifier [0] KeyIdentifier OPTIONAL, + * authorityCertIssuer [1] GeneralNames OPTIONAL, + * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + * + * KeyIdentifier ::= OCTET STRING + * </pre> + * + * <br /> + * <br /> + * Authority key identifiers are not parsed by the + * <code>X509CertSelector</code>. Instead, the values are compared using + * a byte-by-byte comparison.<br /> + * <br /> + * When the <code>keyIdentifier</code> field of + * <code>AuthorityKeyIdentifier</code> is populated, the value is usually + * taken from the SubjectKeyIdentifier extension in the issuer's + * certificate. Note, however, that the result of + * X509Certificate.getExtensionValue(<SubjectKeyIdentifier Object + * Identifier>) on the issuer's certificate may NOT be used directly as the + * input to 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 + * SubjectKeyIdentifier extension, it will be necessary to extract the value + * of the embedded KeyIdentifier OCTET STRING, then DER encode this OCTET + * STRING inside a SEQUENCE. For more details on SubjectKeyIdentifier, see + * {@link #setSubjectKeyIdentifier(byte[]) setSubjectKeyIdentifier(byte[] subjectKeyID }).<br /> + * <br /> + * Note also that the byte array supplied here is cloned to protect against + * subsequent modifications. + * + * @param authorityKeyID + * the authority key identifier (or <code>null</code>) + * + * @see #getAuthorityKeyIdentifier() + */ + public void setAuthorityKeyIdentifier(byte[] authorityKeyID) + { + if (authorityKeyID == null) + { + this.authorityKeyID = null; + } + else + { + this.authorityKeyID = (byte[])authorityKeyID.clone(); + } + } + + /** + * Sets the certificateValid criterion. The specified date must fall within + * the certificate validity period for the X509Certificate. If + * <code>null</code>, no certificateValid check will be done.<br /> + * <br /> + * Note that the Date supplied here is cloned to protect against subsequent + * modifications. + * + * @param certValid + * the Date to check (or <code>null</code>) + * + * @see #getCertificateValid() + */ + public void setCertificateValid(Date certValid) + { + if (certValid == null) + { + this.certValid = null; + } + else + { + this.certValid = new Date(certValid.getTime()); + } + } + + /** + * Sets the privateKeyValid criterion. The specified date must fall within + * the private key validity period for the X509Certificate. If + * <code>null</code>, no privateKeyValid check will be done.<br /> + * <br /> + * Note that the Date supplied here is cloned to protect against subsequent + * modifications. + * + * @param privateKeyValid + * the Date to check (or <code>null</code>) + * + * @see #getPrivateKeyValid() + */ + public void setPrivateKeyValid(Date privateKeyValid) + { + if (privateKeyValid == null) + { + this.privateKeyValid = null; + } + else + { + this.privateKeyValid = new Date(privateKeyValid.getTime()); + } + } + + /** + * Sets the subjectPublicKeyAlgID criterion. The X509Certificate must + * contain a subject public key with the specified algorithm. If + * <code>null</code>, no subjectPublicKeyAlgID check will be done. + * + * @param oid + * The object identifier (OID) of the algorithm to check for (or + * <code>null</code>). An OID is represented by a set of + * nonnegative integers separated by periods. + * + * @exception 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 + { + CertUtil.parseOID(oid); + subjectKeyAlgID = new ASN1ObjectIdentifier(oid); + } + + /** + * Sets the subjectPublicKey criterion. The X509Certificate must contain the + * specified subject public key. If null, no subjectPublicKey check will be + * done. + * + * @param key + * the subject public key to check for (or null) + * + * @see #getSubjectPublicKey() + */ + public void setSubjectPublicKey(PublicKey key) + { + if (key == null) + { + subjectPublicKey = null; + subjectPublicKeyByte = null; + } + else + { + subjectPublicKey = key; + subjectPublicKeyByte = key.getEncoded(); + } + } + + /** + * Sets the subjectPublicKey criterion. The <code>X509Certificate</code> + * must contain the specified subject public key. If <code>null</code>, + * no subjectPublicKey check will be done.<br /> + * <br /> + * Because this method allows the public key to be specified as a byte + * array, it may be used for unknown key types.<br /> + * <br /> + * If key is not <code>null</code>, it should contain a single DER + * encoded SubjectPublicKeyInfo structure, as defined in X.509. The ASN.1 + * notation for this structure is as follows.<br /> + * <br /> + * + * <pre> + * 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> + * + * <br /> + * <br /> + * 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</code>) + * + * @exception 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; + subjectPublicKeyByte = null; + } + else + { + subjectPublicKey = null; + subjectPublicKeyByte = (byte[])key.clone(); + // TODO + // try to generyte PublicKey Object from subjectPublicKeyByte + } + } + + /** + * Sets the keyUsage criterion. The X509Certificate must allow the specified + * keyUsage values. If null, no keyUsage check will be done. Note that an + * X509Certificate that has no keyUsage extension implicitly allows all + * keyUsage values.<br /> + * <br /> + * 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 X509Certificate.getKeyUsage(). Or + * <code>null</code>. + * + * @see #getKeyUsage() + */ + public void setKeyUsage(boolean[] keyUsage) + { + if (keyUsage == null) + { + this.keyUsage = null; + } + else + { + this.keyUsage = (boolean[])keyUsage.clone(); + } + } + + /** + * Sets the extendedKeyUsage criterion. The <code>X509Certificate</code> + * must allow the specified key purposes in its extended key usage + * extension. If <code>keyPurposeSet</code> is empty or <code>null</code>, + * no extendedKeyUsage check will be done. Note that an + * <code>X509Certificate</code> that has no extendedKeyUsage extension + * implicitly allows all key purposes.<br /> + * <br /> + * Note that the Set is cloned to protect against subsequent modifications.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId} + * + * @param keyPurposeSet + * a <code>Set</code> of key purpose OIDs in string format (or + * <code>null</code>). Each OID is represented by a set of + * nonnegative integers separated by periods. + * + * @exception 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 keyPurposeSet) throws IOException + { + if (keyPurposeSet == null || keyPurposeSet.isEmpty()) + { + this.keyPurposeSet = keyPurposeSet; + } + else + { + this.keyPurposeSet = new HashSet(); + Iterator iter = keyPurposeSet.iterator(); + Object obj; + KeyPurposeId purposeID; + while (iter.hasNext()) + { + obj = iter.next(); + if (obj instanceof String) + { + purposeID = (KeyPurposeId)keyPurposeIdMap.get((String)obj); + if (purposeID == null) + { + throw new IOException("unknown purposeID " + + (String)obj); + } + this.keyPurposeSet.add(purposeID); + } + } + } + } + + /** + * Enables/disables matching all of the subjectAlternativeNames specified in + * the {@link #setSubjectAlternativeNames setSubjectAlternativeNames} or + * {@link #addSubjectAlternativeName addSubjectAlternativeName} methods. If + * enabled, the <code>X509Certificate</code> must contain all of the + * specified subject alternative names. If disabled, the X509Certificate + * must contain at least one of the specified subject alternative names.<br /> + * <br /> + * The matchAllNames flag is <code>true</code> by default. + * + * @param matchAllNames + * if <code>true</code>, the flag is enabled; if + * <code>false</code>, the flag is disabled. + * + * @see #getMatchAllSubjectAltNames() + */ + public void setMatchAllSubjectAltNames(boolean matchAllNames) + { + matchAllSubjectAltNames = matchAllNames; + } + + /** + * Sets the subjectAlternativeNames criterion. The + * <code>X509Certificate</code> must contain all or at least one of the + * specified subjectAlternativeNames, depending on the value of the + * matchAllNames flag (see {@link #setMatchAllSubjectAltNames}).<br /> + * <br /> + * 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.<br /> + * <br /> + * The <code>names</code> parameter (if not <code>null</code>) is a + * <code>Collection</code> with one entry for each name to be included in + * the subject alternative name criterion. Each entry is a <code>List</code> + * whose first entry is an <code>Integer</code> (the name type, 0-8) and + * whose second entry is a <code>String</code> 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</code> is supplied as the value + * for this argument, no subjectAlternativeNames check will be performed.<br /> + * <br /> + * Each subject alternative name in the <code>Collection</code> may be + * specified either as a <code>String</code> or as an ASN.1 encoded byte + * array. For more details about the formats used, see + * {@link #addSubjectAlternativeName(int, String) addSubjectAlternativeName(int type, String name)} + * and + * {@link #addSubjectAlternativeName(int, byte[]) addSubjectAlternativeName(int type, byte [] name}).<br /> + * <br /> + * Note that the <code>names</code> parameter can contain duplicate names + * (same name and name type), but they may be removed from the + * <code>Collection</code> of names returned by the + * {@link #getSubjectAlternativeNames} method.<br /> + * <br /> + * Note that a deep copy is performed on the Collection to protect against + * subsequent modifications. + * + * @param names - + * a Collection of names (or null) + * + * @exception IOException + * if a parsing error occurs + * + * @see #getSubjectAlternativeNames() + */ + public void setSubjectAlternativeNames(Collection names) throws IOException + { + try + { + if (names == null || names.isEmpty()) + { + subjectAltNames = null; + subjectAltNamesByte = null; + } + else + { + subjectAltNames = new HashSet(); + subjectAltNamesByte = new HashSet(); + Iterator iter = names.iterator(); + List item; + int type; + Object data; + while (iter.hasNext()) + { + item = (List)iter.next(); + type = ((Integer)item.get(0)).intValue(); + data = item.get(1); + if (data instanceof String) + { + addSubjectAlternativeName(type, (String)data); + } + else if (data instanceof byte[]) + { + addSubjectAlternativeName(type, (byte[])data); + } + else + { + throw new IOException( + "parsing error: unknown data type"); + } + } + } + } + catch (Exception ex) + { + throw new IOException("parsing exception:\n" + ex.toString()); + } + } + + /** + * Adds a name to the subjectAlternativeNames criterion. The + * <code>X509Certificate</code> must contain all or at least one of the + * specified subjectAlternativeNames, depending on the value of the + * matchAllNames flag (see {@link #setMatchAllSubjectAltNames}).<br /> + * <br /> + * 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.<br /> + * <br /> + * 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 2459). 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, byte[]) addSubjectAlternativeName(int type, byte [] name)} + * method. + * + * @param type + * the name type (0-8, as specified in RFC 2459, section 4.2.1.7) + * @param name - + * the name in string form (not null) + * + * @exception IOException + * if a parsing error occurs + */ + public void addSubjectAlternativeName(int type, String name) + throws IOException + { + // TODO full implementation of CertUtil.parseGeneralName + byte[] encoded = CertUtil.parseGeneralName(type, name); + List tmpList = new ArrayList(); + tmpList.add(Integers.valueOf(type)); + tmpList.add(name); + subjectAltNames.add(tmpList); + tmpList.set(1, encoded); + subjectAltNamesByte.add(tmpList); + } + + /** + * Adds a name to the subjectAlternativeNames criterion. The + * <code>X509Certificate</code> must contain all or at least one of the + * specified subjectAlternativeNames, depending on the value of the + * matchAllNames flag (see {@link #setMatchAllSubjectAltNames}).<br /> + * <br /> + * 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.<br /> + * <br /> + * 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 2459 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.<br /> + * <br /> + * + * <pre> + * 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> + * + * <br /> + * <br /> + * Note that the byte array supplied here is cloned to protect against + * subsequent modifications.<br /> + * <br /> + * <b>TODO: check encoded format</b> + * + * @param type + * the name type (0-8, as listed above) + * @param name + * a byte array containing the name in ASN.1 DER encoded form + * + * @exception IOException + * if a parsing error occurs + */ + public void addSubjectAlternativeName(int type, byte[] name) + throws IOException + { + // TODO check encoded format + List tmpList = new ArrayList(); + tmpList.add(Integers.valueOf(type)); + tmpList.add(name.clone()); + subjectAltNames.add(tmpList); + subjectAltNamesByte.add(tmpList); + } + + /** + * Sets the name constraints criterion. The <code>X509Certificate</code> + * must have subject and subject alternative names that meet the specified + * name constraints.<br /> + * <br /> + * 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 2459 and + * X.509. The ASN.1 definition of this structure appears below.<br /> + * <br /> + * + * <pre> + * 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> + * + * <br /> + * <br /> + * Note that the byte array supplied here is cloned to protect against + * subsequent modifications.<br /> + * <br /> + * <b>TODO: implement this</b> + * + * @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</code>, in + * which case no name constraints check will be performed + * + * @exception IOException + * if a parsing error occurs + * @exception UnsupportedOperationException + * because this method is not supported + * @see #getNameConstraints() + */ + public void setNameConstraints(byte[] bytes) throws IOException + { + throw new UnsupportedOperationException(); + } + + /** + * Sets the basic constraints constraint. If the value is greater than or + * equal to zero, <code>X509Certificates</code> 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.<br /> + * <br /> + * 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 + * + * @exception IllegalArgumentException + * if the value is less than -2 + * + * @see #getBasicConstraints() + */ + public void setBasicConstraints(int minMaxPathLen) + { + if (minMaxPathLen < -2) + { + throw new IllegalArgumentException("minMaxPathLen must be >= -2"); + } + + this.minMaxPathLen = minMaxPathLen; + } + + /** + * Sets the policy constraint. The X509Certificate must include at least one + * of the specified policies in its certificate policies extension. If + * certPolicySet is empty, then the X509Certificate must include at least + * some specified policy in its certificate policies extension. If + * certPolicySet is null, no policy check will be performed.<br /> + * <br /> + * Note that the Set is cloned to protect against subsequent modifications.<br /> + * <br /> + * <b>TODO: implement match check for this</b> + * + * @param certPolicySet + * a Set of certificate policy OIDs in string format (or null). + * Each OID is represented by a set of nonnegative integers + * separated by periods. + * + * @exception 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 certPolicySet) throws IOException + { + if (certPolicySet == null) + { + policy = null; + policyOID = null; + } + else + { + policyOID = new HashSet(); + Iterator iter = certPolicySet.iterator(); + Object item; + while (iter.hasNext()) + { + item = iter.next(); + if (item instanceof String) + { + CertUtil.parseOID((String)item); + policyOID.add(new ASN1ObjectIdentifier((String)item)); + } + else + { + throw new IOException( + "certPolicySet contains null values or non String objects"); + } + } + policy = new HashSet(certPolicySet); + } + } + + /** + * Sets the pathToNames criterion. The <code>X509Certificate</code> must + * not include name constraints that would prohibit building a path to the + * specified names.<br /> + * <br /> + * This method allows the caller to specify, with a single method call, the + * complete set of names which the <code>X509Certificates</code>'s name + * constraints must permit. The specified value replaces the previous value + * for the pathToNames criterion.<br /> + * <br /> + * 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.<br /> + * <br /> + * The names parameter (if not <code>null</code>) is a + * <code>Collection</code> with one entry for each name to be included in + * the pathToNames criterion. Each entry is a <code>List</code> whose + * first entry is an Integer (the name type, 0-8) and whose second entry is + * a <code>String</code> 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</code> is supplied as the value for this argument, + * no pathToNames check will be performed.<br /> + * <br /> + * Each name in the Collection may be specified either as a String or as an + * ASN.1 encoded byte array. For more details about the formats used, see + * {@link #addPathToName(int, String) addPathToName(int type, String name)} + * and + * {@link #addPathToName(int, byte[]) addPathToName(int type, byte [] name)}.<br /> + * <br /> + * Note that the names parameter can contain duplicate names (same name and + * name type), but they may be removed from the Collection of names returned + * by the {@link #getPathToNames} method.<br /> + * <br /> + * Note that a deep copy is performed on the Collection to protect against + * subsequent modifications.<br /> + * <br /> + * <b>TODO: implement this match check for this</b> + * + * @param names + * a Collection with one entry per name (or <code>null</code>) + * + * @exception IOException + * if a parsing error occurs + * @exception UnsupportedOperationException + * because this method is not supported + * + * @see #getPathToNames() + */ + public void setPathToNames(Collection names) throws IOException + { + try + { + if (names == null || names.isEmpty()) + { + pathToNames = null; + pathToNamesByte = null; + } + else + { + pathToNames = new HashSet(); + pathToNamesByte = new HashSet(); + Iterator iter = names.iterator(); + List item; + int type; + Object data; + + while (iter.hasNext()) + { + item = (List)iter.next(); + type = ((Integer)item.get(0)).intValue(); + data = item.get(1); + if (data instanceof String) + { + addPathToName(type, (String)data); + } + else if (data instanceof byte[]) + { + addPathToName(type, (byte[])data); + } + else + { + throw new IOException( + "parsing error: unknown data type"); + } + } + } + } + catch (Exception ex) + { + throw new IOException("parsing exception:\n" + ex.toString()); + } + } + + /** + * Adds a name to the pathToNames criterion. The + * <code>X509Certificate</code> must not include name constraints that + * would prohibit building a path to the specified name.<br /> + * <br /> + * This method allows the caller to add a name to the set of names which the + * <code>X509Certificates</code>'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.<br /> + * <br /> + * 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 2459). 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, byte[]) addPathToName(int type, byte [] name)} + * method.<br /> + * <br /> + * <b>TODO: implement this match check for this</b> + * + * @param type + * the name type (0-8, as specified in RFC 2459, section 4.2.1.7) + * @param name + * the name in string form + * + * @exceptrion IOException if a parsing error occurs + */ + public void addPathToName(int type, String name) throws IOException + { + // TODO full implementation of CertUtil.parseGeneralName + byte[] encoded = CertUtil.parseGeneralName(type, name); + List tmpList = new ArrayList(); + tmpList.add(Integers.valueOf(type)); + tmpList.add(name); + pathToNames.add(tmpList); + tmpList.set(1, encoded); + pathToNamesByte.add(tmpList); + throw new UnsupportedOperationException(); + } + + /** + * Adds a name to the pathToNames criterion. The + * <code>X509Certificate</code> must not include name constraints that + * would prohibit building a path to the specified name.<br /> + * <br /> + * This method allows the caller to add a name to the set of names which the + * <code>X509Certificates</code>'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.<br /> + * <br /> + * 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 2459 and X.509. The ASN.1 definition of this structure appears in + * the documentation for + * {@link #addSubjectAlternativeName(int,byte[]) addSubjectAlternativeName(int type, byte[] name)}.<br /> + * <br /> + * Note that the byte array supplied here is cloned to protect against + * subsequent modifications.<br /> + * <br /> + * <b>TODO: implement this match check for this</b> + * + * @param type + * the name type (0-8, as specified in RFC 2459, section 4.2.1.7) + * @param name + * a byte array containing the name in ASN.1 DER encoded form + * + * @exception IOException + * if a parsing error occurs + */ + public void addPathToName(int type, byte[] name) throws IOException + { + // TODO check encoded format + List tmpList = new ArrayList(); + tmpList.add(Integers.valueOf(type)); + tmpList.add(name.clone()); + pathToNames.add(tmpList); + pathToNamesByte.add(tmpList); + } + + /** + * Returns the certificateEquals criterion. The specified + * <code>X509Certificate</code> must be equal to the + * <code>X509Certificate</code> passed to the match method. If + * <code>null</code>, this check is not applied. + * + * @retrun the <code>X509Certificate</code> to match (or <code>null</code>) + * + * @see #setCertificate(java.security.cert.X509Certificate) + */ + public X509Certificate getCertificate() + { + return x509Cert; + } + + /** + * Returns the serialNumber criterion. The specified serial number must + * match the certificate serial number in the <code>X509Certificate</code>. + * If <code>null</code>, any certificate serial number will do. + * + * @return the certificate serial number to match (or <code>null</code>) + * + * @see #setSerialNumber(java.math.BigInteger) + */ + public BigInteger getSerialNumber() + { + return serialNumber; + } + + /** + * Returns the issuer criterion as a String. This distinguished name must + * match the issuer distinguished name in the <code>X509Certificate</code>. + * If <code>null</code>, the issuer criterion is disabled and any issuer + * distinguished name will do.<br /> + * <br /> + * If the value returned is not <code>null</code>, it is a distinguished + * name, in RFC 2253 format.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for formatiing + * byte[] issuerDN to String. + * + * @return the required issuer distinguished name in RFC 2253 format (or + * <code>null</code>) + */ + public String getIssuerAsString() + { + if (issuerDN instanceof String) + { + return new String((String)issuerDN); + } + else if (issuerDNX509 != null) + { + return issuerDNX509.toString(); + } + + return null; + } + + /** + * Returns the issuer criterion as a byte array. This distinguished name + * must match the issuer distinguished name in the + * <code>X509Certificate</code>. If <code>null</code>, the issuer + * criterion is disabled and any issuer distinguished name will do.<br /> + * <br /> + * If the value returned is not <code>null</code>, 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[]) setIssuer(byte [] issuerDN)}.<br /> + * <br /> + * Note that the byte array returned is cloned to protect against subsequent + * modifications.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name} to gnerate byte[] + * output for String issuerDN. + * + * @return a byte array containing the required issuer distinguished name in + * ASN.1 DER format (or <code>null</code>) + * + * @exception IOException + * if an encoding error occurs + */ + public byte[] getIssuerAsBytes() throws IOException + { + if (issuerDN instanceof byte[]) + { + return (byte[])((byte[])issuerDN).clone(); + } + else if (issuerDNX509 != null) + { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + + derOutStream.writeObject(issuerDNX509.toASN1Primitive()); + derOutStream.close(); + + return outStream.toByteArray(); + } + + return null; + } + + /** + * Returns the subject criterion as a String. This distinguished name must + * match the subject distinguished name in the <code>X509Certificate</code>. + * If <code>null</code>, the subject criterion is disabled and any + * subject distinguished name will do.<br /> + * <br /> + * If the value returned is not <code>null</code>, it is a distinguished + * name, in RFC 2253 format.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.x509.X509Name X509Name} for formatiing + * byte[] subjectDN to String. + * + * @return the required subject distinguished name in RFC 2253 format (or + * <code>null</code>) + */ + public String getSubjectAsString() + { + if (subjectDN instanceof String) + { + return new String((String)subjectDN); + } + else if (subjectDNX509 != null) + { + return subjectDNX509.toString(); + } + + return null; + } + + /** + * Returns the subject criterion as a byte array. This distinguished name + * must match the subject distinguished name in the + * <code>X509Certificate</code>. If <code>null</code>, the subject + * criterion is disabled and any subject distinguished name will do.<br /> + * <br /> + * If the value returned is not <code>null</code>, 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)}.<br /> + * <br /> + * Note that the byte array returned is cloned to protect against subsequent + * modifications.<br /> + * <br /> + * Uses {@link org.spongycastle.asn1.DEROutputStream DEROutputStream}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name} to gnerate byte[] + * output for String subjectDN. + * + * @return a byte array containing the required subject distinguished name + * in ASN.1 DER format (or <code>null</code>) + * + * @exception IOException + * if an encoding error occurs + */ + public byte[] getSubjectAsBytes() throws IOException + { + if (subjectDN instanceof byte[]) + { + return (byte[])((byte[])subjectDN).clone(); + } + else if (subjectDNX509 != null) + { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + DEROutputStream derOutStream = new DEROutputStream(outStream); + + derOutStream.writeObject(subjectDNX509.toASN1Primitive()); + derOutStream.close(); + + return outStream.toByteArray(); + } + + return null; + } + + /** + * Returns the subjectKeyIdentifier criterion. The + * <code>X509Certificate</code> must contain a SubjectKeyIdentifier + * extension with the specified value. If <code>null</code>, no + * subjectKeyIdentifier check will be done.<br /> + * <br /> + * Note that the byte array returned is cloned to protect against subsequent + * modifications. + * + * @return the key identifier (or <code>null</code>) + * + * @see #setSubjectKeyIdentifier + */ + public byte[] getSubjectKeyIdentifier() + { + if (subjectKeyID != null) + { + return (byte[])subjectKeyID.clone(); + } + + return null; + } + + /** + * Returns the authorityKeyIdentifier criterion. The + * <code>X509Certificate</code> must contain a AuthorityKeyIdentifier + * extension with the specified value. If <code>null</code>, no + * authorityKeyIdentifier check will be done.<br /> + * <br /> + * Note that the byte array returned is cloned to protect against subsequent + * modifications. + * + * @return the key identifier (or <code>null</code>) + * + * @see #setAuthorityKeyIdentifier + */ + public byte[] getAuthorityKeyIdentifier() + { + if (authorityKeyID != null) + { + return (byte[])authorityKeyID.clone(); + } + + return null; + } + + /** + * Returns the certificateValid criterion. The specified date must fall + * within the certificate validity period for the + * <code>X509Certificate</code>. If <code>null</code>, no + * certificateValid check will be done.<br /> + * <br /> + * Note that the <code>Date</code> returned is cloned to protect against + * subsequent modifications. + * + * @return the <code>Date</code> to check (or <code>null</code>) + * + * @see #setCertificateValid + */ + public Date getCertificateValid() + { + if (certValid != null) + { + return new Date(certValid.getTime()); + } + + return null; + } + + /** + * Returns the privateKeyValid criterion. The specified date must fall + * within the private key validity period for the + * <code>X509Certificate</code>. If <code>null</code>, no + * privateKeyValid check will be done.<br /> + * <br /> + * Note that the <code>Date</code> returned is cloned to protect against + * subsequent modifications. + * + * @return the <code>Date</code> to check (or <code>null</code>) + * + * @see #setPrivateKeyValid + */ + public Date getPrivateKeyValid() + { + if (privateKeyValid != null) + { + return new Date(privateKeyValid.getTime()); + } + + return null; + } + + /** + * Returns the subjectPublicKeyAlgID criterion. The + * <code>X509Certificate</code> must contain a subject public key with the + * specified algorithm. If <code>null</code>, no subjectPublicKeyAlgID + * check will be done. + * + * @return the object identifier (OID) of the signature algorithm to check + * for (or <code>null</code>). An OID is represented by a set of + * nonnegative integers separated by periods. + * + * @see #setSubjectPublicKeyAlgID + */ + public String getSubjectPublicKeyAlgID() + { + if (subjectKeyAlgID != null) + { + return subjectKeyAlgID.toString(); + } + + return null; + } + + /** + * Returns the subjectPublicKey criterion. The <code>X509Certificate</code> + * must contain the specified subject public key. If <code>null</code>, + * no subjectPublicKey check will be done. + * + * @return the subject public key to check for (or <code>null</code>) + * + * @see #setSubjectPublicKey + */ + public PublicKey getSubjectPublicKey() + { + return subjectPublicKey; + } + + /** + * Returns the keyUsage criterion. The <code>X509Certificate</code> must + * allow the specified keyUsage values. If null, no keyUsage check will be + * done.<br /> + * <br /> + * 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</code>. + * + * @see #setKeyUsage + */ + public boolean[] getKeyUsage() + { + if (keyUsage != null) + { + return (boolean[])keyUsage.clone(); + } + + return null; + } + + /** + * Returns the extendedKeyUsage criterion. The <code>X509Certificate</code> + * must allow the specified key purposes in its extended key usage + * extension. If the <code>keyPurposeSet</code> returned is empty or + * <code>null</code>, no extendedKeyUsage check will be done. Note that + * an <code>X509Certificate</code> that has no extendedKeyUsage extension + * implicitly allows all key purposes. + * + * @return an immutable <code>Set</code> of key purpose OIDs in string + * format (or <code>null</code>) + * @see #setExtendedKeyUsage + */ + public Set getExtendedKeyUsage() + { + if (keyPurposeSet == null || keyPurposeSet.isEmpty()) + { + return keyPurposeSet; + } + + Set returnSet = new HashSet(); + Iterator iter = keyPurposeSet.iterator(); + while (iter.hasNext()) + { + returnSet.add(iter.next().toString()); + } + + return Collections.unmodifiableSet(returnSet); + } + + /** + * Indicates if the <code>X509Certificate</code> must contain all or at + * least one of the subjectAlternativeNames specified in the + * {@link #setSubjectAlternativeNames setSubjectAlternativeNames} or + * {@link #addSubjectAlternativeName addSubjectAlternativeName} methods. If + * <code>true</code>, the <code>X509Certificate</code> must contain all + * of the specified subject alternative names. If <code>false</code>, the + * <code>X509Certificate</code> must contain at least one of the specified + * subject alternative names. + * + * @return <code>true</code> if the flag is enabled; <code>false</code> + * if the flag is disabled. The flag is <code>true</code> by + * default. + * + * @see #setMatchAllSubjectAltNames + */ + public boolean getMatchAllSubjectAltNames() + { + return matchAllSubjectAltNames; + } + + /** + * Returns a copy of the subjectAlternativeNames criterion. The + * <code>X509Certificate</code> 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</code>, + * no subjectAlternativeNames check will be performed.<br /> + * <br /> + * If the value returned is not <code>null</code>, it is a + * <code>Collection</code> with one entry for each name to be included in + * the subject alternative name criterion. Each entry is a <code>List</code> + * whose first entry is an <code>Integer</code> (the name type, 0-8) and + * whose second entry is a <code>String</code> 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</code> returned + * may contain duplicate names (same name and name type).<br /> + * <br /> + * Each subject alternative name in the <code>Collection</code> may be + * specified either as a <code>String</code> 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)}.<br /> + * <br /> + * Note that a deep copy is performed on the <code>Collection</code> to + * protect against subsequent modifications. + * + * @return a <code>Collection</code> of names (or <code>null</code>) + * + * @see #setSubjectAlternativeNames + */ + public Collection getSubjectAlternativeNames() + { + if (subjectAltNames != null) + { + return null; + } + + Set returnAltNames = new HashSet(); + List returnList; + Iterator iter = subjectAltNames.iterator(); + List obj; + while (iter.hasNext()) + { + obj = (List)iter.next(); + returnList = new ArrayList(); + returnList.add(obj.get(0)); + if (obj.get(1) instanceof byte[]) + { + returnList.add(((byte[])obj.get(1)).clone()); + } + else + { + returnList.add(obj.get(1)); + } + returnAltNames.add(returnList); + } + + return returnAltNames; + } + + /** + * Returns the name constraints criterion. The <code>X509Certificate</code> + * must have subject and subject alternative names that meet the specified + * name constraints.<br /> + * <br /> + * 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 2459 and X.509. + * The ASN.1 notation for this structure is supplied in the documentation + * for + * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.<br /> + * <br /> + * Note that the byte array returned is cloned to protect against subsequent + * modifications.<br /> + * <br /> + * <b>TODO: implement this</b> + * + * @return a byte array containing the ASN.1 DER encoding of a + * NameConstraints extension used for checking name constraints. + * <code>null</code> if no name constraints check will be + * performed. + * + * @exception UnsupportedOperationException + * because this method is not supported + * + * @see #setNameConstraints + */ + public byte[] getNameConstraints() + { + throw new UnsupportedOperationException(); + } + + /** + * Returns the basic constraints constraint. If the value is greater than or + * equal to zero, the <code>X509Certificates</code> 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 minMaxPathLen; + } + + /** + * Returns the policy criterion. The <code>X509Certificate</code> must + * include at least one of the specified policies in its certificate + * policies extension. If the <code>Set</code> returned is empty, then the + * <code>X509Certificate</code> must include at least some specified + * policy in its certificate policies extension. If the <code>Set</code> + * returned is <code>null</code>, no policy check will be performed. + * + * @return an immutable <code>Set</code> of certificate policy OIDs in + * string format (or <code>null</code>) + * + * @see #setPolicy + */ + public Set getPolicy() + { + if (policy == null) + { + return null; + } + + return Collections.unmodifiableSet(policy); + } + + /** + * Returns a copy of the pathToNames criterion. The + * <code>X509Certificate</code> must not include name constraints that + * would prohibit building a path to the specified names. If the value + * returned is <code>null</code>, no pathToNames check will be performed.<br /> + * <br /> + * If the value returned is not <code>null</code>, it is a + * <code>Collection</code> with one entry for each name to be included in + * the pathToNames criterion. Each entry is a <code>List</code> whose + * first entry is an <code>Integer</code> (the name type, 0-8) and whose + * second entry is a <code>String</code> 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</code> returned + * may contain duplicate names (same name and name type).<br /> + * <br /> + * Each name in the <code>Collection</code> may be specified either as a + * <code>String</code> 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)}.<br /> + * <br /> + * Note that a deep copy is performed on the <code>Collection</code> to + * protect against subsequent modifications. + * + * @return a <code>Collection</code> of names (or <code>null</code>) + * + * @see #setPathToNames + */ + public Collection getPathToNames() + { + if (pathToNames == null) + { + return null; + } + + Set returnPathToNames = new HashSet(); + List returnList; + Iterator iter = pathToNames.iterator(); + List obj; + + while (iter.hasNext()) + { + obj = (List)iter.next(); + returnList = new ArrayList(); + returnList.add(obj.get(0)); + if (obj.get(1) instanceof byte[]) + { + returnList.add(((byte[])obj.get(1)).clone()); + } + else + { + returnList.add(obj.get(1)); + } + returnPathToNames.add(returnList); + } + + return returnPathToNames; + } + + /** + * Return a printable representation of the <code>CertSelector</code>.<br /> + * <br /> + * <b>TODO: implement output for currently unsupported options(name + * constraints)</b><br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId} + * + * @return a <code>String</code> describing the contents of the + * <code>CertSelector</code> + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("X509CertSelector: [\n"); + if (x509Cert != null) + { + sb.append(" Certificate: ").append(x509Cert).append('\n'); + } + if (serialNumber != null) + { + sb.append(" Serial Number: ").append(serialNumber).append('\n'); + } + if (issuerDN != null) + { + sb.append(" Issuer: ").append(getIssuerAsString()).append('\n'); + } + if (subjectDN != null) + { + sb.append(" Subject: ").append(getSubjectAsString()).append('\n'); + } + try + { + if (subjectKeyID != null) + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + subjectKeyID); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object derObject = derInStream.readObject(); + sb.append(" Subject Key Identifier: ") + .append(ASN1Dump.dumpAsString(derObject)).append('\n'); + } + if (authorityKeyID != null) + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + authorityKeyID); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object derObject = derInStream.readObject(); + sb.append(" Authority Key Identifier: ") + .append(ASN1Dump.dumpAsString(derObject)).append('\n'); + } + } + catch (IOException ex) + { + sb.append(ex.getMessage()).append('\n'); + } + if (certValid != null) + { + sb.append(" Certificate Valid: ").append(certValid).append('\n'); + } + if (privateKeyValid != null) + { + sb.append(" Private Key Valid: ").append(privateKeyValid) + .append('\n'); + } + if (subjectKeyAlgID != null) + { + sb.append(" Subject Public Key AlgID: ") + .append(subjectKeyAlgID).append('\n'); + } + if (subjectPublicKey != null) + { + sb.append(" Subject Public Key: ").append(subjectPublicKey) + .append('\n'); + } + if (keyUsage != null) + { + sb.append(" Key Usage: ").append(keyUsage).append('\n'); + } + if (keyPurposeSet != null) + { + sb.append(" Extended Key Usage: ").append(keyPurposeSet) + .append('\n'); + } + if (policy != null) + { + sb.append(" Policy: ").append(policy).append('\n'); + } + sb.append(" matchAllSubjectAltNames flag: ") + .append(matchAllSubjectAltNames).append('\n'); + if (subjectAltNamesByte != null) + { + sb.append(" SubjectAlternativNames: \n["); + Iterator iter = subjectAltNamesByte.iterator(); + List obj; + try + { + while (iter.hasNext()) + { + obj = (List)iter.next(); + ByteArrayInputStream inStream = new ByteArrayInputStream( + (byte[])obj.get(1)); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object derObject = derInStream.readObject(); + sb.append(" Type: ").append(obj.get(0)).append(" Data: ") + .append(ASN1Dump.dumpAsString(derObject)).append('\n'); + } + } + catch (IOException ex) + { + sb.append(ex.getMessage()).append('\n'); + } + sb.append("]\n"); + } + if (pathToNamesByte != null) + { + sb.append(" PathToNamesNames: \n["); + Iterator iter = pathToNamesByte.iterator(); + List obj; + try + { + while (iter.hasNext()) + { + obj = (List)iter.next(); + ByteArrayInputStream inStream = new ByteArrayInputStream( + (byte[])obj.get(1)); + ASN1InputStream derInStream = new ASN1InputStream(inStream); + ASN1Object derObject = derInStream.readObject(); + sb.append(" Type: ").append(obj.get(0)).append(" Data: ") + .append(ASN1Dump.dumpAsString(derObject)).append('\n'); + } + } + catch (IOException ex) + { + sb.append(ex.getMessage()).append('\n'); + } + sb.append("]\n"); + } + sb.append(']'); + return sb.toString(); + } + + /** + * Decides whether a <code>Certificate</code> should be selected.<br /> + * <br /> + * <b>TODO: implement missing tests (name constraints and path to names)</b><br /> + * <br /> + * Uses {@link org.spongycastle.asn1.ASN1InputStream ASN1InputStream}, + * {@link org.spongycastle.asn1.ASN1Sequence ASN1Sequence}, + * {@link org.spongycastle.asn1.ASN1ObjectIdentifier ASN1ObjectIdentifier}, + * {@link org.spongycastle.asn1.ASN1Object ASN1Object}, + * {@link org.spongycastle.asn1.DERGeneralizedTime DERGeneralizedTime}, + * {@link org.spongycastle.asn1.x509.X509Name X509Name}, + * {@link org.spongycastle.asn1.x509.X509Extensions X509Extensions}, + * {@link org.spongycastle.asn1.x509.ExtendedKeyUsage ExtendedKeyUsage}, + * {@link org.spongycastle.asn1.x509.KeyPurposeId KeyPurposeId}, + * {@link org.spongycastle.asn1.x509.SubjectPublicKeyInfo SubjectPublicKeyInfo}, + * {@link org.spongycastle.asn1.x509.AlgorithmIdentifier AlgorithmIdentifier} + * to access X509 extensions + * + * @param cert + * the <code>Certificate</code> to be checked + * + * @return <code>true</code> if the <code>Certificate</code> should be + * selected, <code>false</code> otherwise + */ + public boolean match(Certificate cert) + { + boolean[] booleanArray; + List tempList; + Iterator tempIter; + + if (!(cert instanceof X509Certificate)) + { + return false; + } + X509Certificate certX509 = (X509Certificate)cert; + + if (x509Cert != null && !x509Cert.equals(certX509)) + { + return false; + } + if (serialNumber != null + && !serialNumber.equals(certX509.getSerialNumber())) + { + return false; + } + try + { + if (issuerDNX509 != null) + { + if (!issuerDNX509.equals(PrincipalUtil + .getIssuerX509Principal(certX509), true)) + { + return false; + } + } + if (subjectDNX509 != null) + { + if (!subjectDNX509.equals(PrincipalUtil + .getSubjectX509Principal(certX509), true)) + { + return false; + } + } + } + catch (Exception ex) + { + return false; + } + if (subjectKeyID != null) + { + byte[] data = certX509 + .getExtensionValue(X509Extensions.SubjectKeyIdentifier + .getId()); + if (data == null) + { + return false; + } + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + byte[] testData = ((ASN1OctetString)derInputStream.readObject()) + .getOctets(); + if (!Arrays.equals(subjectKeyID, testData)) + { + return false; + } + } + catch (IOException ex) + { + return false; + } + } + if (authorityKeyID != null) + { + byte[] data = certX509 + .getExtensionValue(X509Extensions.AuthorityKeyIdentifier + .getId()); + if (data == null) + { + return false; + } + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + byte[] testData = ((ASN1OctetString)derInputStream.readObject()) + .getOctets(); + if (!Arrays.equals(authorityKeyID, testData)) + { + return false; + } + } + catch (IOException ex) + { + return false; + } + } + if (certValid != null) + { + if (certX509.getNotAfter() != null + && certValid.after(certX509.getNotAfter())) + { + return false; + } + if (certX509.getNotBefore() != null + && certValid.before(certX509.getNotBefore())) + { + return false; + } + } + if (privateKeyValid != null) + { + try + { + byte[] data = certX509 + .getExtensionValue(X509Extensions.PrivateKeyUsagePeriod + .getId()); + if (data != null) + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + inStream = new ByteArrayInputStream( + ((ASN1OctetString)derInputStream.readObject()) + .getOctets()); + derInputStream = new ASN1InputStream(inStream); + // TODO fix this, Sequence contains tagged objects + ASN1Sequence derObject = (ASN1Sequence)derInputStream + .readObject(); + DERGeneralizedTime derDate = DERGeneralizedTime + .getInstance(derObject.getObjectAt(0)); + SimpleDateFormat dateF = new SimpleDateFormat( + "yyyyMMddHHmmssZ"); + if (privateKeyValid.before(dateF.parse(derDate.getTime()))) + { + return false; + } + derDate = DERGeneralizedTime.getInstance(derObject + .getObjectAt(1)); + if (privateKeyValid.after(dateF.parse(derDate.getTime()))) + { + return false; + } + } + } + catch (Exception ex) + { + return false; + } + } + if (subjectKeyAlgID != null) + { + try + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + certX509.getPublicKey().getEncoded()); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo( + (ASN1Sequence)derInputStream.readObject()); + AlgorithmIdentifier algInfo = publicKeyInfo.getAlgorithmId(); + if (!algInfo.getObjectId().equals(subjectKeyAlgID)) + { + return false; + } + } + catch (Exception ex) + { + return false; + } + } + if (subjectPublicKeyByte != null) + { + if (!Arrays.equals(subjectPublicKeyByte, certX509.getPublicKey() + .getEncoded())) + { + return false; + } + } + if (subjectPublicKey != null) + { + if (!subjectPublicKey.equals(certX509.getPublicKey())) + { + return false; + } + } + if (keyUsage != null) + { + booleanArray = certX509.getKeyUsage(); + if (booleanArray != null) + { + for (int i = 0; i < keyUsage.length; i++) + { + if (keyUsage[i] + && (booleanArray.length <= i || !booleanArray[i])) + { + return false; + } + } + } + } + if (keyPurposeSet != null && !keyPurposeSet.isEmpty()) + { + try + { + byte[] data = certX509 + .getExtensionValue(X509Extensions.ExtendedKeyUsage + .getId()); + if (data != null) + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + ExtendedKeyUsage extendedKeyUsage = ExtendedKeyUsage.getInstance( + (ASN1Sequence)derInputStream.readObject()); + tempIter = keyPurposeSet.iterator(); + while (tempIter.hasNext()) + { + if (!extendedKeyUsage + .hasKeyPurposeId((KeyPurposeId)tempIter.next())) + { + return false; + } + } + } + } + catch (Exception ex) + { + return false; + } + } + if (minMaxPathLen != -1) + { + if (minMaxPathLen == -2 && certX509.getBasicConstraints() != -1) + { + return false; + } + if (minMaxPathLen >= 0 + && certX509.getBasicConstraints() < minMaxPathLen) + { + return false; + } + } + if (policyOID != null) + { + try + { + byte[] data = certX509 + .getExtensionValue(X509Extensions.CertificatePolicies + .getId()); + if (data == null) + { + return false; + } + if (!policyOID.isEmpty()) + { + ByteArrayInputStream inStream = new ByteArrayInputStream( + data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + inStream = new ByteArrayInputStream( + ((ASN1OctetString)derInputStream.readObject()) + .getOctets()); + derInputStream = new ASN1InputStream(inStream); + Enumeration policySequence = ((ASN1Sequence)derInputStream + .readObject()).getObjects(); + ASN1Sequence policyObject; + boolean test = false; + while (policySequence.hasMoreElements() && !test) + { + policyObject = (ASN1Sequence)policySequence + .nextElement(); + if (policyOID.contains(policyObject.getObjectAt(0))) + { + test = true; + } + } + if (!test) + { + return false; + } + } + } + catch (Exception ex) + { + ex.printStackTrace(); + return false; + } + } + if (subjectAltNamesByte != null) + { + try + { + byte[] data = certX509 + .getExtensionValue(X509Extensions.SubjectAlternativeName + .getId()); + if (data == null) + { + return false; + } + ByteArrayInputStream inStream = new ByteArrayInputStream(data); + ASN1InputStream derInputStream = new ASN1InputStream(inStream); + inStream = new ByteArrayInputStream( + ((ASN1OctetString)derInputStream.readObject()) + .getOctets()); + derInputStream = new ASN1InputStream(inStream); + Enumeration altNamesSequence = ((ASN1Sequence)derInputStream + .readObject()).getObjects(); + ASN1TaggedObject altNameObject; + boolean test = false; + Set testSet = new HashSet(subjectAltNamesByte); + List testList; + ASN1Object derData; + ByteArrayOutputStream outStream; + DEROutputStream derOutStream; + while (altNamesSequence.hasMoreElements() && !test) + { + altNameObject = (ASN1TaggedObject)altNamesSequence + .nextElement(); + testList = new ArrayList(2); + testList.add(Integers.valueOf(altNameObject.getTagNo())); + derData = altNameObject.getObject(); + outStream = new ByteArrayOutputStream(); + derOutStream = new DEROutputStream(outStream); + derOutStream.writeObject(derData); + derOutStream.close(); + testList.add(outStream.toByteArray()); + + if (testSet.remove(testList)) + { + test = true; + } + + if (matchAllSubjectAltNames && !testSet.isEmpty()) + { + test = false; + } + } + if (!test) + { + return false; + } + } + catch (Exception ex) + { + ex.printStackTrace(); + return false; + } + } + + return true; + } + + /** + * Returns a copy of this object. + * + * @return the copy + */ + public Object clone() + { + try + { + X509CertSelector copy = (X509CertSelector)super.clone(); + if (issuerDN instanceof byte[]) + { + copy.issuerDN = ((byte[])issuerDN).clone(); + } + if (subjectDN instanceof byte[]) + { + copy.subjectDN = ((byte[])subjectDN).clone(); + } + if (subjectKeyID != null) + { + copy.subjectKeyID = (byte[])subjectKeyID.clone(); + } + if (authorityKeyID != null) + { + copy.authorityKeyID = (byte[])authorityKeyID.clone(); + } + if (subjectPublicKeyByte != null) + { + copy.subjectPublicKeyByte = (byte[])subjectPublicKeyByte + .clone(); + } + if (keyUsage != null) + { + copy.keyUsage = (boolean[])keyUsage.clone(); + } + if (keyPurposeSet != null) + { + copy.keyPurposeSet = new HashSet(keyPurposeSet); + } + if (policy != null) + { + copy.policy = new HashSet(policy); + copy.policyOID = new HashSet(); + Iterator iter = policyOID.iterator(); + while (iter.hasNext()) + { + copy.policyOID.add(new ASN1ObjectIdentifier( + ((ASN1ObjectIdentifier)iter.next()).getId())); + } + } + if (subjectAltNames != null) + { + copy.subjectAltNames = new HashSet(getSubjectAlternativeNames()); + Iterator iter = subjectAltNamesByte.iterator(); + List obj; + List cloneObj; + while (iter.hasNext()) + { + obj = (List)iter.next(); + cloneObj = new ArrayList(); + cloneObj.add(obj.get(0)); + cloneObj.add(((byte[])obj.get(1)).clone()); + copy.subjectAltNamesByte.add(cloneObj); + } + } + if (pathToNames != null) + { + copy.pathToNames = new HashSet(getPathToNames()); + Iterator iter = pathToNamesByte.iterator(); + List obj; + List cloneObj; + while (iter.hasNext()) + { + obj = (List)iter.next(); + cloneObj = new ArrayList(); + cloneObj.add(obj.get(0)); + cloneObj.add(((byte[])obj.get(1)).clone()); + copy.pathToNamesByte.add(cloneObj); + } + } + return copy; + } + catch (CloneNotSupportedException e) + { + /* Cannot happen */ + throw new InternalError(e.toString()); + } + } +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java new file mode 100644 index 000000000..d56f1c6f3 --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Certificate.java @@ -0,0 +1,33 @@ + +package java.security.cert; + +import java.math.BigInteger; +import java.security.Principal; +import java.util.Date; + +public abstract class X509Certificate extends Certificate +implements X509Extension +{ + protected X509Certificate() + { + super("X.509"); + } + + public abstract void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException; + public abstract void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException; + public abstract int getBasicConstraints(); + public abstract Principal getIssuerDN(); + public abstract boolean[] getIssuerUniqueID(); + public abstract boolean[] getKeyUsage(); + public abstract Date getNotAfter(); + public abstract Date getNotBefore(); + public abstract BigInteger getSerialNumber(); + public abstract String getSigAlgName(); + public abstract String getSigAlgOID(); + public abstract byte[] getSigAlgParams(); + public abstract byte[] getSignature(); + public abstract Principal getSubjectDN(); + public abstract boolean[] getSubjectUniqueID(); + public abstract byte[] getTBSCertificate() throws CertificateEncodingException; + public abstract int getVersion(); +} diff --git a/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java new file mode 100644 index 000000000..20855be1e --- /dev/null +++ b/libraries/spongycastle/core/src/main/jdk1.1/java/security/cert/X509Extension.java @@ -0,0 +1,12 @@ + +package java.security.cert; + +import java.util.Set; + +public interface X509Extension +{ + public abstract Set getCriticalExtensionOIDs(); + public abstract byte[] getExtensionValue(String oid); + public abstract Set getNonCriticalExtensionOIDs(); + public abstract boolean hasUnsupportedCriticalExtension(); +} |